Advertisement

Need SDL wiz

Started by May 12, 2011 06:03 AM
0 comments, last by rip-off 13 years, 6 months ago
There's a youtube series online that does C++/SDL, (appears to be dead), and it stops just short of finishing the game (that after this tutorial will be more OOP). Before the last two tutorials, he finished the game (it compiled perfectly), and he was in the process of just organizing it (to make it more engine-like, before the last two tutorials it was just one main.cpp file) when he apparently stopped making videos, so I know the code is good, just not exactly where to put it. The code I am unsure of is in the third code snippet.


//THIS CODE SHOULD BE FINE, INCLUDING IT JUST IN CASE
#include "gameEvents.h"

int main (int argc, char* argv[])
{
gameEvents gameEvents;

gameEvents.gameLoad();
gameEvents.gameInit();

while(gameEvents.runningState())
{ gameEvents.gameInput();
gameEvents.gameDraw();
gameEvents.gameUpdate(); }

gameEvents.gameClean();

return 0;

}



//PROBABLY NEED TO PUT THE CODE SOMEWHERE IN HERE
#include "globals.h"

class gameEvents
{private:
SDL_Surface* screen;
bool gameRunning;

public:
gameEvents();
void gameLoad();
void gameInit();
void gameInput();
void gameDraw();
void gameUpdate();
void gameClean();
bool runningState();};

gameEvents::gameEvents(){}

void gameEvents::gameLoad(){}

void gameEvents::gameInit()
{ gameRunning = true;
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
SDL_WM_SetCaption("First Game", NULL); }

void gameEvents::gameInput()
{ SDL_Event event;
if(SDL_PollEvent(&event))
{ bool keys[323] = {false};
if(event.type == SDL_KEYDOWN)
{ keys[event.key.keysym.sym] = true; }
if(event.type == SDL_KEYUP)
{ keys[event.key.keysym.sym] = false; }
if(keys[SDLK_RIGHT])
{ dstX += 1; }
if(keys[SDLK_LEFT])
{ dstX -= 1; }
if(keys[SDLK_UP])
{ dstY += 1; }
if(keys[SDLK_DOWN])
{ dstY -= 1; }
if(dstX < 0)
{ dstX = 0; }
if(dstY < 0)
{ dstY = 0; }
if(dstX + width > SCREEN_WIDTH)
{ dstX = SCREEN_WIDTH - width; }
if(dstY + height > SCREEN_HEIGHT)
{ dstX = SCREEN_HEIGHT - height; }
}

if(event.type = SDL_QUIT)
{ gameRunning = false; }}

void gameEvents::gameDraw()
{
}

void gameEvents::gameUpdate(){} //Will takeover draw once the initial screen is loaded and drawn

void gameEvents::gameClean()
{ SDL_Delay(1000);
SDL_Quit();
exit(0); }

bool gameEvents::runningState() { return gameRunning;}





//!!!
//THIS CODE IS WHAT I'M HAVING AN ISSUE WITH. I DON'T KNOW EXACTLY WHERE TO PUT ALL THE CODE AFTER THE
// const int SCREEN_BPP = 32; TO MAKE THE ENGINE RUN.
//!!!

#include <SDL.h>
#include <SDL_image.h>

const int SCREEN_HEIGHT = 640;
const int SCREEN_WIDTH = 480;
const int SCREEN_BPP = 32;

SDL_Surface * screen = NULL; //
SDL_Surface * background = NULL; //
SDL_Surface * sprite = NULL; //

//sprite values
int width = 32;
int height = 32;

int srcX = 0;
int srcY = 0;

int dstX = 0;
int dstY = 0;

void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination) //this applies the surface to the screen
{
SDL_Rect rect;
rect.x = x;
rect.y = y;

SDL_BlitSurface(source, NULL, destination, &rect);
SDL_Flip(screen);
}

void draw_sprite(int srcX, int srcY, int dstX, int dstY, int width, int height, //Handles the sprites values
SDL_Surface* source, SDL_Surface* destination)
{
SDL_Rect src;
src.x = srcX;
src.y = srcY;
src.w = width;
src.h = height;

SDL_Rect dst;
dstX = dstX;
dstY = dstY;
dst.w = width;
dst.h = height;

SDL_BlitSurface( source, &src, destination, &dst);
SDL_Flip(screen);
}


All this code is expected to do is move a 32x32 image across the screen, and set boundaries that prevent the image from going out of the screen. You should be able to hold down a movement key and it'll keep moving.

The main thing I don't know what to do with is the void apply_surface() and the void draw_sprite(). (And possibly the sprite values above them, I was thinking I could just leave them in there).

The code compiles as-is, but it's just a blank screen. =\

This has been bugging me all night, your help is greatly appreciated!

Devlin
You're getting a blank screen because you're not drawing anything. You shoudn't use global variables, for the moment you can make all those variables members of the gameEvents class, or constants in the Game.cpp file.

