Jump to content
  • Advertisement
Sign in to follow this  

Splitting up project in .h and .cpp

This topic is 3699 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I must say I still don't quite understand how to manage my code in the correct files. My code doesn't do anything yet, I just started this project, but I want to organize my files correctly from the start on. This is how I've tried it untill now: main.cpp
/**
  * PongSDL
  * Reinventing the wheel
  *
**/

#include <cstdlib>

#include "graphics.h"


int main ( int argc, char* argv[] )
{
    Gfx gfx;
    gfx.init();

    return 0;
}

/**
  * End of main.cpp
  *
**/

graphics.h
/**
  * graphics.h
  *
**/


class Gfx
{
public:

    Gfx();
    ~Gfx();

    int init();

    int draw();

private:

    SDL_Surface* screen;

};



/**
  * End of graphics.h
  *
**/

graphics.cpp
/**
  * graphics.cpp
  *
**/


#include "graphics.h"

#include <SDL/SDL.h>


const int GFX_SCREEN_W = 600;
const int GFX_SCREEN_H = 400;


Gfx::Gfx()
{
    *screen = NULL;
}

Gfx::~Gfx()
{
    SDL_FreeSurface( screen );
}


int Gfx::init()
{
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "Unable to init SDL: %s\n", SDL_GetError() );
        return -1;
    }

    SDL_WM_SetCaption( "PongSDL", NULL );

    *screen = SDL_SetVideoMode( GFX_SCREEN_W, GFX_SCREEN_H, 32, SDL_SWSURFACE );

    if ( !screensurface )
    {
        printf( "Unable to set video: %s\n", SDL_GetError() );
        return -1;
    }

    return 1;
}



/**
  * End of graphics.cpp
  *
**/

The error:
graphics.h:20: error: ISO C++ forbids declaration of `SDL_Surface' with no type
graphics.h:20: error: expected `;' before '*' token
Can someone tell me how to organize my files properly? Thanks. PS: I'm using CPP, but for some reason GameDev gets rid of the two plusses in my post.

Share this post


Link to post
Share on other sites
Advertisement
Your graphics.h has no way of knowing what SDL_Surface means. To fix the problem, you should move the inclusion of SDL.h to the beginning of graphics.h.

File inclusion in C/C++ has some quirks though, for which reason you should really use include guards. It's very simple, really. Just do the following:
// blarg.h
// Class that does awesome stuff

#ifndef BLARG_H
#define BLARG_H

// Your code and includes goes here
#include <SDL.h>

class Blarg {
// Stuff
};

#endif // BLARG_H


This ensures that your code is only parsed once, no matter how many times the file is included from the same compilation unit.

Share this post


Link to post
Share on other sites
That error occurs in your graphics.cpp file, when you include #include "graphics.h". You are doing that before including #include <SDL/SDL.h>, so when it sees SDL_Surface, it doesn't know what it is.

You should include the standard includes before your own headers, like you've correctly done in main.cpp.

So your graphics.cpp file should look like:
/**
* graphics.cpp
*
**/

#include <SDL/SDL.h>

#include "graphics.h"

...
I suggest you read this article if you haven't already. It may not be the best, but it's the only one I know of.

http://www.gamedev.net/reference/articles/article1798.asp

Share this post


Link to post
Share on other sites
You need to put #include <SDL/SDL.h> into the beginning graphics.h, because you refer to types defined there. Also, you should add guards to your header files.

Put this right into the beginning of graphics.h, before anything else:

#ifndef GRAPHICS_H
#define GRAPHICS_H



And this comes right at the end after everything else:

#endif // GRAPHICS_H



If you do not have these guards, and you include graphics.h twice, the compiler will complain of doubly defined classes and such.

Share this post


Link to post
Share on other sites
Including SDL in the header file solved my problem.
Including SDL before the header in the cpp file did not solve my problem. I chose to just include it in the header aswell.
Thanks a lot for the tips on the guards, this will probably save me lots of trouble later on.
I remember seeing that article somewhere sometime, but I couldn't fid it anymore. I bookmarked it this time :)

Thanks for all your replies

Share this post


Link to post
Share on other sites
I still have many problems... Google made me a little wisers and taught me how to use the extern operator, but it doesn't always work.

snippet of game.h
/**
* game.h
*
**/



#ifndef GAME_H
#define GAME_H

#include "graphics.h" // The game passes commands to the graphics
#include <SDL/SDL.h> // For SDL_Event
#include "ball.h" // The game has a ball
#include <vector> // Sometimes more than one ball

// ...

struct Gamestate
{
public:

std::vector<Ball> vball;

};

// ...

#endif // GAME_H

snippet of graphics.h
/**
* graphics.h
*
**/



#ifndef GFX_H
#define GFX_H

#include <SDL/SDL.h> // For SDL_Video
#include "game.h" // Needs information about game elements to draw

// ...

class Gfx
{
public:

Gfx();
~Gfx();

int init();

void draw( Gamestate* state ); // <- Error is here

private:

SDL_Surface* screen;

void drawPixel( int x, int y );

};

// ...

#endif // GFX_H


I get the following error:
graphics.h:24: error: `Gamestate' has not been declared
graphics.h:24: error: ISO C++ forbids declaration of `state' with no type
graphics.h:24: note: candidates are: void Gfx::draw(int*)


I can't use the extern keyword for struct though! What am I doing wrong?

Share this post


Link to post
Share on other sites
Hmmm, this is going very wrong already... I don't understand the idea behind proper splitting up of files. I started programming Pong to teach myself this. Could you please look at my code and tell me how I should split things up and what needs to include what with a little explanation. Thanks in forward

main.cpp
/**
* PongSDL
* main.cpp
*
**/




#include "game.h"



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

if( pong.mainMenu() )
pong.play();


pong.~Game();

return 0;
}



/**
* End of main.cpp
*
**/



game.h
/**
* game.h
*
**/



#ifndef GAME_H
#define GAME_H

#include <SDL/SDL.h> // For SDL_Event
#include "graphics.h" // We need some graphics to play
#include "ball.h" // The game has a ball



struct Gamestate
{
public:

Ball ball;

};



class Game
{
public:

Game();
~Game();

bool mainMenu();
int play();

private:

Gfx gfx;
SDL_Event event;
Gamestate* current_state;
Gamestate* previous_state;


};



extern Ball newBall( int x, int y, float velocity, float angle, float rad );
extern void updateBall( Ball* b, double dt );



#endif // GAME_H

/**
* game.h
*
**/



game.cpp
/**
* game.cpp
*
**/



#include "game.h"
#include <SDL/SDL.h> // For SDL_Event
#include "timer.h"
#include "ball.h"



void process( Gamestate* state, double t, double dt )
{
// Move ball
updateBall( &state->ball, dt );

// Todo: Rest of processing, eg. collision detection
}



Game::Game()
{
gfx.init();
}

Game::~Game()
{
gfx.~Gfx();
}



bool Game::mainMenu()
{
return true;

// Placeholder for a future main menu

}


int Game::play()
{
Timer timer;
const float DELTA = 0.01;

previous_state = new Gamestate;
current_state = new Gamestate;

current_state->ball = newBall( 100, 100, 0.1, 0.0, 5.0 );


bool loop = true;

while( loop ) {

timer.fillAccu();

while( timer.pinchAccu( DELTA ) ) {

// Process here
*previous_state = *current_state;
process( current_state, timer.getTimePassed(), DELTA );

} // End of processing


while( SDL_PollEvent( &event ) ) {

if( event.type == SDL_QUIT )
loop = false;

} // End of event polling


gfx.draw( current_state );


} // End of main loop


return 0;
}



/**
* End of game.cpp
*
**/



graphics.h
/**
* graphics.h
*
**/



#ifndef GFX_H
#define GFX_H

#include <SDL/SDL.h> // For SDL_Video

struct Gamestate; // Forward declaration



class Gfx
{
public:

Gfx();
~Gfx();

int init();

void draw( Gamestate* state );

private:

SDL_Surface* screen;

void drawPixel( int x, int y );

};



