Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411507 Posts in 69374 Topics- by 58429 Members - Latest Member: Alternalo

April 26, 2024, 06:15:53 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityTownhallForum IssuesArchived subforums (read only)TutorialsC++ SDL2 - Need Help with a tutorial issue
Pages: [1]
Print
Author Topic: C++ SDL2 - Need Help with a tutorial issue  (Read 5769 times)
ASnogarD
Level 1
*



View Profile
« 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
Level 10
*****


View Profile
« Reply #1 on: April 23, 2014, 03:30:07 AM »

Quote
The problem is he doesnt write out the whole code, just bits and pieces and expects the reader to fill in the 'basics'

 Wink ahem, maybe you could post some code?
Logged
ASnogarD
Level 1
*



View Profile
« 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
*



View Profile
« Reply #3 on: April 23, 2014, 03:39:26 AM »

SDLGameObject.h
Code:
#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
Code:
#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
Code:
#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
Code:
#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
*



View Profile
« 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
*



View Profile
« 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
*



View Profile
« Reply #6 on: April 23, 2014, 09:01:15 AM »

Thanks for the explanation , I appreciate it  Beer!
Logged

Somethings are painfully obvious, others must be made obvious... painfully.
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic