Beginner trying to learn inheritance with game programming - c++

I'm trying to make a framework for an SFML game I'm making and I'm having trouble with inheritance. I thought I knew how to do it but it doesn't seem right. I want my main to just call GameLoop basically and thats it. In my GameLoop class I have methods for making the window and running the game. Then I want my GamePlayScreen class to actually handle the game logic but for some reason I can't figure out how to inherit from GameLoop. I was watching a video and the guy was using C# which is why I'm having trouble converting it. The video is https://www.youtube.com/watch?v=WhbeqOOSDEo&index=2&list=PLfTDIoEcaNroztBVGPA0aU3NbOauRVIe3.
GameLoop.h
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <string>
class GameLoop
{
public:
GameLoop(int width, int height, std::string title);
virtual void Run();
virtual void LoadContent();
virtual void Initialize();
virtual void Update();
virtual void Render();
sf::RenderWindow window;
};
GameLoop.cpp
#include "GameLoop.h"
GameLoop::GameLoop(int width, int height, std::string title)
{
window = sf::RenderWindow(sf::VideoMode(width, height), title, sf::Style::Default);
}
void GameLoop::Run()
{
LoadContent();
Initialize();
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
Update();
window.clear();
Render();
window.display();
}
}
void GameLoop::LoadContent()
{
}
void GameLoop::Initialize()
{
}
void GameLoop::Update()
{
}
void GameLoop::Render()
{
}
GamePlayScreen.h
#pragma once
#include "GameLoop.h"
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
class GamePlayScreen : public GameLoop
{
public:
GamePlayScreen();
void Initialize();
};
GamePlayScreen.cpp
#include "GamePlayScreen.h"
GamePlayScreen::GameLoop(800, 600, "Game");
{
}
void GamePlayScreen::Initialize()
{
GameLoop game(800, 600, "Game");
}

The constructor will be called automatically when you 'new' the class. Just make a matching constructor in GamePlayScreen and the system will call the derived constructor first - but the signature must match.
class GamePlayScreen : public GameLoop
{
public:
GamePlayScreen();
GamePlayScreen(int width, int height, std::string title);
void Initialize();
};

Maybe this is not a real answer but I can not comment.
As I can see main subject is about "Handling Multiple Screens".
So you may look at this tutorial: https://github.com/SFML/SFML/wiki/Tutorial:-Manage-different-Screens

Related

SFML Ambiguous conversion from derived class when implementing draw function

I am trying to create by own game engine where each basic is a GameObject which will consist of an update function and other notifiers.
Here is my code so far:
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "AssetManager.hpp"
class GameObject : public sf::Drawable, public sf::Transformable
{
public:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
target.draw(*this, states);
};
};
class Sprite : public GameObject, public sf::Sprite {
public:
Sprite(AssetManager assetManager, std::string assetName) : sf::Sprite(){
setTexture(assetManager.getTextureNamed(assetName));
}
};
int main(int argc, char const** argv)
{
sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
AssetManager assetManager = AssetManager("/Users/iProgram/Desktop/My Game Engine/My Game Engine");
assetManager.loadTextureWithName("tank", "tank.png", sf::Vector2f(16,16));
Sprite tank = Sprite(assetManager, "tank");
while(window.isOpen()){
window.clear();
window.draw(tank);
window.display();
}
return EXIT_SUCCESS;
}
Please note, the asset manager simply stores textures in memory and returns it when needed with a given size.
The problem is on the line: window.draw(tank);, I am getting the error
Ambiguous conversion from derived class 'const Sprite' to base class 'const sf::Drawable':
Why is this as I have implemented the draw function in the GameObject class and how can I fix it?
Your Sprite class inherits from GameObject which inherits from sf::Drawable. Your class also inherits from sf::Sprite which also inherits from sf::Drawable. Now your Sprite class has 2 inherited sf::Drawable subobjects and the compiler can't choose.
To fix this, either rethink your design or inherit virtually.
To solve this issue, I dod not have to use private inheritance as some suggested, I just needed my base class (GameObject) to inherit nothing. My Sprite class would then inherit sf::Sprite like so:
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "AssetManager.hpp"
class GameObject{
public:
virtual void update(){}
};
class Sprite : public GameObject, public sf::Sprite {
public:
Sprite(AssetManager* assetManager, std::string assetName) : sf::Sprite(assetManager->getTextureNamed(assetName)){
}
};
class Tank: public Sprite{
public:
Tank(AssetManager* assetManager) : Sprite(assetManager, "tank"){
setScale(3, 3);
};
virtual void update(){
move(1,0);
}
};
int main(int argc, char const** argv)
{
sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
AssetManager* assetManager = new AssetManager("/Users/iProgram/Desktop/My Game Engine/My Game Engine");
assetManager->loadTextureWithName("tank", "tank.png", sf::Vector2f(16,16));
Tank tank = Tank(assetManager);
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if(event.type == sf::Event::Closed){
window.close();
}
}
tank.update();
window.clear();
window.draw(tank);
window.display();
}
return EXIT_SUCCESS;
}

