I need to create a thread to run the Networking portion of my game. I would prefer to use SFML threads as my compiler doesn't yet support C++11 threads. However the class which contains the thread is created with make_shared(). Here is the code:
Game.cpp (not all the code just the declaration of GameScreen)
std::shared_ptr<Screen> Game::screen = std::make_shared<GameScreen>();
Screen is just a base class containing pure virtual functions. You should be able to figure out which ones are virtual based off the override keywords.
GameScreen.h
#ifndef GAMESCREEN_H
#define GAMESCREEN_H
#include <SFML/Graphics.hpp>
#include "Events.h"
#include "Screen.h"
#include "Map.h"
#include "Network.h"
class GameScreen : public Screen
{
public:
GameScreen();
void handleInput(sf::RenderWindow&) override;
void update(sf::RenderWindow&, sf::View&) override;
void render(sf::RenderWindow&) override;
private:
Map m_map;
Network network;
Events eventManager;
sf::Thread networkThread;
};
#endif // GAMESCREEN_H
GameScreen.cpp
#include <memory>
#include <iostream>
#include "GameScreen.h"
#include "Game.h"
GameScreen::GameScreen()
: networkThread(network.receive(eventManager))
{
network.Connect();
}
void GameScreen::handleInput(sf::RenderWindow& window)
{
/*Code*/
}
void GameScreen::update(sf::RenderWindow& window, sf::View& view)
{
/*Code*/
}
void GameScreen::render(sf::RenderWindow& window)
{
/*Code*/
}
Network.cpp (receive function only)
void Network::Recieve(Events& eManager)
{
sf::Packet m_rPacket;
m_socket.receive(m_rPacket, m_serverIP, port);
m_rPacket >> /*Data*/
eManager.addEvent(tmp);
}
You can use this in the constructor's initialization list:
MyClass::MyClass()
: AClass(&MyFunction(*this))
{
/*do stuff*/
}
However, this doesn't make sense in your example, because you are trying to pass a pointer to MyFunction (or its non-existent return value) to AClass(), and you can't quality a pointer with parameters. You can only pass parameters to MyFunction() when actually calling MyFunction(). Are you sure you don't actually mean something more like this instead:
MyClass::MyClass()
: AClass()
{
/*do stuff*/
MyFunction(*this);
}
Without seeing what AClass() actually is, or what it expects as input, it is difficult to know for sure what you are trying to do.
Update clearly you have not read the SFML documentation or SFML Tutorial on threading. The Thread constructor takes a pointer to a function/method as one input parameter, and an optional input value for the function/method as a separate parameter. Try this instead:
class MyClass : public sf::Thread
{
private:
static void MyFunction(MyClass &cls);
public:
MyClass();
};
MyClass::MyClass()
: sf::Thread(&MyClass::MyFunction, *this)
{
/*do stuff*/
}
void MyClass::MyFunction(MyClass &cls)
{
/*do stuff with 'cls'*/
}
Or this, as you can use a non-static class method with an SFML thread:
class MyClass : public sf::Thread
{
private:
void MyFunction();
public:
MyClass();
};
MyClass::MyClass()
: sf::Thread(&MyClass::MyFunction, *this)
{
/*do stuff*/
}
void MyClass::MyFunction()
{
/*do stuff with 'this'*/
}
Update: based on your new code, you are still not even close to constructing the sf::Thread object correctly (did you read the documentation/tutorial I linked to?). Also, your thread needs access to multiple objects owned by GameScreen, so you can't pass them all to the sf::Thread constructor. You need to do something more like this instead:
class GameScreen : public Screen
{
public:
GameScreen();
...
private:
...
Network network;
Events eventManager;
sf::Thread networkThread;
void networkThreadFunc();
};
GameScreen::GameScreen()
: networkThread(&GameScreen::networkThreadFunc, *this)
{
network.Connect();
}
void GameScreen::networkThreadFunc()
{
network.Receive(eventManager);
}
Related
I am trying to connect a gui to my logic thread using boosts signals and slots, the logic class has a neat method to connect functions to the signal.
Here is a simplified replica of the locig class:
#include <boost/signals2.hpp>
#include <boost/function.hpp>
typedef boost::signals2::signal<void (const double&)> some_signal;
typedef some_signal::slot_type some_slot;
class LogicClass {
some_signal sig;
public:
LogicClass();
~LogicClass();
void register_callback(boost::function<void (const double&)>) {
sig.connect(boost::bind(&LogicClass::doStuff(), this, _1));
}
void doStuff(); // Does a bunch of stuff in a separate thread and fires LogicClass::sig every now and then
}
Here is a simplified replica of the gui class
#include <boost/signals2.hpp>
#include <QWidget.h>
class GuiClass : public QWidget {
Q_OBJECT //etc. etc. w.r.t. Qt stuff
public:
GuiClass ();
~GuiClass ();
void draw_stuff(const double&); // Want this to listen to LogicClass::sig;
}
At some point in my code the gui class is already instantiated but the logic class isn't. So i want to instantiate the LogicClass and subscribe the GuiClass::draw_stuff(const double&) to the LogicClass::sig signal. Something like
#include <logicclass.h>
#include <guiclass.h>
GuiClass *gui; //Was initialized elsewhere, but available here;
void some_function() {
LogicClass *logic = new LogicClass();
logic->register_callback(gui->drawStuff);
logic->do_stuff(); //Start drawing on the gui
delete logic;
}
This unfortunately doesn't work. Goes without saying it would like it to work very much!
I know Qt also implements signals & slots, but i would like to use boost for portability with other UI libraries.
Looks like you meant to bind draw_stuff instead of hardcoded doStuff inside of that register function:
logic->register_callback(boost::bind(&GuiClass::draw_stuff, gui, _1));
And then
void register_callback(boost::function<void(double)> handler) {
sig.connect(handler);
}
Simple Demo
Live On Coliru
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
#include <iostream>
typedef boost::signals2::signal<void(double)> some_signal;
typedef some_signal::slot_type some_slot;
class LogicClass {
some_signal sig;
public:
LogicClass() = default;
~LogicClass() = default;
void register_callback(boost::function<void(double)> handler) {
sig.connect(handler);
}
void doStuff() {
std::cout << __PRETTY_FUNCTION__ << "\n";
// Does a bunch of stuff in a separate thread and fires LogicClass::sig every now and then
boost::thread([this] {
for (double d : {1,2,3}) {
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
sig(d);
}
}).join();
}
};
#define Q_OBJECT
struct QWidget {};
class GuiClass : public QWidget {
Q_OBJECT // etc. etc. w.r.t. Qt stuff
public:
GuiClass() = default;
~GuiClass() = default;
void draw_stuff(double v) { std::cout << __PRETTY_FUNCTION__ << "(" << v << ")\n"; }
};
//#include <logicclass.h>
//#include <guiclass.h>
GuiClass *gui; // Was initialized elsewhere, but available here;
void some_function() {
LogicClass *logic = new LogicClass();
logic->register_callback(boost::bind(&GuiClass::draw_stuff, gui, _1));
logic->doStuff(); // Start drawing on the gui
delete logic;
}
int main() {
GuiClass gui_instance;
gui = &gui_instance;
some_function();
}
Prints
void LogicClass::doStuff()
void GuiClass::draw_stuff(double)(1)
void GuiClass::draw_stuff(double)(2)
void GuiClass::draw_stuff(double)(3)
I have two classes: AbstractClass and SubClass.
This is basically my code (well, just some example code):
abstractclass.h
class AbstractClass
{
public:
AbstractClass();
void doSomething();
protected:
virtual void implementMe() = 0;
int a;
};
abstractclass.cpp
#include "abstractclass.h"
AbstractClass::AbstractClass(){}
void AbstractClass::doSomething()
{
implementMe(); // compiler error: "implementMe() was not declared in this scope"
a = 0; // same compiler error here...
}
subclass.h
#include "abstractclass.h"
class SubClass : public AbstractClass
{
public:
SubClass();
protected:
void implementMe();
};
subclass.cpp
#include "subclass.h"
SubClass::SubClass() {}
void SubClass::implementMe()
{
// do some stuff
}
In the AbstractClass, however, I keep getting a compiler error (for the virtual function as well as for the class variable):
implementMe() was not declared in this scope
The only way I found to get rid of this was to use forward-declaration:
void implementMe();
AbstractClass::doSomething()
{
implementMe();
}
I cannot believe that this is the correct way, though?
Thanks!
EDIT:
Ok, as my conceptual understanding of subclassing in C++ doesn't seem to be totally wrong (see the comments), I'm gonna share some of my original source code. Hopefully this will help to indentify the error.
This is my abstract / base class:
abstractenvironment.h
#ifndef ABSTRACTENVIRONMENT_H
#define ABSTRACTENVIRONMENT_H
#include <QObject>
class AbstractEnvironment : public QObject
{
Q_OBJECT
public:
AbstractEnvironment(QObject *parent = 0);
protected:
virtual void process() = 0;
quint32 counter;
private slots:
void handleTimeout();
};
#endif // ABSTRACTENVIRONMENT_H
abstractenvironment.cpp
#include "abstractenvironment.h"
#include <QTimer>
QTimer *myTimer;
AbstractEnvironment::AbstractEnvironment(QObject *parent) :
QObject(parent)
{
myTimer = new QTimer(this);
connect(myTimer, &QTimer::timeout, this, &AbstractEnvironment::handleTimeout);
myTimer->start(1);
counter = 0;
}
void handleTimeout()
{
process();
counter++;
}
And this is my subclass:
environment.h
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
#include "abstractenvironment.h"
class Environment : public AbstractEnvironment
{
Q_OBJECT
public:
Environment(Controller *controller, QObject *parent = 0);
protected:
void process();
};
#endif // ENVIRONMENT_H
environment.cpp
#include "environment.h"
Environment::Environment(Controller *controller, QObject *parent) :
AbstractEnvironment(controller, parent) {}
void Environment::process()
{
// do something
}
PS: I've learned from the first part of this question and tried to compile the source code above inside Qt with MinGW. I get exactly two error messages (as expected):
..\untitled\abstractenvironment.cpp: In function 'void handleTimeout()':
..\untitled\abstractenvironment.cpp:17:13: error: 'process' was not declared in this scope
..\untitled\abstractenvironment.cpp:18:5: error: 'counter' was not declared in this scope
In case you want to try it yourself, I've zipped the Qt project and uploaded it to my Dropbox (of course I will remove this file at some point but the code is exactly the same as in the post above --> it's just for the sake of convenience, so you don't have to copy-paste it yourself)
EDIT: You just changed your question. So I can't tell if your original text was your actual source code or not. Good rule of thumb, paste your actual code rather than paraphrase it (then de-identify or reduce it if needed).
ORIGINAL ANSWER:
implementMe(); // compiler error: "implementMe() was not declared in this scope"
That is because doSomething() isn't declared properly in AbstractClass. You "declared" it in the base class with:
doSomething();
The compiler doesn't recognize AbstractClass::doSomething() out of line definition so nothing inside the implementation is resolved to the class scope.
Change that to:
void doSomething();
just like in your derived class.
and
AbstractClass::doSomething()
{
implementMe();
}
to
void AbstractClass::doSomething()
{
implementMe();
}
UPDATE:
void handleTimeout()
{
process();
counter++;
}
is a global function. That isn't the class implementation. It should be:
void AbstractClass::handleTimeout()
{
process();
counter++;
}
In abstractenvironment.cpp you define void handleTimeout(), which is non-member function and does not relate to AbstractEnvironment class. Thus, it doesn't look for AbstractEnvironment::process() and AbstractEnvironment::counter, but for ::process() and ::counter instead (which are not declared, hence the error).
Change it to void AbstractEnvironment::handleTimeout() and it should compile.
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 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.
I'm trying to implement a State Pattern in C++, but have problems with the circular dependency. I have read other related material here - unfortunately it didn't help me. I don't have a lot of experience with C++, so bear with me.
The following code is developed on a Ubuntu 10.10 machine in Eclipse Helios CDT:
ConcreteSystem.h
#ifndef CONCRETESYSTEM_H_
#define CONCRETESYSTEM_H_
class SystemState;
class ConcreteSystem {
public:
ConcreteSystem();
void SelfTestFailed();
void Restart();
private:
friend class SystemState;
SystemState *currentState;
void ChangeState(SystemState *state);
};
#endif /* CONCRETESYSTEM_H_ */
ConcreteSystem.cpp
#include "ConcreteSystem.h"
#include "SystemState.h"
ConcreteSystem::ConcreteSystem() {
currentState = SelfTest::GetInstance();
}
void ConcreteSystem::SelfTestFailed() {
currentState->SelfTestFailed(this);
}
void ConcreteSystem::Restart() {
currentState->Restart(this);
}
void ConcreteSystem::ChangeState(SystemState *state){
currentState = state;
}
SystemState.h
#ifndef SYSTEMSTATE_H_
#define SYSTEMSTATE_H_
class ConcreteSystem;
class SystemState {
public:
virtual void Restart(ConcreteSystem *cs);
virtual void SelfTestFailed(ConcreteSystem *cs);
protected:
virtual void ChangeState(ConcreteSystem *cs, SystemState *state);
};
#endif /* SYSTEMSTATE_H_ */
SystemState.cpp
#include "SystemState.h"
#include "ConcreteSystem.h"
void SystemState::Restart(ConcreteSystem *cs) {
}
void SystemState::SelfTestFailed(ConcreteSystem *cs) {
}
void SystemState::ChangeState(ConcreteSystem *cs, SystemState *state) {
cs->ChangeState(state);
}
SelfTest.h
#ifndef SELFTEST_H_
#define SELFTEST_H_
#include "SystemState.h"
class SelfTest : public SystemState {
public:
SelfTest();
void SelfTestFailed(ConcreteSystem* cs);
static SystemState* GetInstance();
private:
static SystemState* instance;
};
#endif /* SELFTEST_H_ */
SelfTest.cpp
#include "SelfTest.h"
#include "Failure.h"
SystemState* SelfTest::instance = 0;
SelfTest::SelfTest() {
}
void SelfTest::SelfTestFailed(ConcreteSystem *cs) {
ChangeState(cs, Failure::GetInstance());
}
SystemState* SelfTest::GetInstance() {
if (instance == 0) {
instance = new SelfTest();
}
return instance;
}
Failure.h
#ifndef FAILURE_H_
#define FAILURE_H_
#include "SystemState.h"
class SelfTest;
class Failure : public SystemState {
public:
Failure();
void Restart(ConcreteSystem* t);
static SystemState* GetInstance();
private:
static SystemState* instance;
};
#endif /* FAILURE_H_ */
Failure.cpp
#include "Failure.h"
#include "SelfTest.h"
SystemState* Failure::instance = 0;
Failure::Failure() {
}
void Failure::Restart(ConcreteSystem* t) {
ChangeState(t, SelfTest::GetInstance());
}
SystemState* Failure::GetInstance() {
if (instance == 0) {
instance = new Failure();
}
return instance;
}
I have problem with the includes, which gives me some weird compiler errors. Anyone with a good solution to this problem?
From the looks of the code you've posted, you'll have classes being redefined. Looking at your Failure.cpp file, you have:
#include "Failure.h"
#include "SelfTest.h"
Which will include both of those files, and each of those files include the SystemState.h file. Since the SystemState.h file is included more than once, it tries to redefine the SystemState class. At the top of each of your header files, you should do something like this:
// SystemState.h
#ifndef SystemState_h
#define SystemState_h
.. class definition ..
#endif // close the if statement from above.
As an aside on the design, I think it's bad form for the states to know about each other - use your ConcreteSystem as a state controller and then base the state on the return value of the last state operation.
Also, if you're relatively inexperienced with C++, I would recommend looking at this as a great source of learning material (in addition to StackOverflow, of course!).