I am trying to create a basic game engine in C++ and I want an Engine object to be able to loop through all the GameObject children to run their update methods, to do this I want to use a vector of all children within the Engine class.
For example:
This is similar to what I have been trying to do:
Parent Engine Class
class Engine {
public:
Engine() {};
std::vector<GameObject> GameObjects; //Vector to store all GameObjects
void AddNewObject(GameObject& obj) {
GameObjects.push_back(obj); //Add new object to the vector array
}
void Run() {
for (int i = 0; i < GameObjects.size(); i++) {
GameObjects[i].Update(); //Run the update method of each GameObject
}
}
}
GameObject Child Class
class GameObject : public Engine {
public:
GameObject() {}
void Update() {
//Do stuff
}
}
Main code loop
int main(void) {
Engine engine;
GameObject object;
engine.AddNewObject(object); //Add object
engine.run();
}
Any help would be greatly appreciated, Thanks.
There are a few issues here. First, your vector needs to be a vector of references or pointers, otherwise GameObjects.push_back(obj); makes a copy of obj to place into the vector (unless you move it) and polymorphism won't work (you can't hold subclasses of GameObject).
How you approach this depends on which object you want to own the memory associated with each GameObject. A trivial fix is is by using a vector of pointers:
class Engine {
public:
Engine() {};
std::vector<GameObject*> GameObjects; //Vector to store all GameObjects
void AddNewObject(GameObject& obj) {
GameObjects.push_back(&obj); //Add new object to the vector array
}
void Run() {
for (int i = 0; i < GameObjects.size(); i++) {
GameObjects[i]->Update(); //Run the update method of each GameObject
}
}
}
However, with modern, C++ you would want to probably use a smart pointer like unique_ptr:
class Engine {
public:
Engine() {};
std::vector<std::unique_ptr<GameObject>> GameObjects; //Vector to store all GameObjects
void AddNewObject(std::unique_ptr<GameObject> obj) {
GameObjects.push_back(std::move(obj)); //Add new object to the vector array
}
void Run() {
for (int i = 0; i < GameObjects.size(); i++) {
GameObjects[i]->Update(); //Run the update method of each GameObject
}
}
}
By using a unique pointer, you would have to change your other code:
int main(void) {
Engine engine;
std::unique_ptr<GameObject> object = std::make_unique<GameObject>();
// Transfers memory ownership of `object` into `engine`
engine.AddNewObject(std::move(object)); //Add object
engine.run();
}
Lastly, your class hierarchy looks invalid. You probably don't need or want GameObject to be a subclass of Engine since they don't share anything in common. GameObject may likely be a good base class itself and other game objects would inherit it.
Related
I have to modify my program and create a new (Gamefigures) class from which my current classes(Rabbit and Hedg) inherit. The code is a small game where two animals race until they reach the goal, but in the second task I have to make sure that it is possible that multiple iterations of these animals can race. (5 vs 5 or X vs X for instance). I am allowed to move some variables or methods to the Gamefigures class. Both of the animals use different rules to walk. How do I make a new class which creates multiple objects dynamically of the same class from which my current classes inherit?
I have tried to use the new expression to create a new object but I don't know if it is the right thing to do.
I tried:
Hedg* nHedg = new Hedg[numFigures];
Here is the rest of my code:
class Hedg: public Gamefigures
{
private:
int salat = 1;
protected:
int position1 = 0;
public:
bool turn(int fields)
{
int counter = 10;
if (fields < 11)//Less than 10 fields
{
while ((counter > 0))
{
if (counter < fields)//max 10 fields
{
fields = counter;
}
position1 += fields;//walk
counter -= fields;
if (counter <= 0)
{
salat = 0;
}
}
getSalat();
return true;
}
else
return false;
}
Hedg()
{
}
int getPosition1()
{
return position1;
}
int getSalat()
{
return salat = 1;
}
int getStock1()
{
return salat;
}
~Hedg()
{
}
};
class Game :public Hedg, public Rabbit
{
private:
int goal = 0;
int numFields = 0;
protected:
Rabbit theRabbit;
Hedg theHedg;
public:
Game();
Game(int numFields);
int getGoal();
int dice();
void doyourturn();
bool getStand();
~Game();
};
Here is the error message:
Error code C4430 missing typespecifier
I think that the polymorphism is what you need for your use case and will solve your problems.
Let's suppose you have a base class for your animals:
class Animal
{
// ...
// Create all the (pure) virtual methods to be redefined by a derived class
virtual void walk() = 0; // For example
};
Then you defines your two specific animals, the rabbit and the hedgehog:
class Rabbit : public Animal
{
// ...
// Redefine here the (pure) virtual methods of Animal for a Rabbit
void walk() override;
};
class HedgeHog : public Animal
{
// ...
// Redefine here the (pure) virtual methods of Animal for a HedgeHog
void walk override;
};
And you can use polymorphism to handle your list of animals:
std::vector<Animal*> race_competitors;
race_competitors.push_back(new Rabbit);
race_competitors.push_back(new HedgeHog);
And this way, when you will call the walk() method over a competitor, it will automatically execute the proper walking rule of the corresponding animal.
Of course, at the end of the race, don't forget to delete the content of the vector because the animals was created with new ("manually" allocated memory, on the heap).
Just for information, the Game class doesn't have to inherit from Rabbit and HedgeHog, it just has to know them as class members, or even better, store a std::vector<Animal*> as a list of competitors.
I hope it will help you to improve your design and solve your problems.
I would like to create a simple framework for throwing and catching events in a game. Events could be things like a Collision which (according to the type) can take several arguments (note that every Event type may take another amount of arguments, not just two as in the example).
I would then like to implement functions/classes/... to deal with a Collision, based on polymorphism. This example should illustrate the problem:
#include <iostream>
#include <vector>
class Entity {};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (! b->exploded) {
std::cout << "BOOM";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
// Possibility for Collision between Minesweeper and Bomb later
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
onCollision(board[0], board[1]); // player and bomb!
onCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Note that I understand perfectly well why the above code doesn't work as intended, I included this example solely to illustrate my problem better.
The above example uses functions for the events, but I'm perfectly fine with classes or any other solution that is maintainable.
I hope it is clear that I would like C++ to decide which event handler to use based on the types of the arguments (presumably at runtime).
My question: How can I do this in C++? An example would be appreciated.
(not my question: fix my code please)
user2864740 provided enough clues for me to find a solution myself. Multiple dispatch was indeed the missing piece.
The following code works as intended, making use of dynamic_cast to dispatch correctly.
#include <iostream>
#include <vector>
class Entity {
virtual void please_make_this_polymorphic() {}
// although this function does nothing, it is needed to tell C++ that it
// needs to make Entity polymorphic (and thus needs to know about the type
// of derived classes at runtime).
};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (!b->exploded) {
std::cout << "BOOM\n";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
void dispatchCollision(Entity* e, Entity* f) {
Player* p = dynamic_cast<Player*>(e);
Bomb* b = dynamic_cast<Bomb*>(f);
if (p != nullptr && b != nullptr) {
onCollision(p, b); // player and bomb
} else {
onCollision(e, f); // default
}
}
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatchCollision(board[0], board[1]); // player and bomb
dispatchCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Although it works, I'd like to point out some problems with this code:
Manual editing of dispatchCollision needed when adding new Collisions.
Currently, the dispatcher using a simple kind of rule-based system. (Does it fit rule 1? What about rule 2? ...) When adding loads of different functions it needs to dispatch, that may have an impact on the performance.
A collision between A and B should be the same as a collision between B and A, but that isn't properly handled yet.
Solving these problems is not necessarily in the scope of this question IMHO.
Also, the example given should work just as well for more than 2 arguments. (Multiple dispatch, not just double dispatch.)
You should decide first what event subscription model you need.
It could be signal/slot mechanism and you can find plenty of libraries:
https://code.google.com/p/cpp-events/ , http://sigslot.sourceforge.net/ and the like.
Or it could be bubbling/sinking events like in HTML DOM when event gets propagated on parent/child chain ( from event source element to its containers).
Or even other schema.
It is quite easy to create whatever you need with std::function holders in modern C++.
Maybe a good structure for your case could be something like this:
class Entity{
public:
virtual int getType() = 0;
};
enum EntityTypes {
ACTOR,
BOMB,
MINESWEEPER,
};
class Actor : public Entity{
public:
virtual int getType() {return int(ACTOR);}
void applyDamage() {
std::cout << "OUCH";
}
};
class Bomb : public Entity{
public:
Bomb() : exploded(false) {}
virtual int getType() {return int(BOMB);}
void explode() {
this->exploded = true;
}
bool isExploded() {
return this->exploded;
}
protected:
bool exploded;
};
class MineSweeper : public Entity{
public:
virtual int getType() {return int(MINESWEEPER);}
};
class CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) = 0;
};
class ActorBombCollisionSolver : public CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) {
Actor* actor;
Bomb* bomb;
if (entity0->getType() == ACTOR && entity1->getType() == BOMB) {
actor = static_cast<Actor*>(entity0);
bomb = static_cast<Bomb*>(entity1);
}else if (entity1->getType() == ACTOR && entity0->getType() == BOMB) {
actor = static_cast<Actor*>(entity1);
bomb = static_cast<Bomb*>(entity0);
}else {
//throw error;
}
if (!bomb->isExploded()) {
bomb->explode();
actor->applyDamage();
}
}
};
class CollisionDispatcher {
public:
CollisionDispatcher() {
CollisionSolver* actorBombCollisionSolver = new ActorBombCollisionSolver;
this->solvers[ACTOR][BOMB] = actorBombCollisionSolver;
this->solvers[BOMB][ACTOR] = actorBombCollisionSolver;
// this part wouldn't be necessary if you used smart pointers instead of raw... :)
this->solvers[BOMB][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][BOMB] = 0;
this->solvers[ACTOR][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][ACTOR] = 0;
}
void dispatchCollision(Entity* entity0, Entity* entity1) {
CollisionSolver* solver = this->solvers[entity0->getType()][entity1->getType()];
if (!solver) {
return;
}
solver->solve(entity0, entity1);
}
protected:
unordered_map<int, unordered_map<int, CollisionSolver*> > solvers;
};
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() : dispatcher(new CollisionDispatcher)
{
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatcher->dispatchCollision(board[0], board[1]);
dispatcher->dispatchCollision(board[0], board[2]);
dispatcher->dispatchCollision(board[1], board[2]);
}
protected:
CollisionDispatcher* dispatcher;
};
int main() {
Game g;
g.main_loop();
}
This way you can easily add new collision solvers, just define the class, and register t in the CollisionDispatcher constructor.
If you use smart pointers you won't need to set zeroes in the map entries not registered, but if you use raw pointers you have to set them to zero OR use unordered_map::find method instead of just grabbing the solver using operator []
Hope it helps!
I'm having trouble figuring out a way to make a component based engine architecture in c++. But i cant figure out a way to combine a vector of components with a class that derives from component.
I want to override components virtual function. But the only way i can make it call the overrided function is to make the component-derived class a pointer, but i want every gameobject to contain its own components in a vector and not outside the class as a pointer.
I tried to remove as much unnecessary code as possible.
My structure:
//GameObject class, contains components and other objects
class GameObject
{
public:
GameObject(){}
~GameObject(){}
void AddChild(GameObject child)
{
children.push_back(child);
}
void AddComponent(Component component)
{
components.push_back(component);
}
void Input(){}
void Update(){}
void Render()
{
for(unsigned int i = 0; i < components.size(); i++)
components[i].Render();
}
private:
std::vector<GameObject> children;
std::vector<Component> components;
};
//base class component
class Component
{
public:
Component(){}
~Component(){}
virtual void Input(){}
virtual void Update(){}
virtual void Render(){ cout << "Component -> Render()" << endl; }
};
class MeshRenderer : public Component
{
public:
MeshRenderer(Mesh _mesh, Material _material)
{
mesh = _mesh;
material = _material
}
~MeshRenderer(){}
//override components virtual Render()
void Render(Transform transform)
{
mesh.Render(material);
cout << "MeshRenderer -> Render()" << endl;
}
private:
Mesh mesh;
Material material;
};
GameObject* root = new GameObject();
MeshRenderer meshRenderer(mesh, material);
root->AddComponent(meshRenderer);
//GameLoop
while(!quit)
{
root->Render();
}
It would be the best if you could use unique_ptr:
void AddComponent(std::unique_ptr<Component> component) {
components.push_back(std::move(component));
}
std::vector<std::unique_ptr<Component>> components;
Thus by calling AddComponent() you transfer ownership of the component to containing GameObject.
Looks like you want to pass your objects by reference, use
void AddComponent(Component& component);
to avoid any slicing.
For proper usage with std::vector<>'s and polymorphic inheritance, you'll need smart pointers, e.g. std::unique_ptr<Component> to preserve ownership, or std::shared_ptr<Component> for shared ownership (raw pointers as Component* might work as well, but are far harder to manage correctly).
void AddComponent(std::unique_ptr<Component> componentPtr); // Unique ownership
or
void AddComponent(std::shared_ptr<Component> componentPtr); // Shared ownership
and accordingly
std::vector<std::unique_ptr<Component>> components;
or
std::vector<std::shared_ptr<Component>> components;
It depends on your actual use cases if these Component instances should be uniquely owned by their aggregating parent GameObject class, or not.
To use std::shared<> pointers, that could expire outside their usages scope you may consider using std::weak_ptr<>.
As mentioned, it totally depends on your use cases, and how you want these aggregated components being accessible from outside of the GameObject class.
This is going to be hard to explain so let me use an example:
Imagine you have 10 items on a GUI that are all inheriting members from the same abstract base class. You want to be able to use a loop to check if the user clicked on any of the items. Then you want to be able to call a constructor from that item. The essence of this is that pointers point to objects but I am asking if It is possible to have them point to the actual class or do something with a similar function. Seeing as this explanation could seem a little bit confusing allow me to elaborate with code.
This example will use 3 Items rather than 10 for simplicity
class A //the base class
{
public:
int x,y;// inherited values
virtual void render() = 0;// thats right its an abstract class
};
A * basePointer = NULL;
class a0: public A
{
public:
a0()
{
//do stuff
}
void render()
{
//do render stuff
}
}
class a1: public A
{
public:
a1()
{
//do different stuff
}
void render()
{
//do different render stuff
}
}
class a2: public A
{
public:
a2()
{
//do even more stuff
}
void render()
{
//do even more render stuff
}
}
mainloop()
{
//handle events and get mouse position
for(int i = 0;i < 3;i++)//3 being the number of non-absract classes
{
if(a[i].x = mousePos.x && a[i].y = mousePos.y)
{
basePointer = new a[i]
}
}
}
I understand that trying to reference a1,a2, and a3 using a[i] and a loop was kind of silly but I hope It helps you understand what I am trying to do. Any help help or work around suggestions is appreciated.
The typical way of achieving this is called "Cloning", or another form of the Factory design pattern.
You could add a Clone pure virtual method in the Base class, allowing each object to clone itself.
class A //the base class
{
public:
int x,y;// inherited values
virtual void render() = 0;// thats right its an abstract class
virtual std::unique_ptr<A> Clone() = 0;
};
A typical override is quite simple :
//In class a1
virtual std::unique_ptr<A> Clone()
{
auto clone = new a1();
clone->x = x;
clone->y = y;
return std::unique_ptr<A>(clone);
}
Writing a for loop to render and duplicate objects is then trivial :
std::vector<A*> items;
items.push_back(new a0 ());
items.push_back(new a1 ());
items.push_back(new a2 ());
for(auto item : items)
{
item->render();
auto new_item = item->Clone();
// use the clone
}
Live example on ideone.
I am having a problem with the following code, the overriden virtual functions are not executing. Not sure i'm doing wrong here probably a silly mistake. Anyway this is a game project and I have an array of objects which looks like this (the core::array is an irrlicht array, similar to the vector array)
core::array<GameObject> gameTargets;
This is the GameObject and Zombie definition
class GameObject {
protected:
scene::ISceneNode* node;
public:
int ID;
int hitpoints;
GameObject() {
...
};
void setNode(scene::ISceneNode* inode) {
...
}
virtual void shot(int dmg) {
... [BREAKPOINT HERE]
}
scene::ISceneNode* getNode() {
return node;
}
};
class Zombie : public GameObject {
public:
static const enum Animation {
ZOMBIE_WALK,
ZOMBIE_HURT,
ZOMBIE_DIE,
ZOMBIE_TWITCH,
ZOMBIE_ATTACK,
ZOMBIE_IDLE
};
//We only want to accepted animated mesh nodes for this object
Zombie(int hp, scene::IAnimatedMeshSceneNode* inode) {
...
}
//Override the shot function
void shot(int dmg) {
... [BREAKPOINT HERE]
}
//Animate the zombie
void setAnimation(Animation anim) {
...
}
};
The member functions of the derived classes is never called, I am creating the objects like this
Zombie target(hp, (scene::IAnimatedMeshSceneNode*)node);
and calling the virtual function like this
for(int i = 0; (u32)i<level->gameTargets.size(); i++) {
if(selectedNode == level->gameTargets[i].getNode()) {
level->gameTargets[i].shot(b->damage);
}
}
where b is a pointer to a bullet with a int variable damage and gameTargets contains GameObject
I suspect that you're experiencing slicing because the gameTargets array contains values. I can't tell for sure because I don't know how the core::array template works. See What is object slicing? for a discussion about what slicing is.
To fix this problem, store either raw pointers as in
core::array<GameObject *> gameTargets;
Or use some sort of reference-counted pointer like
core::array<std::shared_ptr<GameObject>> gameTargets; // only available in C++11
array<GameObject> is a container of objects, not a container of pointers. Every object you add to it will be a GameObject and not one of the derived classes (if you add a derived class object, then it'll be "sliced").
Without knowing exactly what your core::array does, I suspect what you really intended to create is an array of std::unique_ptr<GameObject> (smart pointers) along the lines of
core::array< std::unique_ptr<GameObject> > gameTargets;
std::unique_ptr<GameObject> my_zombie(new Zombie);
gameTargets.push_back( my_zombie );
a quick solution would be to make those parent functions as pure virtual functions, as in:
virtual void shot(int dmg) { } = 0;
// edit
and use array of pointer as suggested by Frerich Raabe