C++ error: cannot declare variable 'block' to be of abstract type 'AABB'

I just started writing a simple game in SFML 2.0.
I created class AABB with inheritance two class from SFML to write in class draw() method.
But i get all the time this error:
\main.cpp|14|error: cannot declare variable 'block' to be of abstract type 'AABB'|
code:
#include <SFML/Graphics.hpp>
#include <vector>
#include <iostream>
#include "headers/system.h"
#include "headers/AABB.h"
using namespace std;
int main()
{
sf::RectangleShape shape(sf::Vector2f(50,50));
AABB block (shape);
System sys;
if(!sys.create())
{
cout << "Critical error! Did you modified ini files?";
return EXIT_FAILURE;
}
sf::RenderWindow * WindowApp = sys.getHandle();
while (WindowApp->isOpen())
{
sf::Event event;
while (WindowApp->pollEvent(event))
{
if (event.type == sf::Event::Closed)
WindowApp->close();
if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
WindowApp->close();
}
WindowApp->draw(block);
WindowApp->clear();
WindowApp->display();
}
return EXIT_SUCCESS;
}
AABB.h:
#include <SFML\Graphics.hpp>
#include <SFML\System.hpp>
#include <SFML\Audio.hpp>
#include <SFML\Network.hpp>
using namespace std;
class AABB : public sf::Drawable, public sf::Transformable
{
public:
AABB(sf::Vector2f pos, sf::Vector2f size) :
m_pos(pos),
m_size(size) {}
AABB(sf::RectangleShape shape) :
m_sprite(shape)
{}
private:
virtual void draw(sf::RenderTarget& target) const ;
private:
sf::Vector2f m_size;
sf::Vector2f m_pos;
sf::RectangleShape m_sprite;
};
AABB.cpp
#include "../headers/AABB.h"
using namespace std;
void AABB::draw(sf::RenderTarget& target) const
{
target.draw(m_sprite);
}
system class is not important here i think :D
BTW when I remove inheritance from class app compile without errors. What i suppose to do ? Please help me :)
Your class AABB inherits sf::Drawable, which is an abstract class, and AABB does not override all pure virtual functions of it -- which would be necessary to make AABB a concrete class and to have objects of it. I suspect that this is the result of a typo. Where you write
virtual void draw(sf::RenderTarget& target) const ;
in AABB.h, it should be
virtual void draw(sf::RenderTarget& target, sf::RenderStates) const ;
because the latter is the signature of sf::Drawable's pure virtual function, as is described in the SFML documentation. You will have to change the definition of this function in AABB.cpp as well, naturally.

C++ creating an instance of a class

