C++ States: Sequence of Events is not very object orientated - c++

I am struggling to make my code more object orientated.
I have a small program that wishes to accomplish 2 very simple states: An input state, and a result state.
The input state seems simple to resolve as although it is graphical it is "self-updating." The user drops sprites and removes sprites on to the screen to produce an input.
The result state is annoying me because I have produced some very ugly code for it, that is not at all Object Orientated.
This state is required to do things sequentially and I am struggling to find examples of how that is done with Objects. It's basically some animation with the same object: here is some Pseudo-Code.
Static int objectx = 120, object y = 120;
Static int state=0
switch(state)
{
Case 0:
//....move object right
//....once object is far enough right
state = 1;
Case 1:
//....move object down
//....once object is far enough down
state = 2;
...etc
So I am guessing it needs to move to having some sort of state engine, but I am struggling to see how to accomplish sequential events using states. These states are always the same, and so can be hard coded, they will not change based upon the input given.
Any help will be most gratefully recieved.
UPDATE
Maybe we could think about this second state as a cut-scene in a 2d game. We want a character to walk on to the screen, say something and then walk off.
So the way I'm doing it at the moment is managing this part of the programs state via the switch statement. This function is called every time we are in the "result" part of our program, and we are using the switch statement to update the positions of our sprites. Once we have reached the end of the first set of movements we move to the next switch statement and keep doing that until it is completed. It works but I was hoping to use a " gamestate " Class, that could take ownership of the graphics and sound, and move things as appropriate.

Note: making some assumptions here because I don't have any context.
It sounds like each sprite should have its own cycle, rather than the entire game logic moving about the sprites.
Adapting this into an object-orientated design, you can wrap each sprite in some
class:
class NPC : Sprite {
private:
Position CurrentPosition;
int CurrentState;
public:
virtual void Think() = 0;
virtual void Render() = 0;
};
Then you can inherit from this class for specific sprites:
class GobbledyGook : NPC {
private:
const int FinalState = 10;
public:
bool Completed = false;
void Think() override {
if(Completed)
return;
switch(CurrentState) {
// ... repeating logic here ...
}
CurrentState++;
if(CurrentState == FinalState)
Completed = true;
}
void Render() override {
// ... draw the sprite ...
}
}
From the main game logic you can then update every sprite:
// Spawn a GobbledyGook into existence.
my_npcs.insert(new GobbledyGook());
// In frame logic.
bool finished = true;
for( NPC* n : my_npcs )
{
n->Think();
if(!n->Completed)
finished = false;
}
if(finished) {
// Result state.
}
// In render logic.
for( NPC* n : my_npcs )
{
n->Render();
}
You can naturally adopt this logic for entire scenes too:
class Intro : Cutscene {
private:
vector<NPC*> SceneSprites;
public:
void Think() override {
switch(CurrentState) {
...
}
for( NPC* n : SceneSprites ) {
n->Think();
}
}
...
};
As for whether you should be removing or changing the use of states, what do you intend to gain from doing that?
It's hard to recommend a different approach without knowing all the flaws of the current approach.

Related

Using The State Pattern in games

Recently, I've tried to create Snake game in SFML. However, I also wanted to use some design pattern to make some good habits for future programming - it was The State Pattern. But - there is some problem that I am unable to solve.
To make everything clear, I've tried to make several Menus - one main menu, and others, like "Options", or something like this. The first option of the main menu would take the player to the "Playing State". But then, the problem appears - I think the whole game should be an independent module implemented to program. So, what should I do with the actual state which program is in? (for example, let's call this state "MainMenu").
Should I make an additional state called "PlayingState", which would represent the whole game? How would I do it? How is it possible to add new functionality to a single state? Do you have any ideas?
The State Pattern allows you, for example, to have an object of a class Game and alter its behavior when the game state changes providing the illusion that this Game object had changed its type.
As an example, imagine a game that has an initial menu and can be paused while playing if you press the space bar. When the game is paused, you can either go back to the initial menu by pressing the backspace key or continue playing by pressing the space bar again:
First, we define an abstract class, GameState:
struct GameState {
virtual GameState* handleEvent(const sf::Event&) = 0;
virtual void update(sf::Time) = 0;
virtual void render() = 0;
virtual ~GameState() = default;
};
All the state classes – i.e., MenuState, PlayingState, PausedState – will publicly derive from this GameState class. Note that handleEvent() returns a GameState *; this is for providing the transitions between the states (i.e., the next state, if a transition occurs).
Let's focus for the moment on the Game class instead. Eventually, our intention is to use the Game class as in the following way:
auto main() -> int {
Game game;
game.run();
}
That is, it has basically a run() member function that returns when the game is over. We define the Game class:
class Game {
public:
Game();
void run();
private:
sf::RenderWindow window_;
MenuState menuState_;
PausedState pausedState_;
PlayingState playingState_;
GameState *currentState_; // <-- delegate to the object pointed
};
The key point here is the currentState_ data member. At all times, currentState_ points to one of the three possible states for the game (i.e., menuState_, pausedState_, playingState_).
The run() member function relies on delegation; it delegates to the object pointed by currentState_:
void Game::run() {
sf::Clock clock;
while (window_.isOpen()) {
// handle user-input
sf::Event event;
while (window_.pollEvent(event)) {
GameState* nextState = currentState_->handleEvent(event);
if (nextState) // must change state?
currentState_ = nextState;
}
// update game world
auto deltaTime = clock.restart();
currentState_->update(deltaTime);
currentState_->render();
}
}
Game::run() calls the GameState::handleEvent(), GameState::update() and GameState::render() member functions that every concrete class that derives from GameState must override. That is, Game does not implement the logic for handling the events, updating the game state and rendering; it just delegates these responsabilities to the GameState object pointed by its data member currentState_. The illusion that Game appears to change its type when its internal state is altered is achieved through this delegation.
Now, back to the concrete states. We define the PausedState class:
class PausedState: public GameState {
public:
PausedState(MenuState& menuState, PlayingState& playingState):
menuState_(menuState), playingState_(playingState) {}
GameState* handleEvent(const sf::Event&) override;
void update(sf::Time) override;
void render() override;
private:
MenuState& menuState_;
PlayingState& playingState_;
};
PlayingState::handleEvent() must at some time return the next state to transition into, and this will correspond to either Game::menuState_ or Game::playingState_. Therefore, this implementation contains references to both MenuState and PlayingState objects; they will be set to point to Game::menuState_ and Game::playingState_ data members at PlayState's construction. Also, when the game is paused, we ideally want to render the screen corresponding to the playing state as the starting point, as we will see below.
The implementation of PauseState::update() consists of doing nothing, the game world simply remains the same:
void PausedState::update(sf::Time) { /* do nothing */ }
PausedState::handleEvent() only reacts to the events of either pressing the space bar or the backspace:
GameState* PausedState::handleEvent(const sf::Event& event) {
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Space)
return &playingState_; // change to playing state
if (event.key.code == sf::Keyboard::Backspace) {
playingState_.reset(); // clear the play state
return &menuState_; // change to menu state
}
}
// remain in the current state
return nullptr; // no transition
}
PlayingState::reset() is for clearing the PlayingState to its initial state after construction as we go back to the initial menu before we start to play.
Finally, we define PausedState::render():
void PausedState::render() {
// render the PlayingState screen
playingState_.render();
// render a whole window rectangle
// ...
// write the text "Paused"
// ...
}
First, this member function renders the screen corresponding to the playing state. Then, on top of this rendered screen of the playing state, it renders a rectangle with a transparent background that fits the whole window; this way, we darken the screen. On top of this rendered rectangle, it can render something like the "Pause" text.
A stack of states
Another architecture consists of a stack of states: states stack up on top of other states. For example, the pause state will live on top of the playing state. Events are delivered from the topmost state to the bottommost, and so are states updated as well. The rendering is performed from the bottom to the top.
This variation can be considered a generalization of the case exposed above as you can always have – as a particular case – a stack that consists of just a single state object, and this case would correspond to the ordinary State Pattern.
If you are interested in learning more about this other architecture, I would recommend reading the fifth chapter of the book SFML Game Development.
For you design, i think you can use incremented loop for the different state:
Simple example:
// main loop
while (window.isOpen()) {
// I tink you can simplify this "if tree"
if (state == "MainMenu")
state = run_main_menu(/* args */);
else if (state == "Play")
state = run_game(/* args */);
// Other state here
else
// error state unknow
// exit the app
}
And when the game is running:
state run_game(/* args */)
{
// loading texture, sprite,...
// or they was passe in args
while (window.isOpen()) {
while (window.pollEvent(event)) {
// checking event for your game
}
// maybe modifying the state
// Display your game
// Going to the end game menu if the player win/loose
if (state == "End")
return run_end_menu(/* args */);
// returning the new state, certainly MainMenu
else if (state != "Play")
return state;
}
}
You have a main menu and the game, your state by default is "MainMenu".
When you enter in your main menu you click the play button, then the state returns "Play" and you go back to the main loop.
The state is "Play" so you go to the game menu and your start your game.
When the game ends, you change your state to "EndGame" and go out of the game menu to the end menu.
The end menu returns the new menu to display, so you go back to the main loop and check every available menu.
With this design you can add a new menu without changing the entire architecture.

