PDA

Voir la version complète : probleme de compilation...


ganlhi
26/07/2005, 13h05
Salut !
J'écris un petit jeu de shoot façon R-Type, grace à SDL.
J'avais une version fonctionelle en C, et j'ai décidé de la porter en C++.

J'utilise le principe des GameStates (http://www.games-creators.org/wiki/Gestion_des_Game_States_en_C_plus_plus) présentés sur le wiki, et je me heurte à un probleme de compilation de la classe CGameEngine, mais que sur mon code, alors que celui donné en exemple compile bien...

gameengine.h

#ifndef _GAMEENGINE_H_
#define _GAMEENGINE_H_

#include "common.h"
#include "configuration.h"
#include "gamestates.h"

class CGameState;

class CGameEngine
{
public:

CGameEngine();

void Init(const char *title);
void Cleanup();

void ChangeState(CGameState* state);
void PushState(CGameState* state);
void PopState();

void HandleEvents();
void Update();
void Draw();

bool Running() { return m_running; }
inline void Quit() { m_running = false; }

// ecran
SDL_Surface* screen;

private:
// pile de game states
vector<CGameState*> states;
// le jeu est-il en cours d'execution ?
bool m_running, m_fullscreen;
// configuration
Configuration config;
};

#endif


gameengine.cpp

#include "gameengine.h"

void CGameEngine::Init(const char *title)
{
Uint32 flags;

// chargement de la configuration
config.load();

// init du module video de SDL
if (SDL_Init(SDL_INIT_VIDEO) == -1)
{
fprintf(stderr,"Init SDL Video : %s\n",SDL_GetError());
exit(ERR_SDL_INIT);
}

// set the title bar text
SDL_WM_SetCaption(title, title);

// recuperation du booleen fullscreen
m_fullscreen = config.getFullscreen();

// reglages du module video de SDL
flags = config.getSdlVideoFlags();

if (m_fullscreen)
{
flags |= SDL_FULLSCREEN;
}

screen = SDL_SetVideoMode(config.getScreenX(),config.getScreenY(),config.getBpp(),flags);
printf("Mode video : %dx%dx%d\n",screen->w,screen->h,screen->format->BitsPerPixel);

// ne pas afficher le curseur de la souris
SDL_ShowCursor(0);

// demarrage
m_running = true;
}

void CGameEngine::Cleanup(void)
{
Uint32 flags;

// cleanup the all states
while (!states.empty())
{
states.back()->Cleanup();
states.pop_back();
}

// switch back to windowed mode so other
// programs won't get accidentally resized
if (m_fullscreen)
{
flags = config.getSdlVideoFlags() & (! SDL_FULLSCREEN);
screen = SDL_SetVideoMode(config.getScreenX(),config.getScreenY(),config.getBpp(),flags);
}

cout << "game engine cleaned !";

SDL_Quit();
}

void CGameEngine::ChangeState(CGameState* state)
{
// cleanup the current state
if ( !states.empty() ) {
states.back()->Cleanup();
states.pop_back();
}

// store and init the new state
states.push_back(state);
states.back()->Init();
}

void CGameEngine::PushState(CGameState* state)
{
// pause current state
if ( !states.empty() ) {
states.back()->Pause();
}

// store and init the new state
states.push_back(state);
states.back()->Init();
}

void CGameEngine::PopState(void)
{
// cleanup the current state
if ( !states.empty() ) {
states.back()->Cleanup();
states.pop_back();
}

// resume previous state
if ( !states.empty() ) {
states.back()->Resume();
}
}

void CGameEngine::HandleEvents()
{
// let the state handle events
states.back()->HandleEvents(this);
}

void CGameEngine::Update()
{
// let the state update the game
states.back()->Update(this);
}

void CGameEngine::Draw()
{
// let the state draw the screen
states.back()->Draw(this);
}


gamestates.h