class Game {
private:
string title;
bool running;
State currentState;
public:
sf::RenderWindow window;
void setup();
void run();
};
I have a variable called currentState. This is State:
#ifndef STATE_HPP
#define STATE_HPP
using namespace std;
class State {
private:
public:
void start();
void update();
void render();
};
#endif
And then I have a class called PlayState, which inherits State:
#ifndef PLAY_STATE_HPP
#define PLAY_STATE_HPP
#include <SFML/Graphics.hpp>
#include "Game.hpp"
#include "State.hpp"
using namespace std;
class PlayState : public State {
private:
sf::CircleShape shape;
Game game;
public:
PlayState();
void start();
void update();
void render();
};
#endif
On my Game.cpp, I am creating currentState, by doing:
currentState = PlayState();
The problem is, though, that it's not working. currentState.update() is state.update(). It seems that I am not overriding the State methods when I create PlayState.
Here's PlayState.cpp:
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <stdio.h>
#include "PlayState.hpp"
PlayState::PlayState() {
printf("heyyy\n");
}
void PlayState::start() {
shape.setRadius(100.f);
shape.setOrigin(20.0f, 20.0f);
shape.setFillColor(sf::Color::Green);
}
void PlayState::update() {
sf::Event event;
while (game.window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
game.window.close();
//running = false;
}
}
printf("here\n");
}
void PlayState::render() {
printf("here\n");
game.window.clear();
game.window.draw(shape);
game.window.display();
}
Any ideas about how I can 'override' those methods? Thank you.
EDIT
I had to make State.cpp functions virtual so that they can be overriden.
I also had to define State *currentState as a pointer and create PlayState with "currentState = new PlayState();".
Also, now I access .update and .draw with ->update() and ->draw().
Two problems. As #McAden said, the functions in State that are to be overridden in PlayState need to be marked virtual. The other problem is that the data member currentState in Game has type State. When you assign an object of type PlayState to it, it gets the State part of the PlayState object, but not the derived parts. This is called "slicing". To prevent it, make currentState a pointer to State, and when you create that PlayState object, assign its address to the Game object's currentState.
What you're looking for is the concept of virtual functions.
Wikipedia entry
State needs:
virtual void update();
PlayState needs:
void update();
You need to make your function's with the virtual modifier ie.
virtual void Update();
When calling currentState->Update() this will call the topmost overridden function, if you desire to call any of the parent classes functions inside of the classes methods simply specify ie. State::Update(); when calling the function.

i need help implementing my event manager and engine system (SDL && C++)

i need help with my attempt at writing a reusable game engine. it's not the best engine, but i definitely think it will be reusable once i am done. i am not asking for code or to be spoonfed, but i am asking for some advice :-).
my current layout:
i have an engine class, a game class, and an event manager class. the engine class extends the event manager class, and the game class extends the engine class. here is my current code for these 3 classes (ignore the Graphics class--it is just a reusable class i use to avoid rewriting fullscreen, initialize, and resize screen functions).
ENGINE.HPP
#ifndef _ENGINE_HPP
#define _ENGINE_HPP
#pragma once
#include <SDL/SDL.h>
#include "event_manager.hpp"
enum
{
ENGINE_SUCCESS = 0,
ENGINE_INITIALIZATION_ERROR
};
class Engine : public EventManager
{
public:
Engine();
virtual ~Engine();
int exec();
void handle_event(SDL_Event *);
void update_engine();
virtual bool init();
virtual void render();
virtual void update();
virtual void clean();
bool running_;
};
ENGINE.CPP
#include "./engine.hpp"
Engine::Engine()
{
running_ = false;
}
Engine::~Engine()
{
}
int Engine::exec()
{
if (!init())
{
clean();
return ENGINE_INITIALIZATION_ERROR;
}
SDL_Event event;
while (running_)
{
while (SDL_PollEvent(&event))
handle_event(&event);
update();
render();
}
clean();
return ENGINE_SUCCESS;
}
void update_engine()
{
}
void handle_event(SDL_Event *event)
{
EventManager::handle_event(event);
}
bool init() {return true;}
void render() {}
void update() {}
void clean() {}
EVENT_MANAGER.HPP
#ifndef _EVENT_MANAGER_HPP
#define _EVENT_MANAGER_HPP
#pragma once
#include <SDL/SDL.h>
class EventManager
{
public:
EventManager();
virtual ~EventManager();
virtual void handle_event(SDL_Event *);
// events here
virtual void event_exit();
};
#endif
EVENT_MANAGER.CPP
#include "./event_manager.hpp"
EventManager::EventManager()
{
}
EventManager::~EventManager()
{
}
void EventManager::handle_event(SDL_Event *event)
{
switch (event->type)
{
case SDL_QUIT:
event_exit();
break;
}
}
void on_exit() {}
GAME.HPP
#ifndef _GAME_HPP
#define _GAME_HPP
#include "./engine.hpp"
#include "./entity.hpp"
#include "./graphics.hpp"
class Game : public Engine
{
public:
Game();
bool init();
void render();
void update();
void clean();
private:
Graphics g;
};
#endif
GAME.CPP
#include "./game.hpp"
int main(int argc, char **argv)
{
Engine engine;
return engine.exec();
}
Game::Game() {}
bool Game::init()
{
if (!g.init(800, 600, 32, g.screen_flags()))
{
return false;
}
SDL_WM_SetCaption("Title", NULL);
return true;
}
void Game::update()
{
Engine::update_engine();
}
void Game::clean()
{
SDL_FreeSurface(g.screen_);
SDL_Quit();
}
void Game::render()
{
SDL_Flip(g.screen_);
}
i am getting this error:
engine.cpp: In function ‘void handle_event(SDL_Event*)’:
engine.cpp:40: error: cannot call member function ‘virtual void
EventManager::handle_event(SDL_Event*)’ without object
why is this happening? shouldn't i be able to do EventManager:: if the I did
class Engine : public EventManager
???
that is the only error i get, i am sure it is something simple. now i need a little bit of advice.
instead of handling events like
void Engine::event_exit()
in the engine, i'd rather do it in the game class.
class Game : public Engine
void Game::event_exit()
if that doesn't make sense, notice how i made Engine extend EventManager, and my Game class extends Engine
class Engine : public EventManager
class Game : public Engine
would it work if i called the snippet above these ^ two snippets? i can't test it because i get that error.
Happens to the best of us, but I think it's just a matter of forgetting to specify namespaces. When you implement the functions in engine.cpp, you forgot to prepend Engine::, so the code should be:
void Engine::update_engine()
{
}
void Engine::handle_event(SDL_Event *event)
{
EventManager::handle_event(event);
}
It's a classic case of C++ error messages not really telling you the root of the error.
A short explanation, just in case:
The compiler tried to compile the function void handle_event(SDL_Event *event), and saw a call to a method EventManager::handle_event(event);. Since the compiler thought the function was not part of the Engine class, it would expect you to call the method of a particular instance of the EventManager class, i.e.
someEventManager->handle_event(event);
As soon as you specify that the implementation you wrote is that of a method, belonging to the class Engine, the compiler essentially deduces:
void Engine::handle_event(SDL_Event *event)
{
this->EventManager::handle_event(event);
}
And therefore is happy.