Vector is crashing my program

I've got a serious problem with my SFML game.
I've been trying whole day to find a solution, tried diffrent things but nothing worked for me so far.
These are my .h files:
Bullet.h
#pragma once
#include <SFML\Graphics.hpp>
#include <iostream>
#include <vector>
class Bullet
{
friend class Player;
friend class Game;
float width;
float height;
float x;
float y;
std::vector<Bullet*> projectiles;
sf::RectangleShape bullet;
void draw_projectiles(sf::RenderWindow &window);
void make_projectiles();
public:
void check();
Bullet();
~Bullet();
};
Game.h
#pragma once
#include <SFML\Graphics.hpp>
#include "Player.h"
#include "Bullet.h"
#include <vector>
//#include "Enemy.h"
class Game
{
friend class Player;
sf::RenderWindow* window;
sf::Event* evnt;
Player* player;
Bullet* bullet;
public:
void Loop();
void game_func();
Game();
~Game();
};
Player.h
#pragma once
#include <SFML\Graphics.hpp>
#include <iostream>
#include "Game.h"
#include "Bullet.h"
class Player
{
sf::RectangleShape player;
Bullet* bullet;
int ammo;
float width;
float height;
int x;
int y;
float vel;
public:
void draw(sf::RenderWindow &window);
void move(sf::Event &evnt, sf::RenderWindow &window);
Player();
~Player();
};
Here come cpp files
Bullet.cpp
#include "Bullet.h"
void Bullet::check()
{
x = bullet.getPosition().x;
y = bullet.getPosition().y;
}
void Bullet::draw_projectiles(sf::RenderWindow &window)
{
for (int i = 0; i < 10; i++)
{
window.draw(projectiles[i]->bullet);
}
}
void Bullet::make_projectiles()
{
projectiles.push_back(new Bullet());
}
Bullet::Bullet()
{
std::cout << "zostal utworzony nowy obiekt" << std::endl;
width = 50;
height = 50;
bullet = sf::RectangleShape(sf::Vector2f(width, height));
bullet.setFillColor(sf::Color::Yellow);
bullet.setPosition(0, 0);
x = bullet.getPosition().x;
y = bullet.getPosition().y;
}
Bullet::~Bullet(){}
Game.cpp
#include "Game.h"
Game::Game()
{
window= new sf::RenderWindow(sf::VideoMode(1280, 720), "SFML Game",
sf::Style::Close);
player = new Player();
}
Game::~Game(){}
void Game::Loop()
{
while (window->isOpen())
{
sf::Event evnt;
while (window->pollEvent(evnt))
{
//events
if (evnt.type==sf::Event::Closed)
window->close();
player->move(evnt, *window);
window->clear();
player->draw(*window);
window->display();
bullet->draw_projectiles(*window);
}
}
}
void Game::game_func()
{
Game::Loop();
}
Player.cpp
#include "Player.h"
void Player::draw(sf::RenderWindow &window)
{
window.draw(player);
}
void Player::move(sf::Event &evnt, sf::RenderWindow &window)
{
x = player.getPosition().x;
y = player.getPosition().y;
float width = window.getSize().x;
float height = window.getSize().y;
Bullet obj;
if (evnt.type == sf::Event::KeyPressed)
{
//movement
if (evnt.key.code == sf::Keyboard::Key::W)
{
if (y <= 0)
{
return;
}
player.move(0, -1 * vel);
}
if (evnt.key.code == sf::Keyboard::Key::S)
{
if (y >= height - Player::height)
{
return;
}
player.move(0, 1 * vel);
}
if (evnt.key.code == sf::Keyboard::Key::A)
{
if (x <= 0)
{
return;
}
player.move(-1 * vel, 0);
}
if (evnt.key.code == sf::Keyboard::D)
{
if(x>width-Player::width)
{
return;
}
player.move(1 * vel, 0);
}
if (evnt.key.code == sf::Keyboard::Space)
{
obj.make_projectiles();
}
}
}
Player::Player()
{
width = 100;
height = 100;
vel = 10;
player = sf::RectangleShape(sf::Vector2f(width, height));
player.setFillColor(sf::Color::Red);
player.setPosition(sf::Vector2f(15, 20));
}
Player::~Player(){}
And main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include "Game.h"
int main()
{
Game gme;
gme.game_func();
return 0;
}
I tried many diffrent things and can't figure it out why it's not working. Im running in on Visual Studio 15.
So here is error that I'm getting:
Exception thrown: read access violation.
std::_Vector_alloc<std::_Vec_base_types<Bullet *,std::allocator<Bullet *> >
>::_Mylast(...) returned 0x18.
I'm aware that code is not perfect and little messy but I'm just a begginer and trying to learn new stuff.
I will appreciate any help!
I answered your question in my last paragraphs, you can skip to that paragraph but I sugest you take a look at all of this. First of all you should understand how should a basic game look like in code.
The Game Logic
You can separate the game logic in 2 main functions. The initialization and the loop.
Initialization
In the initialization function, you basically load everything needed for your game to run (that is only available for small games, since loading tens of gigs of sprites in memory may not be the best solution for bigger ones. With time you'll figure out the right time to load and release resources).
The loop
This is called the main loop or the game loop. This loop should execute 3 main functions. Handle user input, update world, and render the world. This loop should execute while the game is running (i.e. while the window is open)
So your main in pseudo-c++ should look something like this:
Init();
while (window.isOpen())
{
HandleEvents(window); //user input
Update(elapsedTime);
Render(window);
}
I'll explain what the functions do, what the arguments mean and how this functions are mapped to your code. Keep in mind that every function has one specific task and only that. I won't check if the user is pressing a button while I'm drawing the sprites on the screen.
User input
Everything from button pressing and mouse clicking to pressing the exit button and resizing the window is called user input. User's actions generate the so called events, which we handle at the beginning of each loop. Now this events are window specific(you can't control the player if the window is minimized or unfocused). That means that the window generates the events (if I'm wrong with this one technically, please correct me). This is the reason that when you are handling events you need to pass the window.
Events
Before handling the events, you need to understand how sf::Event is made (see more on the sfml page). Long story short the sf::Event is an union (only one field is valid at a time). That is, if you try to access event.key when the window.pollEvent() returned an sf::Event::JoystickEvent you will get an undefined behavior (I lived a long happy life without knowing what unions are, never used them and probably never will, but they are quite an interesting concept that is worth at least reading about). Ok so an event object is created by calling window.pollEvent() and passing to it an sf::Event instance. This function will give you events from the queue until there are no more events to be given, that's when it returns false. With that in mind, your Event handling code would look something like:
sf::Event ev;
while (window.pollEvent(ev))
{
switch (ev.type)
{
//code for each type needed by your application
}
}
Keep in mind that key events do not handle real time input (sf::Keyboard::isKeyPressed does that). This means that if you want your character to move when you hold a button, handling it by events will result in a delay that can be the best explained by the way typing works(when you hold down 'a' for example the first character is written immediately, the rest of the input is delayed by a second before registering). This is a way of explaining it, but maybe not the most technical one(I'm asking for a little help here :) ). Anyway, this problem can be solved either by using the static methods of sf::Keyboard or by keeping a bool in your Player class that answers to the events KeyPressed and KeyReleased(the update will be handled based on that bool).
World Update
Here is your logic code(although player movement may also be handled in the events section, since it's based on them). Here you update your entities(move the enemy one more block based on his AI), move the sun around the map etc. Keep in mind that this has nothing to do with the drawing part, in this section you only change the state of your objects. In your game it means, after you launched a projective through an event triggered by the user, each frame you move the projectile. This code usually requires some sort of frame counting method.
Frames
A frame is an iteration of the loop, you can say that the game updates and draws itself each frame. Frames are a very important concept because they arise some issues. If the game updates itself each frame, that means that each frame the projectile is moving, so that means that his movement is dependent to the FPS your pc can run. This is a problem, because while your game may run as you want on your pc, at a stable 60 FPS rate, on mine it might run at 53, or some other random value. That means that the projectiles on my pc will move slower, and we don't want that.
Frame independent movement
This can be achieved by counting the frames. One way you can do that is by counting the seconds it passed since the last frame, with that in mind you can get the amount of space your entity needs to move in that specific frame. For example, you want to move your projectile with 100px/sec. If you have 2FPS that means that in 2 frames it needs to move 100px, so each frame moves 100 / 2 px. So the formula is finalDistance / framerate. There are more ways of doing this, but in my opinion this is the simplest to understand at the beginning. So how is this implemented in SFML? You basically keep a clock that you restart at the end of each update. getElapsedTime and restart does that, but restart returns the elapsedTime so it is better to call it once, since calling them one by one may result in different times and desyncs.
sf::Clock clock;
while (window.isOpen())
{
HandleEvents(window);
Update(clock.restart());
Render(window);
}
And you simply move your entities with move(vector * clock.getElapsedTime().asSeconds()) since sf::Vector has operator* overloaded for floats(the return type of asSeconds()).
Rendering
The rendering part may be very complicated, but sfml makes it "simple and fast". Basically it works like that: You clear the screen, you draw your entities, you display the screen. The more technical answer is the following: the window consists of 2 buffers, one visible and one hidden. The visible one is the one you see on the screen. When you call clear() you basically clear the hidden one, draw() draws also on the hidden window, and finally display() swaps the buffers.
That means that you won't see any results unless you call window.display(), and you'll get a window xp experience if you don't call clear() before drawing. So the Render function might look like this:
window.clear();
window.draw(player); //or player.draw(window) based on your implementation
//other draws
window.display();
Your question
What happens in your code is that you try to access things that don't exist. You add one projectile at a time, but each frame you draw 10 of them.
The solution
Keep a counter of your objects. Since you are using a vector that is already provided, you have std::vector::size that returns exactly what you expect, so your code will turn into something like:
for (int i = 0; i < yourProjectiles.size(); i++)
{
window.draw(yourProjectiles[i]->bullet);
}
Alternatively you can use iterators(look them up):
for (auto it = yourProjectiles.begin(); it != yourProjectiles.end(); ++it)
{
window.draw(it->bullet);
}
Memory management
You don't deallocate memory. You have to look into dynamic memory allocation. The base principle is that for every new there should be a delete. The deallocation part should be handled most of the time in the destructor of the class. I think someone may suggested to use smart pointers(std::shared_ptr) so manage your memory, but I can't recommend you that since you are at the beginning. Smart pointers are a concept you should keep in mind, but as you started out it is better to face the struggles of manual memory management(until you get used to it).
Code organizing
A class should be made for only one purpose. When you create a class called Bullet, it is expected that this Bullet will represent one projectile in your game, but when your Bullet makes "projectiles" and stores projectiles, it becomes a paranormal entity. Your bullet atm holds pointers to instances of other bullets that hold pointers to instances of other bullets. This is a total mess. Unless you want to create a graph or a tree of some sort you don't have any reason to store pointers of instances of the same class.
Too many friends
If every class is friend with every class, what is your reason of creating private fields? Friend is a very powerful concept and should be used with care, only in cases you DON'T have other options. The only reason I would avoid this keyword is the messiness it creates. It creates the same effect as public attributes. When everything is accessible from everywhere, everything can be destroyed from everywhere. When you create a small set of methods that manipulate your attributes, you know where the problem is.
Conclusion
I might suggest looking a little more into c++ and after that debug your game, or recreate it from scratch. While I know how it feels to try something new, you should always be careful to not shoot yourself in the leg, and don't be afraid to go back to the basics when you stumble into such errors. You have problems managing memory? Read more about dynamic memory allocation, do some example apps using it. Besides that I noticed you are still at the beginning with using classes. I'd say practice makes perfect. Look at other people code, even these 3rd party libraries like sfml may give you some hints on good class practices. The good thing is that it is not needed to look at the source code of those libraries, you just use their interface. If you like it, it means it is good written and you may borrow a part of that style and implement in your classes. I'll conclude this by saying that I am very happy and eager to help you via email if you have any other question regarding anything.
I believe you are attempting to access ten projectiles:
for (int i = 0; i < 10; i++)
{
window.draw(projectiles[i]->bullet);
}
But you only add one at a time:
projectiles.push_back(new Bullet());

Is there a better way to make an EventManager

I made a little code for my EventManager, it works correctly, but the thing is, I created it with a lot of copy-paste, and I think that every time you start doing copy-paste on a few lines, your code is badly designed.
So, having done a lot of copy-paste on that EventManager, I think it's time to find out if there is another way to make it (and there probably is, and probably better).
What I achieved is that when an Event happens (window.pollEvent(event)), it calls the onEvent(sf::Event, sf::RenderWindow*) method of the EventManager class, and for every event I need to listen, I call all instances of the listener.
Here's the class :
public:
void registerKeyPressed(std::shared_ptr<KeyPressedEventListener> listener);
void registerWindowResized(std::shared_ptr<WindowResizedEventListener> listener);
void registerWindowFrameUpdate(std::shared_ptr<WindowFrameUpdateEventListener> listener);
private:
std::vector<std::shared_ptr<KeyPressedEventListener>> m_keyPressedListeners;
std::vector<std::shared_ptr<WindowResizedEventListener>> m_windowResizedListeners;
std::vector<std::shared_ptr<WindowFrameUpdateEventListener>> m_windowFrameUpdateListeners;
So, the thing is, it is a lot of code for only 3 listeners (I currently have 6, but it's not useful to show them as the code is always similar).
My problem is that I want a class to be able to listen to one, two or more events at a time, so all my listeners have a different function that's called when the event happens. For example, these three listeners have the functions onKeypressed(sf::Event);, onWindowResized(sf::Event, sf::RenderWindow* window); and onFrameUpdate(sf::RenderWindow* window);. That's the only way I found to make this code work.
It actually works, but I'd like to make something better, because it's a lot of code for every event :
void EventManager::onEvent(sf::Event event, sf::RenderWindow* window) { // The window argument is used further, but it's not useful to show it here as the code is quite the same
switch (event.type) {
case sf::Event::Resized:
for (unsigned int i = 0; i < m_windowResizedListeners.size(); i++) {
if (m_windowResizedListeners.at(i)->onWindowResized(event)) break; // The events return a bool value : True if the loop has to stop (for an error, for example), false otherwise. I always return false unless an error happen, but it's in case I need to stop it.
}
break;
}
}
void EventManager::registerWindowResized(std::shared_ptr<WindowResizedEventListener> listener) {
m_windowResizedListeners.push_back(listener);
}
And I have to duplicate this code for every event. If there's a bug, you understand it'll be a lot of work to correct it, so I hoped you could help me find a better way to achieve it.
Thank you for your help.
You could use a common class:
class EventHandler{
public:
virtual void handle(sf::RenderWindow &window) = 0;
};
class EventManager {
public:
void registerKeyPressed(std::shared_ptr<EventHandler> listener);
void registerWindowResized(std::shared_ptr<EventHandler> listener);
void registerWindowFrameUpdate(std::shared_ptr<EventHandler> listener);
private:
std::vector<std::shared_ptr<EventHandler>> m_keyPressedListeners;
std::vector<std::shared_ptr<EventHandler>> m_windowResizedListeners;
std::vector<std::shared_ptr<EventHandler>> m_windowFrameUpdateListeners;
}
You can now define a map in the class, the key is the event type and the value is his listener's vector.
std::map<int,std::vector<std::shared_ptr<EventHandler>>*> eventType;
}
//...
EventManager::EventManager(){
eventType[sf::EventType::Resized] = &m_windowResizedListeners;
eventType[sf::EventType::KeyPressed] = &m_keyPressedListeners;
//Keep going...
}
So now, the onEvent function is pretty straightforward:
void EventManager::onEvent(sf::Event event, sf::RenderWindow* window) {
std::vector<std::shared_ptr<EventHandler>>* ptr = eventType[event.type];
for (int i = 0;i < ptr->size();i++)
(*ptr)[i]->handle(window);
}
Let's put an example:
class SettingsSaver : public EventHandler{
public:
void handle(sf::RenderWindow &window) override {
std::cout << "I am saving the state in the hardrive before of exit" << std::endl;
}
}
class MoveHero : public EventHandler{
public:
void handle(sf::RenderWindow &window) override {
std::cout << "I am moving the character" << std::endl;
}
}
// Main
std::shared_ptr<EventHandler> settingsSaver(new SettingsSaver);
std::shared_ptr<EventHandler> moveHero(new MoveHero);
EventManager manager;
manager.registerWindowClosed(settingsSaver);
manager.registerKeyPressed(moveHero);

call method on every object from the same class

I'm working on a arduino project.
For those who don't know what a arduino is:
arduino is a little electronic-board whit a micro-controller which can be programmed in C++
Since a arduino is a little micro-controller, it is single core 16MHz multiprocessing is very hard.
I have made a class, in th constructor, it defines a pin as pwm output en sets min fade, max fade, fade time etc.
I have methods to start fading and stop fading change setpoint, speed...
for multifading I've made a update method.
So when I call light1.update() it checks if the pwm output needs to be changed or not.
Now the question is:
I have more lights so that will be:
light1.update();
light2.update();
light3.update();
and so on
Is there a way to write just one line to call update() on every object of the fade class?
Looks like you're looking for a combination of the Observer pattern combined with an Instance manager pattern.
Whenever you create a new instance of Light, add it to the manager. When you want the events to be triggered, iterate through the instances in the manager and call update.
Something like:
class LightManager
{
static std::vector<Light> lights;
static void notify()
{
for ( size_t i = 0 ; i < lights.size() ; i++ )
lights[i].update();
}
static void add(const light& l)
{
lights.push_back(l);
}
};
class Light
{
Light()
{
LightManager::add(*this);
}
};
Then you update all lights with:
LightManager::notify();

The "concept" of an oo game

In most or all object oriented games, each class relies on not just its own but parent classes. How is this class connection implemented in C++? Do you just add a pointer for the parent class you need or is there a better way?
For example a football game, when the person class clicks it ask the scene class if he is kicking any balls, and if he is then move it. I hope this is understandable and not too abstract.
I don't think passing along the parent in a constructor is a good idea. Instead, you should be using a class that maintains a list of all game elements and facilities interactions between them; for instance, the Game class illustrated below would check for collisions between any two players and if it's detected tell each of them that they were hit and by who.
I'm not sure if this will benefit you at all, but I typed it up for my initial response so I might as well submit. Note that all of this is still relevant if you're talking about a text-only game, just ignore the allusions to graphics in that case. Game design is based around a continuous game loop, and can be thought of very simply as:
while(true)
for each tick:
react to user input
update player, enemies, objects, etc.
end while
Where "tick" is every iteration of the game clock, however you choose to implement it--based on the fps, each second, whatever. In your example, the user clicks the football, the game sees the click and tells the football to move. To do this very simply, maintain a list all of all of the game elements within a class that maintains the state. To illustrate, here are is a very basic way you could implement this:
class Game {
vector<GameElement> elements;
Football football;
Player currentPlayer;
Game() {
this.football = new Football();
}
void update() {
for e in elements:
e.update();
// Once every element has been updated for the current tick, redraw them on the screen
screen.redraw();
}
void addElement(GameElement e) {
elements.add(e);
}
}
class GameElement {
int posx, posy; // screen coordinates
void paint() {}; // method to draw this element to the screen
virtual void update();
}
class Football: public GameElement {
bool kicked;
int anglex, angley;
double velocity;
void update() {
if(kicked){
// update position, angle, velocity; slow it down, check for bounce, whatever
posx = new x position;
posy = new y position;
if(velocity == 0)
kicked = false;
}
paint(); // call the paint method after the new position has been found
}
}
Assume you have another class that inherits from GameElement, Player, with a method kick(football) that sets the passed football into motion--i.e., sets kicked=True. So to initialize the game, you'd set it up with something like:
Game game = Game();
game.add(new Football());
game.add(new Player());
while(true) {
if(user_input==X)
game.currentPlayer.kick(football);
game.update();
sleep(1);
}
This could be changed to maintain, for example, layers instead of the entire game, then a higher level class could call update of each layer in order, allowing things to be painted over each other and children to only interact with siblings. There are a lot of possibilities.
Ran into similar questions working on a poker game: Here's the way I did it:
In your example, add a scene * the_scene to the constructor of person. Then, when person is initialized pass it a pointer to scene. Since you said parent and child, if the parent Is scene then it would just use "this" and it would send the address of the parent.
Then again, it seems like that's how you were going to do it anyway. One more thing, if you need person to interact with more than one class that is not directly inside it you can make some kind of container class that would store the pointers to all of them and just pass person that one to avoid having a constructor with too many parameters.