#ifndef _GAMESTATES_H_
#define _GAMESTATES_H_

#include "common.h"

class CGameEngine;
#include "gameengine.h"

class CGameState
{
public:
virtual void Init() = 0;
virtual void Cleanup() = 0;

virtual void Pause() = 0;
virtual void Resume() = 0;

virtual void HandleEvents(CGameEngine* game) = 0;
virtual void Update(CGameEngine* game) = 0;
virtual void Draw(CGameEngine* game) = 0;

void ChangeState(CGameEngine* game, CGameState* state)
{
game->ChangeState(state);
}

protected:
CGameState() { }
};

#endif


erreur :

ganlhi@osiris shoot $ g++ -c gameengine.cpp `sdl-config --cflags`
In file included from gameengine.h:6,
from gameengine.cpp:1:
gamestates.h: Dans member function « void CGameState::ChangeState(CGameEngine*,
CGameState*) »:
gamestates.h:24: error: `ChangeState' undeclared (first use this function)
gamestates.h:24: error: (Each undeclared identifier is reported only once for
each function it appears in.)

Loulou
26/07/2005, 14h15
Problème d'inclusions cycliques. Tu as déjà la moitié de la solution, à savoir les déclarations anticipées. Ce qui te manque c'est ensuite d'inclure l'en-tête correspondant à la classe déclarée non plus dans le .h, mais dans le .cpp.

GameEngine.h

class CGameState; // déclaration anticipée

class CGameEngine
{
// ...
std::vector<CGameState*> ...
};


GameEngine.cpp

#include "Gamestates.h"

// ...

Et pareil pour l'autre classe si tu veux. De toute façon, généraliser les déclarations anticipées est une bonne chose : cela réduit les dépendances et par la même occasion le temps de compilation. Mieux vaut en abuser.

ganlhi
28/07/2005, 12h52
Bon, juste un post pour dire que ce probleme est résolu ! Merci Loulou !

* repart coder son jeu ===> *

ganlhi
28/07/2005, 13h56
bon, me revoila avec un autre probleme :

mon programme compile, mais à l'exécution, j'ai une erreur de segmentation.
voila le code du main :


#include "gameengine.h"
#include "menustate.h"
#include "common.h"

int main ( int argc, char *argv[] )
{
cout << "ZERO";
CGameEngine game;
cout << "UN";
// initialize the engine
game.Init( "Engine Test v1.0" );
cout << "DEUX";
// load the intro
game.ChangeState( CMenuState::Instance() );

// main loop
while ( game.Running() )
{
game.HandleEvents();
game.Update();
game.Draw();
}

// cleanup the engine
game.Cleanup();

return 0;
}


le truc bizarre c'est que meme le cout de la premiere ligne ne s'effectue pas. Pour info, iostream a bien été inclu, dans common.h.

Loulou
28/07/2005, 14h06
Essaye d'ajouter un "<< flush" pour forcer l'affichage avec cout. Si ça ne change rien alors c'est que le plantage intervient avant l'entrée dans le main, càd dans un objet déclaré statiquement ou globalement.

ganlhi
28/07/2005, 14h14
apres plusieurs tests à l'aide de cout, j'ai trouvé la portion de code provoquant l'erreur :

// init du module video de SDL
if (SDL_Init(SDL_INIT_VIDEO) == -1)
{
fprintf(stderr,"Init SDL Video : %s\n",SDL_GetError());
exit(ERR_SDL_INIT);
}


mais je ne vois pas pourquoi il y a une erreur...

TrizoLakai
28/07/2005, 14h29
pourquoi ne fait tu pas, cerr << "blabla" << SDL_GetError(); ?
Arives-tu as lancer un jeu en SDL? Peut etre te manque t-il quelque chose :00000010:

Loulou
28/07/2005, 15h25
apres plusieurs tests à l'aide de cout, j'ai trouvé la portion de code provoquant l'erreur
Les debuggers sont faits pour ça... :)
Tu as essayé un coup de debugging ?

ganlhi
28/07/2005, 17h48
TrizoLakai > En fait apres avoir posté, je l'ai modifié, mais comme je le dis dans le premier post, mon jeu était à l'origine en C, d'où le fprintf... D'ailleurs la version C et les autres jeux en SDL fonctionnent parfaitement...

Loulou > Je sais, mais au risque de passer pour un nul, je n'ai jamais pris le temps d'apprendre à me servir du debbuger. Mais je crois que je vais m'y mettre...

Loulou
28/07/2005, 18h40
Loulou > Je sais, mais au risque de passer pour un nul, je n'ai jamais pris le temps d'apprendre à me servir du debbuger. Mais je crois que je vais m'y mettre...
Ne t'inquiète pas, très peu de gens prennent le temps d'apprendre à l'utiliser. Je crois que si c'était le cas, la moitié des posts dont le titre contient "plantage" pourraient être évités.

Mais bon, faut dire que gdb en ligne de commande, perso j'ai lâché l'affaire (là c'est moi qui passe pour un nul :) ). J'ai trop pris l'habitude des IDE qui permettent de retrouver en un clic la ligne qui plante, avec la pile d'appels à droite et la valeur des variables à gauche.

ganlhi
28/07/2005, 19h37
Bon, je regarderai ça quand j'aurai le temps, mais en attendant, si quelqu'un a une idée, n'hésitez pas à m'en faire part ;)

ganlhi
29/07/2005, 10h48
Bon, je n'ai pas trop compris l'utilisation de gdb (à part qu'il m'a apris que le seg fault provoquait un SIGSERV...
Mais la question que je me pose : cette fonction SDL_Init(SDL_INIT_VIDEO) n'utilise aucune variable utilisée par moi... elle est entierement dépendante de SDL. Or j'ai ce meme programme écrit en C avec SDL qui marche parfaitement... Comprends pas...

ganlhi
29/07/2005, 11h32
bon, au temps pour moi... apres des tests plus poussés, il aparait que la seg fault arrive sur

fontMenu = TTF_OpenFont("fonts/vera.ttf", 32);


fonts/vera.ttf existe bien, et fontMenu est une variable de type TTF_Font*

Corkus
29/07/2005, 13h06
Utilise TTF_GetError() pour voir le probleme. Souvent c'est qu'il n'existe pas de police à la taille que tu as écrit.

ganlhi
29/07/2005, 13h14
Le truc, c'est que c'est un plantage, donc TTF_GetError ne s'exécutera pas... Mais de toute façon, dans ma version en C de ce jeu, j'utilisais cette police avec cette taille, et ça marchais...

EDIT : je viens d'essayer plusieurs tailles, et ça ne fonctionne pas...

Corkus
29/07/2005, 13h20
Peut tu montrer ton code? Ca sera plus facile.

ganlhi
30/07/2005, 11h00
Comme le code est un peu long je l'ai mis dans un fichier : http://ganlhi.homelinux.org/fichiers/others/srcshoot.rar

Par contre je suis désolé, il manque un peu de commentaires...

Donc la fonction qui pose probleme est dans le fichier menustate.cpp, dans la fonction CMenuState::Init...

Merci

ganlhi
30/07/2005, 17h40
Bon, je suis définitivement un boulet... J'ai oublié d'initialiser SDL_ttf avec TTF_Init()...

Désolé pour le dérangement ! dès que je serai devant mon PC, je testerai ça, mais à priori ça devrait résoudre le probleme.

Corkus
30/07/2005, 17h54
Hum j'ai vu une autre erreur.

Dans gameengine.cpp, tu as oublié d'initialiser l'objet config.

Étant donné que config est un pointeur, tu dois initialiser config dans le tas par la manière suivante:

config = new Configuration();


Non erreur de ma part. Ca à l'air de marcher pour le moment