SFML pass renderwindow

Im trying to make a game with the SFML.
I'm making a sf::RenderWindow but when I try to pass the window to another class
it fails. I can't access the window. Because I think it's good to make a separate
class for handling events like 'close the window' etc. but then I can't access it. How
can I fix this?
RenderWindow *window;
window = new RenderWindow(VideoMode(768, 614), "Tower Defence ver 2.0");
Create yourself a header file and define your function like so
Header file
#pragma once
#include "SFML/Graphics.hpp"
class MyClass
{
public:
sf::Sprite Sprite;
MyClass();
void Setup(sf::Texture& texture);
void Draw(sf::RenderWindow& window);
};
Cpp file
#include "Bullet.h"
MyClass::MyClass()
{
}
void MyClass::Setup(sf::Texture& texture)
{
Sprite.setTexture(texture);
Sprite.setPosition(0, 0);
}
void MyClass::Draw(sf::RenderWindow& window)
{
window.draw(Sprite);
}
Then in your game loop for drawing you can call something like this
// myClass is an object of type MyClass
// renderWindow is your sf::RenderWindow object
myClass.Draw(renderWindow);
Hope this helps. Let me know if you need any more guidance.
RenderWindow is in a namespace 'sf'
Maybe you have somewhere "using namespace sf;" and it's missing in other places.
Try prefixing it with sf::RenderWindow everywhere.
Which version of SFML are you using? This is not possible in SFML 1.6, but is in SFML 2.0 (upcoming version).
try this
class Foo
{
public:
Foo(sf::RenderWindow& ptrwindow)
: ptrwindow(ptrwindow)
{
// your code here
};
sf::RenderWindow* window()
{
return &this->ptrwindow;
}
private:
sf::RenderWindow ptrwindow;
};
int main()
{
sf::RenderWindow* mywindow = new sf::RenderWindow()
Foo myfoo(*mywindow);
myfoo.window()->create(sf::VideoMode(768, 614), "Tower Defence ver 2.0")
}