Quantcast
Channel: Programming Forums
Viewing all articles
Browse latest Browse all 51036

Problem: C++/SDL Game Applcation Exits When Calling an SDL Function

$
0
0
I'm currently working on a game (and framework) using C++ and SDL. I have implemented a state manager, and each game state (main menu, playing, and pause) have their own class. Within those classes are three important functions (important to this problem, anyway). Those functions are:

update():
Update the object, such as moving it and collision checking.
draw():
Draw the object's sprite (done with SDL_BlitSurface()).
clean():
Invoke SDL_FreeSurface() to free the object's sprite surface.

As can be seen from above, the draw() and clean() functions invoke SDL functions, whereas update() doesn't.

Each game object is stored within a vector names "gameObjects". Within the three functions above, I iterate over the vector and invoke the appropriate functions. This just makes it easier to handle all objects within the current state.

If I switch from the MenuState to PlayState, then back to MenuState, then again back to PlayState, the game will simply exit. However, if I comment out the SDL functions used in update() and draw(), this strange problem disappears. So it seems that if SDL functions are called from update(), or draw(), the game will crash.

My question is, does anyone know why this does the game crash only when an SDL function is called from the above functions? Other, non-SDL functions work fine within update(), draw(), and clean().

Here's the most relevant code:

PlayState.cpp
#include <stdio.h>

#include "SDL.h"

#include "Game.hpp"
#include "MenuState.hpp"
#include "PlayState.hpp"
#include "PauseState.hpp"
#include "MessageBoxState.hpp"

namespace mrbp
{
PlayState PlayState::playState;

// PlayState::init()
void PlayState::init()
{
    background = NULL;
    background = Sprite::load("bg/play-bg.png");
    
    player = new Player();
    player->load("player/player-idle.png");
    
    // Add player to the gameObjects vector.
    gameObjects.push_back(player);
}

// PlayState::clean()
void PlayState::clean()
{
    // Call the clean() function for each object in the gameObjects vector.
    for (std::vector<GameObject*>::iterator it = gameObjects.begin();
                it != gameObjects.end(); ++it)
    {
        if (!(*it))
        {
            continue;
        }
        
        (*it)->clean();
    }
    
    SDL_FreeSurface(background);
}

// PlayState::pause()
void PlayState::pause()
{
}

// PlayState::resume()
void PlayState::resume()
{
}

// PlayState::handleEvents()
void PlayState::handleEvents(Game *game)
{
    SDL_Event event;
    if (SDL_PollEvent(&event))
    {
        switch (event.type)
        {
            case SDL_QUIT:
                game->quit();
                break;
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        game->changeState(MenuState::instance());
                        break;
                    case SDLK_SPACE:
                        game->pushState(PauseState::instance());
                        break;
                    case SDLK_m:
                        game->pushState(MessageBoxState::instance());
                        break;
                }
                break;
            case SDL_MOUSEBUTTONDOWN:
                switch (event.button.button)
                {
                    case SDL_BUTTON_LEFT:
                        game->pushState(PauseState::instance());
                        break;
                }
                break;
        }
    }
}

// PlayState::update()
void PlayState::update(Game *game)
{
    // Call the update() function for each object in the gameObjects vector.
    for (std::vector<GameObject*>::iterator it = gameObjects.begin();
                it != gameObjects.end(); ++it)
    {
        if (!(*it))
        {
            continue;
        }
        
        (*it)->update();
    }
}

// PlayState::draw()
void PlayState::draw(Game *game)
{
    Sprite::draw(game->getScreen(), background, 0, 0);
    // Call the draw() function for each object in the gameObjects vector.
    for (std::vector<GameObject*>::iterator it = gameObjects.begin();
                it != gameObjects.end(); ++it)
    {
        if (!(*it))
        {
            continue;
        }
        
        (*it) ->draw();
    }
    
    SDL_Flip(game->getScreen());
}
} // namespace mrbp


GameObject.cpp
#include "GameObject.hpp"
#include "File.hpp"

namespace mrbp
{
// GameObject::load()
void GameObject::load(const char *file)
{
    sprite = Sprite::load(file);
    
    File dataFile;
    dataFile.open("../data/default/gameobject/gameobject.txt");
    dataFile.getFloat(&x);
    dataFile.getFloat(&y);
    dataFile.close();
}

// GameObject::update()
void GameObject::update()
{
}

// GameObject::draw()
void GameObject::draw()
{
    // Strangely, this SDL function, SDL_FillRect(),
    // doesn't crash the game...
    static SDL_Rect rect = {32, 32};
    SDL_FillRect(GameInst::instance()->getScreen(), &rect, 0xFFFFFF);
    // My application will crash if I uncomment the below line
    // as it (draw()) calls the SDL function, SDL_BlitSurface().
    //Sprite::draw(GameInst::instance()->getScreen(), sprite, x, y);
}

// GameObject::clean()
void GameObject::clean()
{
    // Uncommenting the below line will also crash the game.
    //SDL_FreeSurface(sprite);
}
} // namespace mrbp


At this point in time, the player object's update(), draw(), and clean() functions only call the GameObject class' definitions so I won't include the Player.cpp file.

I apologise if I haven't explained my problem clear enough. I'll be happy to try and reiterate if needed.

Viewing all articles
Browse latest Browse all 51036

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>