I have been working to create a game in C++. A World class contains all game-state related objects and the main game loop function.
class World {
Clock clock;
Map map;
std::vector<Entity*> entities;
...
All entities in my game inherit from the abstract class Entity. For example:
class Player: public Entity {...};
class Enemy: public Entity {...};
class Bullet: public Entity {...};
Entities are updated each frame by iterating through a list of all entities and calling the update() method on each one.
To account for varying frame rates, I pass the elapsed time in each frame as a float delta to the update method (like most other game engines). The problem I run into is all the different things an entity might need to reference in update().
The Entity class defines the virtual update method as follows:
virtual void update(float delta) = 0;
Calling this function from the game loop looks like this:
for(int i = 0; i < entities.size(); i++) {
entities[i]->update(clock.get_delta());
}
This works great. But now, let's say for example that we want to add a feature where Player can move faster on different surfaces. To know what surface the player is on would require access to the Map object belonging to the World class.
We could add that to the virtual update method:
virtual void update(float delta, Map *map) = 0;
But now Enemy and Bullet's update functions have to take the new map parameter even though they don't use it.
The same would go for any other object or variable an entity needs in its update method. Before long, there would be dozens of parameters (game map, list of other entities, game state information) cluttering the method definition.
My question is: How can I prevent this? I tried passing a reference to World as the only argument, but it resulted in circular dependencies.
I solved this in my game by storing a Map* in the Player class. Works great if you never have to change it.
Related
TLDR: I think I'm using unique_ptr wrongly, but I'm not sure how to do this otherwise.
I am trying to write a simple physics engine wrapped up in an entity component system. The physics world is essentially the main manager class for all objects that are affected by physics, that should contain all physics properties for entities in the world(ideally stored in a std::vector). In every update loop, after the engine solves constraints, it iterates through the vector of physics objects stored in the physics world and applies the forces, accelerations, impulses etc.
There is also a SceneManager that stores more general entities (eg. for rendering etc) and a SceneEntity which stores behaviour specific components.
I chose to use vector<unique_ptr> for storage because there should only be one instance of each entity (physics or scene) - the end user can handle the raw pointer and pass it to functions etc, but the lifetime of the entities themselves are handled by the SceneManager and PhysicsWorld.
The general structure is as follows:
class PhysicsWorld
{
private:
unique_ptr<PhysicsEntity> entities;
public:
void addEntity(PhysicsEntity * entity)
{
unique_ptr<PhysicsEntity> entity_ptr(entity);
entities.push_back(std::move(entity_ptr));
}
}
class PhysicsEntity
{
private:
unsigned int id;
float gravity;
public:
Entity();
~Entity();
void setGravity(float val);
}
PhysicsWorld world{};
PhysicsEntity * physent = new PhysicsEntity{};
physent->setGravity(3.0f);
world.addEntity(physent)
SceneManager scene{};
RigidbodyComponent * rbcomp = new Rigidbody{ent};
SceneEntity * sceneEnt = new SceneEntity{};
sceneEnt->addComponent(rbcomp);
scene->addEntity(sceneEnt);
My problem is that when I run this code, I get an error from xutility saying "attempting to reference a deleted function" - I believe it occurs somwhere around world.addEntity(). After much searching, I've concluded that this is due to my use of unique_ptr. Is this error occurring because unique_ptr is not the right tool for the job, or am I missing something - or is the error elsewhere?
The issue was that I had not defined move constructors and move assignment operators for PhysicsWorld, so it was using the default ones, which in turn were calling the (deleted) copy constructors for the PhysicsEntity stored in the vector. The code compiled after I defined those.
I have an entity-based-component system.
A GameObject (entity) keeps all pointers to all related GameComponents.
All GameComponent keep a pointer to the GameObject.
If I know that I have to query one component from another component often (Physics<->Graphics), I will cache pointer of another component.
class Physics : public GameComponent {
Graphics* graphic; //different GameObject
};
class Graphics: public GameComponent {
Physics * physic ; //different GameObject
};
The cost of querying pointer from each other (Physics->Graphics and Graphics->Physics) is very small.
As time go by ...
Storing Graphics's pointer in Physics and vice versa becomes less sensible and causes maintainability problem.
For example, if I want to add a new relation, e.g. Physics-Player, I will have to add a field into both classes :-
add Player* to class Physics
add Physic* to class Player
If I proceed, totally simple components will be clogged with many fields about the relation that hard to be tracked and maintained.
class Physic: public GameComponent {
Graphic* graphicsMain;
Graphic* graphicsSecondary;
Player* playerPtr;
Enemy* enemyPtr;
//10+ as project grow
}
Code about query an object from another object are scattering around in many places.
Question: How to solve the maintainability issue without performance penalty?
My workaround
I created a new GameComponent named RelationNode.
Then create a new system named Relation to manage every type of relation in a single place.
Pros: I can code all utility that I want, and it will work for every relation type.
class Physics : public GameComponent {
//no keep Graphics pointer anymore ... clean :)
};
class Graphics: public GameComponent {
//no keep Physics pointer anymore ... clean :)
};
public RelationNode : public GameComponent {
//... some code ... cache other component ...
RelationNode* slot01; //shared Physics->Graphics and Graphics->Physics
RelationNode* slot02; //Physic->graphicsSecondary
.......
RelationNode* slot20;
//^ I can reuse same slot of variable if I am sure.
//instead of "RelationNode*" , it can also be "GameObject*"
};
class Relation{
Graphics* getGraphicsFromPhysics(Physics* gameComponent){
RelationNode* a = toNode(gameComponent); //waste 1-2 indirection
RelationNode* b = queryGraphicFromPhysics(gameComponent);
Graphics* bCom= fromNode(b); //waste 1-2 indirection
return bCom;
}
//the real code is more elegant than this, but suffer the same issue
};
Now my code is so clean but suffer performance penalty from indirection.
It cost about 1-30% (profiled), depends on test case.
I have another crazy idea about add field to component using macro, but I don't like macro - it tends to cause other problems.
My old idea is to use hashMap e.g. HashMap<Graphics*,Physics*>, but it is much slower than my workaround (tested).
I have base class DataProcessor. It is base class for calculators of position in some coordinate system. So, for example, it can have descendants like: SphericDataProcessor, CartesianDataProcessor. There is base class CookedDataCatalogue, which is base class for containers of some objects' positions. So every DataProcessor should be able put its data to every CookedDataCatalogue. I can imagine something like this:
class CookedDataCatalogue
{
virtual void Transform(DataProcessor* dp) = 0;
virtual void PutData(???) = 0;
}
class CookedDataCatalogue1 : public CookedDataCatalogue
{
void Transform(DataProcessor* dp) override
{
dp->TransformTo(this);
}
}
class CookedDataCatalogue2 : public CookedDataCatalogue
{
...
}
class CookedDataCatalogue3 ...
class DataProcessor
{
virtual void Process() = 0;
virtual void TransformTo(CookedDataCatalogue1* c) = 0;
virtual void TransformTo(CookedDataCatalogue2* c) = 0;
virtual void TransformTo(CookedDataCatalogue3* c) = 0;
}
But I don't like it. First of all void Transform(DataProcessor*) migrates from base class to all children**. Second, if I build it as library, other user can not add his own CookedDataUserCatalogue, because he can't add another void TransformTo(CookedDataUserCatalogue). Third, I don't know how to write function PutData(), because every Catalogue uses his own data to contain. Should it be templated?
What is a solution? Is there any programming pattern that I missed?
There are two ways to do this as well as the Double Dispatch Pattern mentioned in the comments:
Baseline
The first is that you specify a "baseline" set of co-ordinates. In order to convert first you transform to the core set and then you transform from that.
Advantages: You only need to write a toBaseline and fromBaseline for any number of different DataProcessors. Adding a new DataProcessor is as simple as creating it and then writing the transformation to and from the core set.
Disadvantages: Performance will suffer as you do two transformations in most cases. Accuracy may suffer due to losses either in representation or conversion.
Transformer objects
Create an interface that converts an object from DataProcessor to DataProcessor.
Create an instance of that interface for each supported transformation.
Have a utility class that has a map of source and destination pairs to the correct transform to use. Call a method on that utility class to perform the transformation on demand.
Advantages: No wastage from having to do multiple transformations.
Disadvantages: n^2 Transform objects need creating where n is the number of different DataProcessor objects. When creating a new DataProcessor you will need to write and add Transform objects for each DataProcessor added. Missing Transforms will be detected at run time not compile time.
I am doing an assignment for the university course and me and my partner have a problem. Program we are making is a game.
We have several classes, which all inherit from the base class, called Creature. These are all enemies player needs to deal with and they all run their own AIs. There are 4 different types of child classes, all within namespace Creature(Including parent, Creature), with one class having special functions that only it needs. This class is called Bunny.
Now, my job is to call AI functions as needed. Problem is, I do not always know what class I am calling out, as such, when I ask the game board to tell me what Creature I get.
All enemies are saved as pointers like so, in game board squares:
struct Square
{
// Pointers to Morso class, where the enemy is saved
Creature::Creature* creature;
//Undeeded stuff removed
};
Now, this is all and fine until we need to access to special functions. Pupu will multiply if certain conditions are filled. As such, with in Pupu there are few functions I need to call to make sure it carries out it's act correctly.
However, here comes the problem.
I call our board class to give me the creature that is in the coordinates I give to it.
void GameEngine::GameEngine::runAI()
{
Creature::Creature* creature= NULL;
for(unsigned int y = 0; y < dimY; y++)
{
for(unsigned int x = 0; x < dimX; x++)
{
Coordinate target;
target.setX(x);
target.setY(y);
creature= board_->returnCreature(target);
//If there is a creature in the target, run its AI
if(creature!= NULL)
{
//If it is, check special procedures
if(creature->returnType() == "bunny")
{
bunnyReproduce(creature);
}
creature->ai();
}
}//for x
}//for y
}
Now, :
void GameEngine::GameEngine::bunnyReproduce(Ccreature::Creature* creature)
{
//Checks that it really is a bunny
if( creature->returnType() != "bunny"){ return; }
//Check is there another bunny near
creature->checkForMate();
}
The problem is, creature, at this point, can't call for checkForMate, which is public member of Bunny, but not Creature. Do we need to make virtual function into Creature?
I tried making checkForMate into Creature::Bunny, but since the original value I try to give to it is Creature class, I can't do so. Do we need to to create an empty virtual function in Creature class and then override it it Bunnyclass?
I am running Qt Creator 2.7.0, with QT 5.0.2.
You should add virtual function reproduce to Creature class and implement it in Bunny or any other creature you may later add to the game. So that any creature will reproduce itself in it's own way. You don't even need to check creature type in this case. Since if you have some non reproducible creatures, you may just implement reproduce as empty method that will do nothing.
Ideally, your engine shouldn't need to care at all what kind of creature it's working with.
If you want the bunny to reproduce on each ai() step, why not do it in the bunny's ai()?
After all, shouldn't it be the bunny's responsibility to decide when to reproduce, rather than some almighty external Engine?
void Creature::Bunny::ai()
{
if (niceMateNearby())
reproduce();
else
eatCarrotsAndJumpAround();
}
I am making a basic render engine.
In order to let the render engine operate on all kinds of geometry,
I made this class:
class Geometry
{
protected:
ID3D10Buffer* m_pVertexBuffer;
ID3D10Buffer* m_pIndexBuffer;
public:
[...]
};
Now, I would like the user to be able to create his own geometry by inheriting from this class.
So let's suppose the user made a class Cube : public Geometry
The user would have to create the vertexbuffer and indexbuffer at initialisation.
This is a problem, since it would recreate the vertexbuffer and indexbuffer each time a new Cube object is made. There should only be one instance of vertexbuffer and indexbuffer per derived class. Either that, or a completely different design.
A solution might be to make separate static ID3D10Buffer* for the inheriting class , and set the pointers of the inherited class equal to those in the constructor.
But that would require a static method like static void CreateBuffers() which the user would have to call explicitly one time in his application for each type he decides to make that inherits from Geometry. That doesn't seem like a nice design.
What is a good solution to this problem?
You should separate the concept of an instance from the concept of a mesh. This means you create one version of the Geometry for a cube that represents the vertex and index buffer for a cube.
You then introduce a new class called GeometryInstance which contains a transformation matrix. This class should also have a pointer/reference to a Geometry. Now you can create new Instances of your geometry by creating GeometryInstances that all refer the same Geometry object not duplicating memory or work when creating a new box.
EDIT:
Given that you have the Geometry class from the question and a Mesh class as in your comment your Mesh class should look something like this:
class Mesh {
private:
Matrix4x4 transformation;
Geometry* geometry;
public:
Mesh(const Matrix4x4 _t, Geometry* _g) : transformation(_t), geometry(_g) {}
}
Now when creating your scene you want to do things like this
...
std::vector<Mesh> myMeshes;
// OrdinaryGeometry is a class inheriting Geometry
OrdinaryGeometry* geom = new OrdinaryGeometry(...);
for(int i = 0; i < ordinaryGeomCount; ++i) {
// generateTransform is a function that generates some
// transformation Matrix given an index, just as an example
myMeshes.push_back(Mesh(generateTransform(i), geom);
}
// SpecialGeometry is a class inheriting Geometry with a different
// set of vertices and indices
SuperSpecialGeometry* specialGeom = new SuperSpecialGeometry(...);
for(int i = 0; i < specialGeomCount; ++i) {
myMeshes.push_back(Mesh(generateTransform(i), specialGeom);
}
// Now render all instances
for(int i = 0; i < myMeshes.size(); ++i) {
render(myMeshes[i]);
}
Note how we only have two Geometry objects that are shared between multiple Meshes. These should ideally be refcounted using std::shared_ptr or something similar but it's outside the scope of the question.
What would be the point of sub classing Geometry in your cube example? A cube is simply an instance of Geometry which has a certain set of triangles and indices. There would be no difference between a Cube class and a Sphere class, other than that they fill their triangle/index buffers with different data. So the data itself is what is important here. You need a way to allow the user to provide your engine with various shape data, and to then refer to that data in some way once its made.
For providing shape data, you have two options. You can decide to either keep the details of Geometry private, and provide some interface that takes raw data like a string from a file, or a float array filled in some user made function, creates a Geometry instance for that data, and then gives the user some handle to that instance (or allow the user to specify a handle). Or, you can create some class like GeometryInfo which has methods addTriangle, addVertex etc which the user fills him/herself, and then have some function that accepts a GeometryInfo, creates a Geometry instance for that data and then gives the user some handle again.
In both situations you need to provide some interface that allows the user to say "here's some data, make something out of it and give it some handle. Minimally it would have a function as I described. You would need to maintain a map somewhere of created Geometry instances in your engine. This is so you enforce your one instance per shape rule, and so you can associate what the user wants ("Ball", "Cube") with what your engine needs (Geometry with filled buffers).
Now about the handle. I would either let the user associate the data with a name, like "Ball", or return some integer that the user would then associate with a certain "Ball" instance. That way when you make your Rocket class, the user can then request the "Ball" instance from your engine, various other objects can use the "Ball" and everything's fine because they're just storing handles, not the ball itself. I wouldn't advise storing a pointer to the actual Geometry instance. The mesh doesn't own the geometry, because it can share it with other meshes. It doesn't need access to the geometry's members, because the renderer handles the grunt work. So it is an unnecessary dependency. The only reason would be for speed, but using hashing for your handles would work just as good.
Now for some examples:
Providing shape data:
//option one
engine->CreateGeometryFromFile("ball.txt", "Ball");
//option two
GeometryInfo ball;
ball.addTriangle(0, 1, 0, 1);
ball.addTriangle(...);
...
engine->CreateGeometryFromInfo(ball, "Ball");
Refering to that data using a handle:
class Drawable
{
std::string shape;
Matrix transform;
};
class Rocket : public Drawable
{
Rocket() { shape = "Ball";}
//other stuff here for physics maybe
};
class BallShapedEnemy : public Drawable
{
BallShapedEnemy() { shape = "Ball";}
...
}
...
...in user's render loop...
for each (drawable in myDrawables)
{
engine->Render(drawable.GetShape(), drawable.GetTransform());
}
Now, having a separate class for each different game object such as Rocket is debatable, and is the subject of another question entirely, I was just making it look like your example from a comment.
This may be a sloppy way of doing it but could you not just make a singleton?
#pragma once
#include <iostream>
#define GEOM Geometry::getInstance()
class Geometry
{
protected:
static Geometry* ptrInstance;
static Geometry* getInstance();
float* m_pVertexBuffer;
float* m_pIndexBuffer;
public:
Geometry(void);
~Geometry(void);
void callGeom();
};
#include "Geometry.h"
Geometry* Geometry::ptrInstance = 0;
Geometry::Geometry(void)
{
}
Geometry::~Geometry(void)
{
}
Geometry* Geometry::getInstance()
{
if(ptrInstance == 0)
{
ptrInstance = new Geometry();
}
return ptrInstance;
}
void Geometry::callGeom()
{
std::cout << "Call successful!" << std::endl;
}
Only problem with this method is you would only ever have one Geometry object and I'm assuming you might want more than one? If not it could be useful, but I think Lasserallan's method is probably a much better implementation for what your looking for.