Other things:

  • What is the difference between gameLoad and gameInit and the constructor? You have three different initialisation functions, this is confusing. I suggest you do the initialisation in the constructor.
  • apply_surface() and draw_sprite() should not flip the screen. There is a bug in draw_sprite, it doesn't correctly set the destination rectangle co-ordinates.
  • You should handle more than one event every frame, using while(SDL_PollEvent()) rather than an if statement.
  • This is a personal thing but the formatting of your source is very confusing. Tightly packing the braces like that makes the code dense and hard to read. I think it would benefit enormously from more whitespace.


    Here is a simple breakdown of what should go where.

    Graphics.h

    #ifndef GRAPHICS_H
    #define GRAPHICS_H

    void apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination);

    void draw_sprite(int srcX, int srcY, int dstX, int dstY, int width, int height, SDL_Surface* source, SDL_Surface* destination);

    #endif


    Game.h:

    #ifndef GAME_H
    #define GAME_H

    class Game
    {
    private:
    SDL_Surface *screen;
    SDL_Surface *background;
    SDL_Surface *sprite;
    bool running;
    int dstX;
    int dstY;

    public:
    Game();
    ~Game();

    void handleInput();

    void draw();

    void update();

    bool isRunning();
    };

    #endif


    Graphics.cpp

    #include "Graphics.h"

    void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination)
    {
    SDL_Rect rect;
    rect.x = x;
    rect.y = y;

    SDL_BlitSurface(source, NULL, destination, &rect);
    }

    void draw_sprite(int srcX, int srcY, int dstX, int dstY, int width, int height, SDL_Surface* source, SDL_Surface* destination)
    {
    SDL_Rect src;
    src.x = srcX;
    src.y = srcY;
    src.w = width;
    src.h = height;

    SDL_Rect dst;
    dst.x = dstX;
    dst.y = dstY;
    dst.w = width;
    dst.h = height;

    SDL_BlitSurface( source, &src, destination, &dst);



    Game.cpp

    #include "Game.h"

    #include <stdexcept>

    #include "Graphics.h"

    const int SCREEN_HEIGHT = 640;
    const int SCREEN_WIDTH = 480;
    const int SCREEN_BPP = 32;

    int SPRITE_WIDTH = 32;
    int SPRITE_HEIGHT = 32;

    Game::Game()
    :
    screen(0),
    background(0),
    sprite(0),
    dstX(0),
    dstY(0),
    running(true)
    {
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
    throw std::runtime_error(SDL_GetError());
    }

    screen = SDL_SetVideoMode(SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_BPP, 0);
    if(!screen)
    {
    SDL_Quit();
    throw std::runtime_error(SDL_GetError());
    }

    background = SDL_LoadBMP("background.bmp");
    sprite = SDL_LoadBMP("sprite.bmp");

    if(!(background && sprite))
    {
    SDL_FreeSurface(background);
    SDL_FreeSurface(sprite);
    SDL_Quit();
    throw std::runtime_error(SDL_GetError());
    }
    }

    Game::~Game()
    {
    SDL_FreeSurface(background);
    SDL_FreeSurface(sprite);
    SDL_Quit();
    }

    bool Game::isRunning()
    {
    return running;
    }

    void Game::handleInput()
    {
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
    if(event.type == SDL_QUIT)
    {
    running = false;
    }
    }

    Uint8 *keys = SDL_GetKeyState(NULL);
    if(keys[SDLK_ESCAPE])
    {
    running = false;
    }

    if(keys[SDLK_RIGHT])
    {
    dstX += 1;
    }
    if(keys[SDLK_LEFT])
    {
    dstX -= 1;
    }

    if(keys[SDLK_UP])
    {
    dstY += 1;
    }
    if(keys[SDLK_DOWN])
    {
    dstY -= 1;
    }

    if(dstX < 0)
    {
    dstX = 0;
    }

    if(dstX + SPRITE_WIDTH > SCREEN_WIDTH)
    {
    dstX = SCREEN_WIDTH - SPRITE_WIDTH;
    }

    if(dstY < 0)
    {
    dstY = 0;
    }

    if(dstY + SPRITE_HEIGHT > SCREEN_HEIGHT)
    {
    dstX = SCREEN_HEIGHT - SPRITE_HEIGHT;
    }
    }

    void Game::draw()
    {
    apply_surface(0, 0, background, screen);
    draw_sprite(0, 0, dstX, dstY, SPRITE_WIDTH, SPRITE_HEIGHT, sprite, screen);
    SDL_Flip(screen);
    }

    void Game::update()
    {
    // TODO: add code here!
    }


    Main.cpp

    #include <stdexcept>
    #include <iostream>

    #include "Game.h"

    int main()
    {
    try
    {
    Game game;
    while(game.isRunning())
    {
    game.handleInput();
    game.update();
    game.draw();
    }
    }
    catch(const std::exception &e)
    {
    std::cerr << "Fatal error: " << e.what() << '\n';
    return 1;
    }
    catch(...)
    {
    std::cerr << "Fatal unknown error occurred\n";
    return 2;
    }
    }

    Note that we need a header file for the graphics function prototypes, because if you #include a function body in more than one file you'd get duplicate definition linker errors. I've renamed gameEvents to "Game" as the older name wasn't really suitable given what the class does.

    Something like that will get you started. The next step might be to separate the sprite stuff into a separate class.

This topic is closed to new replies.

Advertisement