const int GFX_SCREEN_W = 600;
const int GFX_SCREEN_H = 400;



#endif // GFX_H

/**
* End of graphics.h
*
**/



graphics.cpp
/**
* graphics.cpp
*
**/



#include "graphics.h"
#include <SDL/SDL.h> // For SDL_Video
#include "game.h" // To interact with game elements
#include <math.h> // For sqrt()



Gfx::Gfx()
{
screen = 0;
}

Gfx::~Gfx()
{
SDL_FreeSurface( screen );
}


int Gfx::init()
{
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "Unable to init SDL: %s\n", SDL_GetError() );
return -1;
}

SDL_WM_SetCaption( "PongSDL", NULL );

screen = SDL_SetVideoMode( GFX_SCREEN_W, GFX_SCREEN_H, 32, SDL_SWSURFACE );

if( !screen )
{
printf( "Unable to set video: %s\n", SDL_GetError() );
return -1;
}

return 1;
}


void Gfx::draw( Gamestate* state )
{
// WIP
}




void Gfx::drawPixel( int x, int y )
{
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = 1;
rect.h = 1;

SDL_FillRect( screen, &rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );
}



/**
* End of graphics.cpp
*
**/



timer.h
/**
* timer.h
*
**/



#ifndef TIME_H
#define TIME_H



// Time is measured in seconds
class Timer
{
public:

Timer();
//~Timer();

void fillAccu();
bool pinchAccu( float dt );
float getTimePassed();

private:

float time_passed;
float current_time;
float accumulator;
float new_time;
float delta_time;

};



#endif // TIME_H

/**
* End of timer.h
*
**/



timer.cpp
/**
* timer.cpp
*
**/



#include "timer.h"
#include <SDL/SDL.h> // For SDL_GetTicks()



Timer::Timer()
: time_passed(0.00),
accumulator(0.00),
new_time(0.00),
delta_time(0.00)
{
current_time = (float)SDL_GetTicks() / 100;
}



void Timer::fillAccu()
{
new_time = (float)SDL_GetTicks() / 100;
delta_time = new_time - current_time;
current_time = new_time;

accumulator+= delta_time;
}


bool Timer::pinchAccu( float dt )
{
if( accumulator >= dt ) {
time_passed+= dt;
accumulator-=dt;

return true;
}

return false;
}


float Timer::getTimePassed()
{
return time_passed;
}



/**
* End of timer.cpp
*
**/



ball.h
/**
* ball.h
*
**/



#ifndef BALL_H
#define BALL_H



struct Ball
{
public:

float x;
float y;
float velx;
float vely;
float r;

};



#endif // BALL_H

/**
* End of ball.h
*
**/



ball.cpp
/**
* ball.cpp
*
**/



#include "ball.h"
#include "math.h"



Ball newBall( int x, int y, float velocity, float angle, float radius )
{
Ball b;

b.x = x;
b.y = y;

// Set velocities in px/s.
// 180.0*3.14 converts the angle from ° into rad
b.velx = velocity * cos( angle / 180.0 * 3.14 );
b.vely = velocity * sin( angle / 180.0 * 3.14 );

b.r = radius;

return b;
}


void updateBall( Ball* b, double dt )
{
b->x+= dt * b->velx;
b->y+= dt * b->vely;
}



/**
* End of ball.cpp
*
**/


Share this post


Link to post
Share on other sites
It's not usually a good idea to split up code unless you need to. Well organised code is a balance - 3000 line main files makes people cry, but having 20 or so files makes for irritating reading.

What error is your program kicking up? It might be a good idea to start with everything in main.cpp then just build up extra .h/.cpp files one at a time as needed (thats how I program anyway, and when it's just a one man project that tends to work fine).

'Picturing' a whole system of interconnected files and objects before implimenting it can be a whole job in itself (I think thats what software archietects do, but don't quote me on that), and when your task doesn't require you to do it, don't bother! Just take little steps. If it's something reasonably straightforward like pong maybe you coudl write it all in main(), then move components out into other files once you see groupings of functions or objects that can be put together logically.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!