2D Objects with SDL(SuperMario)
Character Source
#include "Character.h"
#include "Texture2D.h"
#include "GameScreenLevel1.h"
Character::Character(SDL_Renderer* renderer, string imagePath, Vector2D startPosition, LevelMap* map, FACING startFacing, float movementSpeed)
{
mRenderer = renderer;
mTexture = new Texture2D(renderer);
mTexture->LoadFromFile(imagePath);
mCollisionRadius = 15.0f;
mPosition = startPosition;
mCurrentLevelMap = map;
mMovingLeft = false;
mMovingRight = false;
mJump = false;
}
Character::~Character()
{
}
//-----------------------------------------------------------------------------------------
void Character::Render()
{
if(mFacingDirection == FACING_RIGHT)
{
mTexture->Render(mPosition, SDL_FLIP_NONE);
}
else
{
mTexture->Render(mPosition, SDL_FLIP_HORIZONTAL);
}
}
//------------------------------------------------------------------------------------------
void Character::Update(float deltaTime, SDL_Event e)
{
int centralXPosition = (int)(mPosition.x+(mTexture->GetWidht()*0.5)) / TILE_WIDTH;
int centralYPosition = (int)(mPosition.y+(mTexture->GetHeight()*0.5))/ TILE_WIDTH;
int footPosition = (int)(mPosition.y+mTexture->GetHeight())/ TILE_WIDTH;
int leftPosition = (int)mPosition.x/ TILE_WIDTH;
int rightPosition = (int)(mPosition.x+mTexture->GetWidht())/ TILE_WIDTH;
if(mCurrentLevelMap->GetTileAt(footPosition,centralXPosition) == 0)
{
AddGravity(deltaTime);
}
if(mMovingLeft)
{
MoveLeft(deltaTime, centralYPosition);
mFacingDirection = FACING_LEFT;
}
else if(mMovingRight)
{
MoveRight(deltaTime, centralYPosition);
mFacingDirection = FACING_RIGHT;
}
else if(mJump)
{
Jump(deltaTime, centralXPosition);
}
if(mCurrentLevelMap->GetTileAt(centralYPosition,leftPosition) == 1)
{
mMovingLeft = false;
mMovingRight = true;
}
else if(mCurrentLevelMap->GetTileAt(centralYPosition,rightPosition) == 1)
{
mMovingLeft = true;
mMovingRight = false;
}
//arrow commands
switch(e.type)
{
case SDL_KEYDOWN:
switch(e.key.keysym.sym)
{
case SDLK_LEFT:
mMovingLeft = true;
mMovingRight = false;
mJump = false;
break;
case SDLK_RIGHT:
mMovingRight = true;
mMovingLeft = false;
mJump = false;
break;
case SDLK_UP:
mJump = true;
break;
}
break;
case SDL_KEYUP:
switch(e.key.keysym.sym)
{
case SDLK_LEFT:
case SDLK_RIGHT:
case SDLK_UP:
mMovingLeft = false;
mMovingRight = false;
mJump = false;
break;
}
break;
}
return;
}
//------------------------------------------------------------------------------------------
void Character::SetPosition(Vector2D newPosition)
{
}
//------------------------------------------------------------------------------------------
Vector2D Character::GetPosition()
{
return mPosition;
}
//-------------------------------------------------------------------------------------------
void Character::SetCurrentLevelMap(LevelMap* map)
{
mCurrentLevelMap = map;
}
//-------------------------------------------------------------------------------------------
void Character::SetState(CHARACTER_STATE newState)
{
mState = newState;
}
void Character::MoveLeft(float deltaTime, int centralYPosition)
{
mPosition.x -= 0.01f;
}
void Character::MoveRight(float deltaTime,int centralYPosition)
{
mPosition.x += 0.01f;
}
void Character::Jump(float deltaTime, int centralXPosition)
{
mPosition.y -=0.03f;
}
void Character::AddGravity(float deltaTime)
{
mPosition.y += 0.005f;
}
Main Character Source
#include "CharacterMario.h"
#include "Constants.h"
#include "Commons.h"
CharacterMario::CharacterMario(SDL_Renderer* renderer, string imagePath, LevelMap* map, Vector2D startPosition, FACING startFacing, float movementSpeed)
: Character(renderer, imagePath, startPosition, map, startFacing, movementSpeed)
{
}
//---------------------------------------------------------------------------------------------------------------------
CharacterMario::~CharacterMario()
{
}
//---------------------------------------------------------------------------------------------------------------------
void CharacterMario::Render()
{
Character::Render();
if(IsInState(CHARACTERSTATE_PLAYER_DEATH))
{
//Spin if in Death state
mTexture->Render(mPosition, SDL_FLIP_NONE, mAngle);
}
else
{
//Parent can deal with any other style renders
Character::Render();
}
}
//---------------------------------------------------------------------------------------------------------------------
void CharacterMario::Update(float deltaTime, SDL_Event e)
{
if (IsInState(CHARACTERSTATE_PLAYER_DEATH))
{
//Be dead for as long as necessary
mDeadTime += 0.05f;
//Increment angle for the spin effect
mAngle += 0.05f;
if(mDeadTime > DEAD_TIME)
{
SetState(CHARACTERSTATE_PLAYER_NONE);
}
}
else
{
Character::Update(deltaTime, e);
}
}
//---------------------------------------------------------------------------------------------------------------------
void CharacterMario::SetState(CHARACTER_STATE newState)
{
mState = newState;
switch(mState)
{
case CHARACTERSTATE_PLAYER_NONE:
mMovementSpeed = MOVE_SPEED;
break;
case CHARACTERSTATE_PLAYER_DEATH:
//Stop moving
mMovementSpeed = 0.0f;
//Stop movement
mMovingLeft = false;
mMovingRight = false;
//Initialise the time we are dead
mDeadTime = 0.05f;
break;
}
if(CHARACTERSTATE_PLAYER_DEATH)
{
mtotalLife -= 1;
}
if(mtotalLife == 0)
{
CHARACTERSTATE_GAME_OVER;
CHARACTERSTATE_ENEMY_GAME_OVER;
}
else if(mtotalLife != 0)
{
}
}
Level Map Source
#include "LevelMap.h"
LevelMap::LevelMap(int map[WORLD_HEIGHT][WORLD_WIDTH])
{
//Allocate memory for the level map
mMap = new int*[WORLD_HEIGHT];
for(unsigned int i = 0; i < WORLD_HEIGHT; i++)
{
mMap[i] = new int[WORLD_HEIGHT];
}
//Populate the array
for(unsigned int i = 0; i < WORLD_HEIGHT; i++)
{
for(unsigned int j = 0; j < WORLD_WIDTH; j++)
{
mMap[i][j] = map[i][j];
}
}
}
LevelMap::~LevelMap()
{
//Delete all elements of the array
for(unsigned int i = 0; i < WORLD_HEIGHT; i++)
{
delete [] mMap[i];
}
delete [] mMap;
}
int LevelMap::GetTileAt(unsigned int h, unsigned int w)
{
if(h < WORLD_HEIGHT && w < WORLD_WIDTH)
{
return mMap [h][w];
}
return 0;
}
Game Level Source
#include "GameScreenLevel1.h"
#include "CharacterFireBall.h"
#include <iostream>
#include "Collisions.h"
using namespace std;
GameScreenLevel1::GameScreenLevel1(SDL_Renderer* renderer) : GameScreen(renderer)
{
srand(NULL);
mLevelMap = NULL;
SetUpLevel();
}
GameScreenLevel1::~GameScreenLevel1()
{
mEnemies.clear();
mCoinMove.clear();
mBalls.clear();
mCoin.clear();
}
//----------------------------------------------------------------------------------------
bool GameScreenLevel1::SetUpLevel()
{
//Create the level map
SetLevelMap();
//Set up the player character
mCharacterMario = new CharacterMario(mRenderer, "Image/Mario.png", mLevelMap, Vector2D(64,32), FACING_RIGHT, 10);
CreateEnemy1(Vector2D(150,100), FACING_RIGHT, ENEMY_SPEED1, BADDIE_NORMAL);
CreateEnemy2(Vector2D(200,130), FACING_RIGHT, ENEMY_SPEED1, BADDIE_NORMAL);
CreateEnemy3(Vector2D(230,115), FACING_RIGHT, ENEMY_SPEED1, BADDIE_NORMAL);
CreateEnemy4(Vector2D(150,102), FACING_RIGHT, ENEMY_SPEED1, BADDIE_NORMAL);
CreateEnemy5(Vector2D(110,102), FACING_RIGHT, ENEMY_SPEED1, BADDIE_NORMAL);
CreateCoin1(Vector2D(180,102), FACING_RIGHT, COIN_SPEED, COIN_GOLD);
CreateCoin2(Vector2D(180,102), FACING_RIGHT, COIN_SPEED, COIN_GOLD);
CreateCoin3(Vector2D(180,102), FACING_RIGHT, COIN_SPEED, COIN_GOLD);
CreateCoin4(Vector2D(180,102), FACING_RIGHT, COIN_SPEED, COIN_GOLD);
CreateCoin5(Vector2D(180,102), FACING_RIGHT, COIN_SPEED, COIN_GOLD);
mBackGroundTexture = new Texture2D(mRenderer);
if( !mBackGroundTexture->LoadFromFile("Image/backgroundMB.png"))
{
cout << "Failed to load background texture!";
return false;
}
return true;
}
//----------------------------------------------------------------------------------------
void GameScreenLevel1::Update(float deltaTime, SDL_Event e)
{
//Update Enemies
UpdateEnemies(deltaTime, e);
//Update the player
mCharacterMario->Update(deltaTime, e);
//////Update FireBalls
UpdateFireBalls(deltaTime, e);
switch(e.type)
{
//Deal with keyboard input
case SDL_KEYUP:
switch(e.key.keysym.sym)
{
case SDLK_DOWN:
CreateFireBalls(mCharacterMario->GetPosition(), mCharacterMario->GetFacing());
break;
default:
break;
}
break;
}
}
//----------------------------------------------------------------------------------------
void GameScreenLevel1::Render()
{
mBackGroundTexture->Render(Vector2D(), SDL_FLIP_NONE);
mCharacterMario->Render();
//Draw Enemies
for(unsigned int i = 0; i < mEnemies.size(); i++)
{
mEnemies[i]->Render();
}
//Draw Balls
for(unsigned int i = 0; i < mBalls.size(); i++)
{
mBalls[i]->Render();
}
//Draw Coin
for(unsigned int i = 0; i < mCoin.size(); i++)
{
mCoin[i]->Render();
}
}
//-----------------------------------------------------------------------------------------
void GameScreenLevel1::SetLevelMap()
{
//Map cordinates
int map[13][16] = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} };
//Clear up any old map
if(mLevelMap != NULL) { delete mLevelMap; }
//Set the new one
mLevelMap = new LevelMap(map);
}
void GameScreenLevel1::UpdateEnemies(float deltaTime, SDL_Event e)
{
if(!mEnemies.empty())
{
int enemyIndexToDelete = -1;
for(unsigned int i = 0; i < mEnemies.size(); i++)
{
mEnemies[i]->Update(deltaTime, e);
//Check to see if the enemy collides with player
if(Collisions::Instance()->Circle(mEnemies[i], mCharacterMario))
{
mCharacterMario->SetState(CHARACTERSTATE_PLAYER_DEATH);
}
//Check if the enemy colliders with a ball that is in FIRE state
for(unsigned int j = 0; j < mBalls.size(); j++)
{
if(mBalls[j]->IsInState(CHARACTERSTATE_BALL_FIRING) && mBalls[j]->IsBallType(BALL))
{
if(Collisions::Instance()->Circle(mEnemies[i], mBalls[j]))
{
mBalls[j]->SetBallType(ENEMY_DIED);
mEnemies[i]->SetAlive(false);
}
}
//If enemy is no longer alive, then schedule it for deletion
if(!mEnemies[i]->GetAlive())
{
enemyIndexToDelete = i;
}
}
//Remove dead enemies -1 each update
if(enemyIndexToDelete != -1)
{
mEnemies.erase(mEnemies.begin()+enemyIndexToDelete);
}
}
}
}
void GameScreenLevel1::UpdateFireBalls(float deltaTime, SDL_Event e)
{
//Update Balls
if(!mBalls.empty())
{
int bubbleIndexToDelete = -1;
for(unsigned int i = 0; i < mBalls.size(); i++)
{
mBalls[i]->Update(deltaTime, e);
//Ball rising check and condition
int ballIndexToDelete = -1;
if(mBalls[i]->IsInState(CHARACTERSTATE_BALL_RISING))
{
if(Collisions::Instance()->Circle(mCharacterMario, mBalls[i]))
{
if(mBalls[i]->IsBallType(BALL))
{
//Pop empty gone
mBalls[i]->SetAlive(false);
}
else
{
//FireBall with baddies change state
mBalls[i]->SetState(CHARACTERSTATE_BALL_DIE);
}
}
if(mBalls[i]->AutoDestroy())
{
mBalls[i]->SetAlive(false);
CreateEnemy1(mBalls[i]->GetPosition(), mBalls[i]->GetFacing(), ENEMY_SPEED2, BADDIE_ANGRY);
}
}
else if(mBalls[i]->MakeMeCoin())
{
mBalls[i]->SetAlive(false);
COIN_TYPE typeOfCoin = COIN_GOLD;
}
//If the ball is no longer alive, then schedule it for deletion
if(!mBalls[i]->GetAlive())
{
bubbleIndexToDelete = i;
}
//Remove a dead enemy - 1 each update
if(ballIndexToDelete != -1)
{
mBalls.erase(mBalls.begin()+ballIndexToDelete);
}
}
}
}
void GameScreenLevel1::CreateFireBalls(Vector2D position, FACING direction)
{
mBalls.push_back(new CharacterFireBall(mRenderer, "Image/MarioFireBall.png", mLevelMap, position, direction, 10));
}
void GameScreenLevel1::UpdateCoin(float deltaTime,SDL_Event e)
{
if(!mCoin.empty())
{
int coinIndexToDelete = -1;
for(unsigned int i = 0; i < mCoin.size(); i++)
{
mCoin[i]->Update(deltaTime, e);
//Check to see if the coin collides with player
if(Collisions::Instance()->Circle(mCoin[i], mCharacterMario))
{
//mCharacterMario->mtotalScore += 1;
}
//Remove dead enemies -1 each update
if(coinIndexToDelete != -1)
{
mCoin.erase(mEnemies.begin()+coinIndexToDelete);
}
}
}
}
//void GameScreenLevel1::CreateCoin(Vector2D position, COIN_TYPE type)
//{
// string coinPath;
//
// switch(type)
// {
// case COIN_GOLD:
// coinPath = "Image/Coin.png";
// break;
// }
//
// Character* coinCharacter = new Character(mRenderer, coinPath, position, mLevelMap, FACING_LEFT, 0);
// Character* tempCharacter = (Character*)coinCharacter;
// mCoin.push_back(tempCharacter);
//}
void GameScreenLevel1::CreateEnemy1(Vector2D position, FACING direction, float speed, BADDIE_TYPE type)
{
string baddiePath;
switch(type)
{
case BADDIE_ANGRY:
baddiePath = "Image/EngryAngry.png";
break;
case BADDIE_NORMAL:
default:
baddiePath = "Image/EnemyNormal.png";
}
Character* EnemyCharacter1 = new CharacterEnemy(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mEnemies.push_back(EnemyCharacter1);
}
void GameScreenLevel1::CreateEnemy2(Vector2D position, FACING direction, float speed, BADDIE_TYPE type)
{
string baddiePath;
switch(type)
{
case BADDIE_ANGRY:
baddiePath = "Image/EnemyAngry.png";
break;
case BADDIE_NORMAL:
default:
baddiePath = "Image/EnemyNormal.png";
}
Character* EnemyCharacter2 = new CharacterEnemy(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mEnemies.push_back(EnemyCharacter2);
}
void GameScreenLevel1::CreateEnemy3(Vector2D position, FACING direction, float speed, BADDIE_TYPE type)
{
string baddiePath;
switch(type)
{
case BADDIE_ANGRY:
baddiePath = "Image/EnemyAngry.png";
break;
case BADDIE_NORMAL:
default:
baddiePath = "Image/EnemyNormal.png";
}
Character* EnemyCharacter3 = new CharacterEnemy(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mEnemies.push_back(EnemyCharacter3);
}
void GameScreenLevel1::CreateEnemy4(Vector2D position, FACING direction, float speed, BADDIE_TYPE type)
{
string baddiePath;
switch(type)
{
case BADDIE_ANGRY:
baddiePath = "Image/EnemyAngry";
break;
case BADDIE_NORMAL:
default:
baddiePath = "Image/EnemyNormal.png";
}
Character* zenChanCharacter4 = new CharacterEnemy(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mEnemies.push_back(zenChanCharacter4);
}
void GameScreenLevel1::CreateEnemy5(Vector2D position, FACING direction, float speed, BADDIE_TYPE type)
{
string baddiePath;
switch(type)
{
case BADDIE_ANGRY:
baddiePath = "Image/EnemyAngry";
break;
case BADDIE_NORMAL:
default:
baddiePath = "Image/EnemyNormal.png";
}
Character* EnemyCharacter5 = new CharacterEnemy(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mEnemies.push_back(EnemyCharacter5);
}
void GameScreenLevel1::CreateCoin1(Vector2D position, FACING direction, float speed, COIN_TYPE type)
{
string baddiePath;
switch(type)
{
case COIN_GOLD:
baddiePath = "Image/coin.png";
break;
}
Character* CoinCharacter1 = new CharacterCoin(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mCoin.push_back(CoinCharacter1);
}
void GameScreenLevel1::CreateCoin2(Vector2D position, FACING direction, float speed, COIN_TYPE type)
{
string baddiePath;
switch(type)
{
case COIN_GOLD:
baddiePath = "Image/coin.png";
break;
}
Character* CoinCharacter2 = new CharacterCoin(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mCoin.push_back(CoinCharacter2);
}
void GameScreenLevel1::CreateCoin3(Vector2D position, FACING direction, float speed, COIN_TYPE type)
{
string baddiePath;
switch(type)
{
case COIN_GOLD:
baddiePath = "Image/coin.png";
break;
}
Character* CoinCharacter3 = new CharacterCoin(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mCoin.push_back(CoinCharacter3);
}
void GameScreenLevel1::CreateCoin4(Vector2D position, FACING direction, float speed, COIN_TYPE type)
{
string baddiePath;
switch(type)
{
case COIN_GOLD:
baddiePath = "Image/coin.png";
break;
}
Character* CoinCharacter4 = new CharacterCoin(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mCoin.push_back(CoinCharacter4);
}
void GameScreenLevel1::CreateCoin5(Vector2D position, FACING direction, float speed, COIN_TYPE type)
{
string baddiePath;
switch(type)
{
case COIN_GOLD:
baddiePath = "Image/coin.png";
break;
}
Character* CoinCharacter5 = new CharacterCoin(mRenderer, baddiePath, mLevelMap, position, direction, 10);
mCoin.push_back(CoinCharacter5);
}