ASnogarD
Level 1
|
|
« on: April 23, 2014, 02:50:16 AM » |
|
EDIT: Got it working , my last post explains the error, it was in the Game.h constructor... changing the constructor from Game(); to Game() {} fixed the issue...why ? No idea TBH.
Hi guys,
Hoping you can help me out here as I am in a bit of a bind...
The issue is I am working my way through Shaun Mitchell's SDL Game Development book, and its pretty crap regarding code and the samples, and I have hit a wall at chapter 3 where he is describing objects and inheritance. The problem is he doesnt write out the whole code, just bits and pieces and expects the reader to fill in the 'basics' but while I was able to work out everything until the last piece of the chapter but now I got an issue I am stumped with.
The problem as I see it is that the code has a cyclic reference issue, with a singleton added to the mess... basically one class that refers to objects in a inherited base class is a singleton reference by a static declaration, but a class that inherits from the base class needs to refer to one of the singletons accessor functions. Simple forward declaration doesnt work, including the singleton header file in the actual cpp file for the derived class lets it compile but fails in the linker with a undefined declaration (it doesnt know the singletons static declared variable used to access the function). The singleton class needs to access the base file and / or the inherited classes of that base file, but one of the inherited classes refers to the singleton.
I have downloaded the books sample codes but in keeping with this crappy books style, the sample codes in the download... are completely different, to the point the actual classes in the chapter dont exist in the official publisher obtained none pirated samples... so I cant even study that to see what I need to do.
I am in a bind here as I have some time off work and want to use that time to 'catch' up with my coding, so I dont want to 'waste' too much time fighting this but I cant just skip it as the book builds on previous code... if this doesnt compile the later stuff wont work either.
Thank you for reading.
|
|
« Last Edit: April 23, 2014, 05:50:55 AM by ASnogarD »
|
Logged
|
Somethings are painfully obvious, others must be made obvious... painfully.
|
|
|
nikki
|
|
« Reply #1 on: April 23, 2014, 03:30:07 AM » |
|
The problem is he doesnt write out the whole code, just bits and pieces and expects the reader to fill in the 'basics' ahem, maybe you could post some code?
|
|
|
Logged
|
|
|
|
ASnogarD
Level 1
|
|
« Reply #2 on: April 23, 2014, 03:36:13 AM » |
|
I will try explain in more detail.
The code so far just puts up a few animate pictures using fairly standard surface -> texture coding with the exception that the TextureManager is also a singleton but is not an issue in this case.
The issue is that a class called Game is used to init SDL, load textures and calls the object load and initialises the starting values for the objects, and Game is a singleton referred to as TheGame::Instance()->functioncallhere(). Objects in the code are created via a base Class called GameObjects, which is pure virtual, and a SDLGameObjects class inherits this GameObjects, and Player and Enemy classes inherit the SDLGameObjects class. SDLGameObjects uses a function in Game to access the textureID for the draw function, so it needs to know about Game and the static instance of Game that is referred as TheGame::Instance->. Game though needs to know about SDLGameObjects, Player and Enemy to call those classes draw functions.
If I include the SDLGameObjects , GameObjects , Player and Enemy classes in the Game.h ... AND include Game.h in the SDLGameObjects.cpp file it compiles but fails in linking as it cannot resolve the call to the static instance in the Game class. Remove that Game.h include in the SDLGameObject.cpp, and it fails to compile as considers all the inherited classes as undefined declarations. I have tried to add Game as a forward declaration by typing class Game; in the SDLGameObjects.h , even tried to pass it a function prototype for the accessor function the SDLGameObjects class uses from Game with no luck... it still doesnt compile SDLGameObjects and thus messes up the other child classes. Working the other way around and trying to declare the SDLGameObjects AND child classes in Game fails the same way.
|
|
|
Logged
|
Somethings are painfully obvious, others must be made obvious... painfully.
|
|
|
ASnogarD
Level 1
|
|
« Reply #3 on: April 23, 2014, 03:39:26 AM » |
|
SDLGameObject.h #ifndef __SDLGAMEOBJECT__ #define __SDLGAMEOBJECT__
#include"GameObject.h"
class SDLGameObject : public GameObject { public:
SDLGameObject(const LoaderParams* pParams);
virtual void draw(); virtual void update(); virtual void clean();
protected:
int m_x; int m_y;
int m_width; int m_height;
int m_currentRow; int m_currentFrame;
std::string m_textureID;
};
#endif SDLGameObjects.cpp #include"SDLGameObject.h" #include"Game.h"
SDLGameObject::SDLGameObject(const LoaderParams* pParams) : GameObject(pParams) {
m_x = pParams->getX(); m_y = pParams->getY(); m_width = pParams->getWidth(); m_height = pParams->getHeight();
m_textureID = pParams->getTextureID();
m_currentRow = 1; m_currentFrame = 1; }
void SDLGameObject::draw() { TheTextureManager::Instance()->drawFrame(m_textureID, m_x, m_y, m_width, m_height, m_currentRow, m_currentFrame, TheGame::Instance()->getRenderer()); }
void SDLGameObject::update() {}
void SDLGameObject::clean() {} Game.h #ifndef __Game__ #define __Game__
// includes #include<iostream> #include<vector>
#include"SDL.h" #include"SDL_image.h" #include"TextureManager.h" #include"GameObject.h" #include"Player.h" #include"Enemy.h"
class Game { public: // create a public instance function static Game* Instance() { if(s_pInstance == 0) { s_pInstance = new Game(); return s_pInstance; }
return s_pInstance; }
// simply set the running variable to true bool init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
void render(); void update(); void handleEvents(); void clean();
// a function to access the private running variable
bool running() { return m_bRunning; }
SDL_Renderer* getRenderer() const { return m_pRenderer; }
private:
Game(); ~Game();
// create the s_pInstance member variable static Game* s_pInstance; SDL_Window* m_pWindow; SDL_Renderer* m_pRenderer;
int m_currentFrame; bool m_bRunning;
/* // temp def objects for GameObject class test GameObject *m_go; GameObject *m_player; GameObject *m_enemy; */
std::vector<GameObject*> m_gameObjects; };
typedef Game TheGame;
#endif
Game.cpp #include"Game.h"
Game* Game::s_pInstance = 0;
bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) { // set flags int flags = 0;
if(fullscreen) { flags = SDL_WINDOW_FULLSCREEN; }
// initialise SDL if(SDL_Init(SDL_INIT_EVERYTHING) == 0) { std::cout << "SDL init OK\n";
// create window m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
// check window was created successfully if(m_pWindow != 0) { std::cout << "window created OK\n";
// create renderer m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
// check renderer was created successfully if(m_pRenderer !=0) { std::cout << "renderer created OK\n";
//set renderer draw colour SDL_SetRenderDrawColor(m_pRenderer, 255, 0, 0, 255); } else { std::cout << "Renderer failed\n"; return false; } } else { std::cout << "Window failed\n"; return false; } } else { std::cout << "SDL Init Fail\n"; return false; } std::cout << "initialisation OK\n";
// set running to true m_bRunning = true;
// loading textures std::cout << "loading images and textures..... \n" ; if(!TheTextureManager::Instance()-> load("Data/GFX/animate-alpha.png", "animate", m_pRenderer)) { //error loading return false; }
m_gameObjects.push_back(new Player(new LoaderParams(100, 100, 128, 82, "animate")));
m_gameObjects.push_back(new Enemy(new LoaderParams(300, 300, 128, 82, "animate")));
return true; }
void Game::render() { // clear renderer SDL_RenderClear(m_pRenderer);
// pass to renderer // loop through vector array of objects for(std::vector<GameObject*>::size_type i = 0;i != m_gameObjects.size(); i++) { m_gameObjects[i]->draw(); }
// draw renderer to screen SDL_RenderPresent(m_pRenderer); }
void Game::update() { // loop through vector array of objects for(std::vector<GameObject*>::size_type i = 0;i != m_gameObjects.size(); i++) { m_gameObjects[i]->update(); } }
void Game::handleEvents() { SDL_Event event; if(SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: m_bRunning = false; break;
default: break; } } }
void Game::clean() { std::cout << "cleaning game\n"; SDL_DestroyWindow(m_pWindow); SDL_DestroyRenderer(m_pRenderer); SDL_Quit(); }
|
|
|
Logged
|
Somethings are painfully obvious, others must be made obvious... painfully.
|
|
|
ASnogarD
Level 1
|
|
« Reply #4 on: April 23, 2014, 05:49:27 AM » |
|
I found the fault, but it destroys my confidence in the book even more...
By removing elements that referred to the Game singleton, just to see if the rest of the code was fine I noted the link error still present despite there being no call to the Game singleton by SDLGameObject.
I then focused on checking the Game.h and Game.cpp code, which by the book was fine but I referred to the other singleton , the TextureManager class, and noted its contructor and the one in Game was different so I change the contructor in Game from
Game();
to
Game() {}
and the code works.
I will be honest and admit I have NO idea why ... I mean if you dont define the constructor it simply make default on that is empty, unless I am mistaken...so essentially there is no difference, just the code seems to work with one and not the other.
|
|
|
Logged
|
Somethings are painfully obvious, others must be made obvious... painfully.
|
|
|
Cheesegrater
Level 1
|
|
« Reply #5 on: April 23, 2014, 07:55:32 AM » |
|
Game(); does define the constructor. It does not implement it, so there should have been a matching implementation in Game.cpp. It was missing, so you get the linker error.
Game() {} both defines and implements the constructor.
You get the autogenerated default constructor if you omit the definition entirely.
|
|
|
Logged
|
|
|
|
ASnogarD
Level 1
|
|
« Reply #6 on: April 23, 2014, 09:01:15 AM » |
|
Thanks for the explanation , I appreciate it
|
|
|
Logged
|
Somethings are painfully obvious, others must be made obvious... painfully.
|
|
|
|