top of page

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);

}

© 2016 by Daniel Bognar. Proudly created with Wix.com

  • Facebook Social Icon
bottom of page