-1

I am trying to learn c++ and sdl but so far i am failing quite miserably. I've been following Lazy Foo's tutorials on sdl but in all his tutorials the code is dumped into one big main source file. I am looking for a way to segment and partition this big chunk of code into headers and classes so that my main.cpp file will have only the single int main function and all the other init and exit functions will stay in other files. I dont know if this is good practice, but so far i have read that you should divide your code into parts so that it runs faster and more smooth. If you could show me some examples i am sure i could figure out the rest. Here is my code and the ways i have tried to partition it:



main.cpp

#include <SDL.h>
#include <stdio.h>

#include "game_state.h"
#include "game_state.cpp"

int main( int argc, char* args[] ) {

    if( !init() )
    {
        printf( "Failed to initialize!\n" );
    } else {
        //Load media
        if( !loadMedia() )
        {
            printf( "Failed to load media!\n" );
        } else {
            //Apply the image
            SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );

            //Update the surface
            SDL_UpdateWindowSurface( gWindow );

            //Wait two seconds
            SDL_Delay( 2000 );
        }
    }

    //Free resources and close SDL
    onExit();

    return 0;

}

game_state.h

#ifndef PLAYER_H
#define PLAYER_H

#include <SDL.h>
#include <stdio.h>

//The window we'll be rendering to
SDL_Window *gWindow;

//The surface contained by the window
SDL_Surface *gScreenSurface;

//The image we will load and show on the screen
SDL_Surface *gHelloWorld;

bool init();

bool loadMedia();

void onExit();

#endif

game_state.cpp

#include "game_state.h"


//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;




bool init() {
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        success = false;
    }
    else
    {
        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == NULL )
        {
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
            success = false;
        }
        else
        {
            //Get window surface
            gScreenSurface = SDL_GetWindowSurface( gWindow );
        }
    }

    return success;
}

bool loadMedia() {
    //Loading success flag
    bool success = true;

    //Load splash image
    gHelloWorld = SDL_LoadBMP( "02_getting_an_image_on_the_screen/hello_world.bmp" );
    if( gHelloWorld == NULL )
    {
        printf( "Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError() );
        success = false;
    }

    return success;
}

void onExit()
{
    //Deallocate surface
    SDL_FreeSurface( gHelloWorld );
    gHelloWorld = NULL;

    //Destroy window
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;

    //Quit SDL subsystems
    SDL_Quit();
}

the original main.cpp by lazy foo, which i tried to segment:

//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//The window we'll be rendering to
SDL_Window* gWindow = NULL;

//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;

//The image we will load and show on the screen
SDL_Surface* gHelloWorld = NULL;

bool init()
{
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        success = false;
    }
    else
    {
        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == NULL )
        {
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
            success = false;
        }
        else
        {
            //Get window surface
            gScreenSurface = SDL_GetWindowSurface( gWindow );
        }
    }

    return success;
}

bool loadMedia()
{
    //Loading success flag
    bool success = true;

    //Load splash image
    gHelloWorld = SDL_LoadBMP( "02_getting_an_image_on_the_screen/hello_world.bmp" );
    if( gHelloWorld == NULL )
    {
        printf( "Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError() );
        success = false;
    }

    return success;
}

void close()
{
    //Deallocate surface
    SDL_FreeSurface( gHelloWorld );
    gHelloWorld = NULL;

    //Destroy window
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;

    //Quit SDL subsystems
    SDL_Quit();
}

int main( int argc, char* args[] )
{
    //Start up SDL and create window
    if( !init() )
    {
        printf( "Failed to initialize!\n" );
    }
    else
    {
        //Load media
        if( !loadMedia() )
        {
            printf( "Failed to load media!\n" );
        }
        else
        {
            //Apply the image
            SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );

            //Update the surface
            SDL_UpdateWindowSurface( gWindow );

            //Wait two seconds
            SDL_Delay( 2000 );
        }
    }

    //Free resources and close SDL
    close();

    return 0;
}

all and any help is appreciated, thank you ;)

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
Ata Keskin
  • 97
  • 1
  • 9
  • 2
    *"i have read that you should divide your code into parts so that it runs faster and more smooth"* - this is completely wrong. It can only manifest in faster build times. – LogicStuff Jan 03 '16 at 22:28
  • What actually doesn't work with your approach. Can you highlight that please? – πάντα ῥεῖ Jan 03 '16 at 22:29
  • You shouldn't include .cpp files - you would normally compile all the .cpp to .o files and then link the .os to an exe. In game_state.h apart from including stdio (which you don't need) it looks like you're on track. – John3136 Jan 03 '16 at 22:29
  • You can read through [this](http://stackoverflow.com/questions/280033/c-header-files-code-separation) to understand this a bit more – James Kirsch Jan 03 '16 at 22:32
  • Global variables should be declared in the game_state.cpp not in game_state.h. if you need to use them in the main, add `extern` in the header before each. – SHR Jan 03 '16 at 22:34
  • Pretty good start. What's the problem? – Lightness Races in Orbit Jan 03 '16 at 22:39
  • As a design problem, cleaned-up this would be suitable for Programmers.SE. – Lightness Races in Orbit Jan 03 '16 at 22:40
  • It is good coding practice to split source over files. Not for running faster, not for running smoother ( what ever that means in code execution ). You should do it to organise your code, keeping thing together that belongs together, keeping variables and functions local to a file ( look at the "static" specifier to do so ) wherever you can. – Hans Lepoeter Jan 03 '16 at 22:48
  • There's also this site: http://codereview.stackexchange.com – kfx Jan 03 '16 at 22:51
  • @kfx Indeed CodeReview can be a fine place to ask if you are also interested in overall improvements too, not just modularization. – Caridorc Jan 03 '16 at 23:13

1 Answers1

0

Big projects are split into a lot of files, that are usually mapped onto a directory hierarchy. The reason for this is not efficiency (the compilation may be actually faster if you dump the whole code into a single file and it does not affect the run time at all), but code management issues (imagine opening a file with over 100 000 lines of code).

The programming language and the tools are usually designed to help with this practice. For example, in C/C++ you have the include preprocessor directive, that allows you to "import" a file.

Regarding the question of how to perform the actual splitting, it is usually best not to use a top down approach like yours (i.e. I have the code, how to I split it?) but rather design the code having this modularity in mind. This being said, you can consider each file as a small module, that provides some related functionality. There are many things to consider here and developing the architecture of an application is a bit of an art, but for now, just keeping things with similar functionality in the same place is a good start.

Your example is too small for any practical advice, it is so small such that having everything in one file is not that bad. Your division is good, you separated the game logic (I don't really like the name of your module, game_state, since you don't really represent the game state there; you seem to define some game-related processes) but is not really necessary.

Paul92
  • 8,827
  • 1
  • 23
  • 37