Created
March 16, 2016 23:11
-
-
Save ajweeks/781eb49186e51ac71d62 to your computer and use it in GitHub Desktop.
2D Matrix Magic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//----------------------------------------------------------------- | |
// Base code by Thomas Kole | |
// http://www.thomaskole.com | |
//----------------------------------------------------------------- | |
#include "IsoScene.h" | |
#define GAME_ENGINE (GameEngine::GetSingleton()) | |
void IsoScene::GameStart() | |
{ | |
m_BmpGroundPtr = new Bitmap(String("Bitmaps/ground.png")); | |
m_BmpTreePtr = new Bitmap(String("Bitmaps/palm.png")); | |
m_BmpTreeShadowPtr = new Bitmap(String("Bitmaps/palm_shadow.png")); | |
m_BmpCharacterPtr = new Bitmap(String("Bitmaps/vaas.png")); | |
m_BmpCharacterShadowPtr = new Bitmap(String("Bitmaps/vaas_shadow.png")); | |
GenerateTrees(); | |
m_playerPos = DOUBLE2(512, 512); | |
} | |
void IsoScene::GenerateTrees() | |
{ | |
m_TreeArr = std::vector<DOUBLE2>(); // Clear th vector | |
for (size_t i = 0; i < 40; i++) | |
{ | |
DOUBLE2 pos; | |
do | |
{ | |
pos.x = rand() % 800 + 100; | |
pos.y = rand() % 800 + 100; | |
} while (IsCloseToTree(pos)); | |
m_TreeArr.push_back(pos); | |
} | |
} | |
bool IsoScene::IsCloseToTree(const DOUBLE2& posRef) | |
{ | |
double closeRadius = 60; | |
for (size_t i = 0; i < m_TreeArr.size(); ++i) | |
{ | |
if ((posRef.x > m_TreeArr[i].x - closeRadius && posRef.x < m_TreeArr[i].x + closeRadius && | |
posRef.y > m_TreeArr[i].y - closeRadius && posRef.y < m_TreeArr[i].y + closeRadius) || | |
(posRef.x > m_playerPos.x - closeRadius && posRef.x < m_playerPos.x + closeRadius && | |
posRef.y > m_playerPos.y - closeRadius && posRef.y < m_playerPos.y + closeRadius)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
void IsoScene::GameEnd() | |
{ | |
delete m_BmpGroundPtr; | |
delete m_BmpTreePtr; | |
delete m_BmpTreeShadowPtr; | |
delete m_BmpCharacterShadowPtr; | |
delete m_BmpCharacterPtr; | |
} | |
bool sortTrees(DOUBLE2 i, DOUBLE2 j) | |
{ | |
return (i.y < j.y); | |
} | |
void sortVector(std::vector<DOUBLE2> & inputVector) | |
{ | |
// for the curious: | |
// we put the vector in the std::sort method. | |
// this method requires #include <algorithm> | |
// this method asks for the beginning of the vector, and the end. | |
// and then it ask for a method, which takes 2 of the vector's types. | |
// in our case DOUBLE2's. | |
// I called this method sortTrees, and you can find it above this method. | |
// all it does is return a Bool that says if the first item is smaller than the second item. | |
std::sort(inputVector.begin(), inputVector.end(), sortTrees); | |
} | |
void IsoScene::GameTick(double deltaTime) | |
{ | |
//all the key inputs, not that exciting. | |
if (GAME_ENGINE->IsKeyboardKeyDown(VK_RIGHT)) | |
m_CamAngle += deltaTime; | |
if (GAME_ENGINE->IsKeyboardKeyDown(VK_LEFT)) | |
m_CamAngle -= deltaTime; | |
if (GAME_ENGINE->IsKeyboardKeyDown(VK_UP)) | |
m_TopDownFactor += deltaTime; | |
if (GAME_ENGINE->IsKeyboardKeyDown(VK_DOWN)) | |
m_TopDownFactor -= deltaTime; | |
if (m_CamAngle < 0) | |
m_CamAngle += M_PI * 2; | |
if (m_CamAngle > (M_PI * 2)) | |
m_CamAngle -= M_PI * 2; | |
if (m_TopDownFactor < 0.1) | |
m_TopDownFactor = 0.1; | |
if (m_TopDownFactor > 0.8) | |
m_TopDownFactor = 0.8; | |
double walkingSpeed = 120; | |
if (GAME_ENGINE->IsKeyboardKeyDown(VK_SHIFT)) | |
walkingSpeed *= 1.8; | |
DOUBLE2 prevPlayerPos = m_playerPos; | |
if (GAME_ENGINE->IsKeyboardKeyDown('W')) | |
{ | |
m_playerPos.x += deltaTime * walkingSpeed * cos(m_CamAngle + M_PI / 2.0); | |
m_playerPos.y -= deltaTime * walkingSpeed * sin(m_CamAngle + M_PI / 2.0); | |
} | |
if (GAME_ENGINE->IsKeyboardKeyDown('S')) | |
{ | |
m_playerPos.x -= deltaTime * walkingSpeed * cos(m_CamAngle + M_PI / 2.0); | |
m_playerPos.y += deltaTime * walkingSpeed * sin(m_CamAngle + M_PI / 2.0); | |
} | |
if (GAME_ENGINE->IsKeyboardKeyDown('D')) | |
{ | |
m_playerPos.x += deltaTime * walkingSpeed * cos(m_CamAngle); | |
m_playerPos.y -= deltaTime * walkingSpeed * sin(m_CamAngle); | |
} | |
if (GAME_ENGINE->IsKeyboardKeyDown('A')) | |
{ | |
m_playerPos.x -= deltaTime * walkingSpeed * cos(m_CamAngle); | |
m_playerPos.y += deltaTime * walkingSpeed * sin(m_CamAngle); | |
} | |
m_playerPos = CheckCollisions(prevPlayerPos); | |
if (GAME_ENGINE->IsKeyboardKeyDown('Q')) | |
m_SunAngle -= deltaTime * 0.5; | |
if (GAME_ENGINE->IsKeyboardKeyDown('E')) | |
m_SunAngle += deltaTime * 0.5; | |
if (GAME_ENGINE->IsKeyboardKeyDown('Z')) | |
m_SunHeight -= deltaTime * 0.5; | |
if (GAME_ENGINE->IsKeyboardKeyDown('C')) | |
m_SunHeight += deltaTime * 0.5; | |
if (GAME_ENGINE->IsKeyboardKeyDown('O')) | |
m_CameraZoom -= deltaTime * 0.5; | |
if (GAME_ENGINE->IsKeyboardKeyDown('P')) | |
m_CameraZoom += deltaTime * 0.5; | |
if (GAME_ENGINE->IsKeyboardKeyPressed('R')) | |
GenerateTrees(); | |
} | |
DOUBLE2 IsoScene::CheckCollisions(DOUBLE2 prevPlayerPos) | |
{ | |
double trunkRadius = 12; | |
DOUBLE2 result = m_playerPos; | |
for (size_t i = 0; i < m_TreeArr.size(); ++i) | |
{ | |
bool collidesX = (m_playerPos.x > m_TreeArr[i].x - trunkRadius && m_playerPos.x < m_TreeArr[i].x + trunkRadius); | |
bool collidesY = (m_playerPos.y > m_TreeArr[i].y - trunkRadius && m_playerPos.y < m_TreeArr[i].y + trunkRadius); | |
if (collidesX && collidesY) | |
{ | |
if (prevPlayerPos.x > m_TreeArr[i].x - trunkRadius && prevPlayerPos.x < m_TreeArr[i].x + trunkRadius) | |
{ | |
result.y = prevPlayerPos.y; | |
} | |
else | |
{ | |
result.x = prevPlayerPos.x; | |
} | |
} | |
} | |
return result; | |
} | |
void IsoScene::GamePaint() | |
{ | |
// An island isn't complete without a sea! | |
GAME_ENGINE->DrawSolidBackground(COLOR(10, 100, 200)); | |
// SETUP CAMERA MATRIX | |
MATRIX3X2 matCameraPosition = MATRIX3X2::CreateTranslationMatrix(-m_playerPos); | |
MATRIX3X2 matCameraPivot = MATRIX3X2::CreateTranslationMatrix(GAME_ENGINE->GetWidth()/2, | |
GAME_ENGINE->GetHeight()/2); | |
MATRIX3X2 matCameraRotate = MATRIX3X2::CreateRotationMatrix(m_CamAngle); | |
MATRIX3X2 matCameraScale = MATRIX3X2::CreateScalingMatrix(1, m_TopDownFactor); | |
MATRIX3X2 matCameraZoom = MATRIX3X2::CreateScalingMatrix(m_CameraZoom, m_CameraZoom); | |
MATRIX3X2 matCameraTotal = matCameraPosition * matCameraRotate * matCameraScale * matCameraZoom * matCameraPivot; | |
GAME_ENGINE->SetViewMatrix(matCameraTotal); | |
// DRAW GROUND | |
GAME_ENGINE->DrawBitmap(m_BmpGroundPtr); | |
// DRAW TREE SHADOWS | |
for (size_t i = 0; i < m_TreeArr.size(); ++i) | |
{ | |
MATRIX3X2 matTreeShadowPivot = MATRIX3X2::CreateTranslationMatrix(DOUBLE2(-30, -100)); | |
MATRIX3X2 matTreeShadowScale = MATRIX3X2::CreateScalingMatrix(1, m_SunHeight); | |
MATRIX3X2 matTreeShadowRotation = MATRIX3X2::CreateRotationMatrix(m_SunAngle); | |
MATRIX3X2 matTreeShadowTranslation = MATRIX3X2::CreateTranslationMatrix(m_TreeArr[i]); | |
GAME_ENGINE->SetViewMatrix(matTreeShadowPivot * matTreeShadowScale * matTreeShadowRotation * | |
matTreeShadowTranslation * matCameraTotal); | |
GAME_ENGINE->DrawBitmap(m_BmpTreeShadowPtr); | |
} | |
// DRAW PLAYER SHADOW | |
MATRIX3X2 matPlayerShadowPivot = MATRIX3X2::CreateTranslationMatrix(DOUBLE2(-15, -60)); | |
MATRIX3X2 matPlayerShadowRotation = MATRIX3X2::CreateRotationMatrix(m_SunAngle); | |
MATRIX3X2 matPlayerShadowTranslation = MATRIX3X2::CreateTranslationMatrix(m_playerPos); | |
GAME_ENGINE->SetViewMatrix(matPlayerShadowPivot * matPlayerShadowRotation * matPlayerShadowTranslation * matCameraTotal); | |
GAME_ENGINE->DrawBitmap(m_BmpCharacterShadowPtr); | |
DOUBLE2 vecPlayerPositionTransformed; | |
vecPlayerPositionTransformed = matCameraTotal.TransformPoint(m_playerPos); | |
// DRAW BACK TREES | |
std::vector<DOUBLE2> transformedTreeArr; | |
for (size_t i = 0; i < m_TreeArr.size(); ++i) | |
{ | |
DOUBLE2 vecTransformedTreePos; | |
vecTransformedTreePos = matCameraTotal.TransformPoint(m_TreeArr[i]); | |
transformedTreeArr.push_back(vecTransformedTreePos); | |
} | |
sortVector(transformedTreeArr); | |
double xScale = cos(m_CamAngle); | |
MATRIX3X2 matSideScale = MATRIX3X2::CreateScalingMatrix(xScale, 1); | |
int lastTreeDrawnIndex = 0; | |
for (size_t i = 0; i < transformedTreeArr.size(); ++i) | |
{ | |
if (transformedTreeArr[i].y >= vecPlayerPositionTransformed.y) | |
{ | |
lastTreeDrawnIndex = i; | |
break; | |
} | |
MATRIX3X2 matTreePivot = MATRIX3X2::CreateTranslationMatrix(DOUBLE2(-30, -100)); | |
MATRIX3X2 matTreeTranslation = MATRIX3X2::CreateTranslationMatrix(transformedTreeArr[i]); | |
GAME_ENGINE->SetViewMatrix(matTreePivot * matCameraZoom * matSideScale * matTreeTranslation); | |
GAME_ENGINE->DrawBitmap(m_BmpTreePtr); | |
} | |
// DRAW PLAYER | |
MATRIX3X2 matPlayerPivot = MATRIX3X2::CreateTranslationMatrix(DOUBLE2(-15, -60)); | |
MATRIX3X2 matPlayerTranslation = MATRIX3X2::CreateTranslationMatrix(vecPlayerPositionTransformed); | |
GAME_ENGINE->SetViewMatrix(matPlayerPivot * matCameraZoom * matSideScale * matPlayerTranslation); | |
GAME_ENGINE->DrawBitmap(m_BmpCharacterPtr); | |
// DRAW FRONT TREES | |
MATRIX3X2 matTreePivot = MATRIX3X2::CreateTranslationMatrix(DOUBLE2(-30, -100)); | |
for (size_t i = lastTreeDrawnIndex; i < transformedTreeArr.size(); ++i) | |
{ | |
MATRIX3X2 matTreeTranslation = MATRIX3X2::CreateTranslationMatrix(transformedTreeArr[i]); | |
GAME_ENGINE->SetViewMatrix(matTreePivot * matCameraZoom * matSideScale * matTreeTranslation); | |
GAME_ENGINE->DrawBitmap(m_BmpTreePtr); | |
} | |
DOUBLE2 xAxis = DOUBLE2(cos(m_CamAngle), sin(m_CamAngle) * m_TopDownFactor); | |
DOUBLE2 yAxis = DOUBLE2(0, 1); | |
MATRIX3X2 matTextBoxSkewing = MATRIX3X2(xAxis, yAxis); | |
GAME_ENGINE->SetViewMatrix(matPlayerPivot * matCameraZoom * matTextBoxSkewing * matPlayerTranslation); | |
GAME_ENGINE->SetColor(COLOR(0, 0, 0, 120)); | |
GAME_ENGINE->FillRect(-145, -100, 145, -50); | |
GAME_ENGINE->SetColor(COLOR(240, 240, 240)); | |
GAME_ENGINE->DrawString(String("WASD TO MOVE VAAS, ARROWS TO ROTATE CAMERA\n" | |
" Q E Z C TO MOVE THE SUN, O P TO ZOOM\n SHIFT TO SPRINT, R TO REGENERATE TREES"), -138, -95); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
class IsoScene : public AbstractGame | |
{ | |
public: | |
virtual void GameInitialize(GameSettings &gameSettingsRef); | |
virtual void GameStart(); | |
virtual void GameEnd(); | |
virtual void GameTick(double deltaTime); | |
virtual void GamePaint(); | |
private: | |
/* Returns whether or not the player collided with any trees */ | |
DOUBLE2 CheckCollisions(DOUBLE2 prevPlayerPos); | |
void GenerateTrees(); | |
bool IsCloseToTree(const DOUBLE2& posRef); | |
DOUBLE2 m_playerPos; | |
double m_CamAngle, m_TopDownFactor = 0.5; | |
double m_SunAngle = 0; | |
double m_SunHeight = 1; | |
double m_CameraZoom = 1; | |
std::vector<DOUBLE2> m_TreeArr; | |
Bitmap * m_BmpTreePtr, * m_BmpTreeShadowPtr , *m_BmpGroundPtr, *m_BmpCharacterPtr, *m_BmpCharacterShadowPtr; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment