Liskov Substitution Principle and class design for a game - c++

In my game I have defined a Screen class, that contains references to a number of visual Entity objects, that may be drawn to the display:
class Screen {
public:
private:
std::vector<Entity*> entities_;
};
All Entity's, have a Draw() function:
class Entity {
public:
void Draw();
private:
int xpos;
int ypos;
};
The Screen is responsible for invoking the Draw() function on each of its Entitys.
The problem is that some (but not all) Entity's also need to be updateable, i.e. over time they will change their appearance/position. The Screen also needs to invoke an Update() function but only for those objects that are Updateable.
My question is:
Does it make sense to derive a class from Entity that has an Update function:
class ChangingEntity : public Entity {
public:
void Update(int time);
};
and have Screen look like this:
class Screen {
public:
private:
std::vector<Entity*> entities_;
std::vector<ChangingEntity*> changing_entities_;
};
If I do the above, then I invoke only Draw() for each of the Entitys, and Draw() and Update() on each of the ChangingEntitys.
Or - should I just put the Update() function in Entity, and if an Entity object can't update, then Update() has no implementation?

There are a couple of things you can enhance here;
It's better not to make the entity draw itself, use a separate Draw() function or Drawable class (Single Responsibility Principle). In your current approach you are making any class that needs drawing to extend Entity, next time you will figure out that a class doesn't need to be an entity to be drawable. So use a separate draw function .
Second you should define what an Entity is, Ogre3D for example define the Entity as an instance of a discrete, movable object based on a Mesh, I don't see that your current definition is sufficient, it only contains position and a draw function. You can define an entity as an Updatable object, and another class called StaticEntity no need for polymorphism. And let the Scene have two separate lists and actually be able to update the objects, again separate the renderer from the scene.
Third your Screen class should be called Renderer and have objects that can be rendered registered based on their static type. You can also have a Drawable interface.

Related

How to 'set' object to a particular base class in multiple inheritence?

I'm trying to inherit from two base classes in C++, that have same named functions. I want an object of the class to 'belong' to the particular base class, is it possible to do so?
I have tried virtual base class (does not suit my particular case) and also tried using scope resolution operator with failure.
I want to do this just by using a single class if it's possible.
I have provide the code;
#include <SFML\Graphics.hpp>
class entity :public sf::CircleShape, public sf::RectangleShape {
public:
entity(int radius = 0) { setRadius(radius); }
entity(sf::Vector2f size) { setSize(size); }
float xspeed =0, yspeed =0;
};
entity ball(6);
entity block(10, 10);
window.draw(block); // ambiguity error as both have base class sf::drawable
window.draw(ball); // and draw function accepts sf::drawable
The problem is that I want "ball" just to inherit from sf::CircleShape and not from sf::RectangleShape.
I expected using scope resolution operator would refer to the circleshape class or I might just be using it wrong.
Edit: The problem I'm trying to solve is that I want to draw "ball" and a rectangular block on to the window, and when I try to do that I'm presented with an ambiguity error as they both are drawable (i.e. both sf::RectangleShape and sf::CircleShape inherit from sf::drawable)
Edit(2): The inheritence diagram
So the function window.draw(); accepts any object of sf::drawable as a parameter. But as I inherit both circleshape and rectangle shape to entity I get an ambiguity error saying base class is ambiguous.
I know this is diamond of death situation however using virtual base classes is not possible as they are part of the SFML library and I do not want to modify them
Problem analysis
class entity :public sf::CircleShape, public sf::RectangleShape
This declaration says that every entity is simultaneously a CircleShape and a RectangleShape. This does not seem to be what you want. You seem to want an entity that can be either a circle or a rectangle. So this inheritance is not the right strategy.
Given that you are adding horizontal and vertical speeds, it seems like you are trying to add a basic animation to elements that can be drawn. Animation is an abstract concept that builds upon drawing (an animation must be drawn, but not all drawings must be animated). Specific moving shapes would build on top of the animation, so your ideal inheritance would be more like the following:
circle -> entity -> drawable
However, there are a few drawbacks. One drawback is that this forces all circles to be animated entities, when some circles might simply be drawn in one spot. Plus, the circle and drawable classes are from a library, so you cannot mess with that particular inheritance scheme.
I can think of two reasonable alternatives off the top of my head. (By the way, "entity" is not a great name for your class, but I'll stick with it for consistency. You should come up with a more descriptive name for the class. It'll be good practice, as naming things is sometimes one of the hardest parts of writing code. :) )
Entity as a base class
You could define entity as a base class, then define a new class for each shape.
--> sf::CircleShape --> sf::Drawable
/
MyCircle --<
\
--> entity
This can work, but it is not great if entity needs to invoke functions defined in Drawable. Not impossible: a side-cast can make it possible to invoke Drawable's functions. It's just that you then have to account for the case where the side-cast fails, as the compiler cannot catch that.
Shapes as members
What I would probably do is give up inheritance altogether. Instead of trying to say that your entity is a circle (inheritance), I would go with the approach that your entity has a circle (membership). One benefit of this approach is that it is not hard to extend this to saying that your entity has multiple shapes, all moving at the same speed. I will, though, stick to a single shape for now.
The difficulty with this approach is that you don't know what shape the entity should have -- should it have a circle or a rectangle? Fortunately, this is the sort of thing polymorphism deals with nicely.
class entity {
std::unique_ptr<sf::Drawable> shape; // <-- Polymorphism to the rescue!
float xspeed = 0.0, yspeed = 0.0;
public:
// Construct a circle.
entity(int radius = 0) : shape(std::make_unique<sf::CircleShape>(radius)) {}
// Construct a rectangle.
entity(sf::Vector2f size) : shape(std::make_unique<sf::RectangleShape>(size)) {}
// Something will go here to support drawing.
};
To support drawing, there are (at least) two options. If it is appropriate to have an entity be a drop-in replacement for a Drawable, it might be reasonable to define an implicit conversion.
operator const sf::Drawable &() const { return *shape; }
If an implicit conversion is not desirable, marking it explicit is an option.
If the only time you need to use an entity as a Drawable is when you call window.draw(), you might want to instead give entity a draw method that takes window as a parameter.
void draw(sf::RenderTarget & target, sf::RenderStates states) const
{ target.draw(*shape, states); }
This makes the Drawable available to RenderTarget::draw() while keeping it out of sight (clutter reduction) at other times.
instead of using inheritance :
simply use direct association :
in your entity class, you want to have RectangleShape and CircleShape , so instead of making the entity class a CircleShape and a RectangeShape at the same time, it's better to consider your entity made of a CircleShape and a RectangleShape .this way you can in your entity class instantiate a RectangeShape and a CircleShape means 'entity' has a Rectangle and a CircleShape
it's the correct way to do it

Getting derived member variable through base class pointer

consider this base class:
struct drawable
{
virtual void draw(sf::RenderWindow &window) const = 0;
};
and this derived class:
struct rectangle : drawable
{
rectangle(sf::Vector2f pos, sf::Vector2f size);
void draw(sf::RenderWindow &window) const;
sf::RectangleShape body;
};
I have similar derived classes for other shapes like circle, line and triangle. I use this function to return shapes based on a string of text I get from a file:
drawable * string_to_object(std::string name)
{
if (name == "RECTANGLE")
{
return new rectangle(sf::Vector2f(20,20), sf::Vector2f(5,5));
}
else if (name == "BALL")
{
return new ball(sf::Vector2f(10,10), 5, sf::Vector2f(0,0));
}
else if (name == "LINE")
{
return new line(sf::Vector2f(30,30), 10, 5);
}
}
Now in my main I have variables like this to test if it works:
auto game_object = string_to_object("BALL");
Now the problem is I need to perform actions/checks on the shape's body, which is a member of the derived class that I cannot access from the drawable pointer variables. It's also a problem that the type of the body is not set, it can be a RectangleShape, CircleShape etc so a getBody() function would need a variable return type. How would I go about getting access to the body in a generic way? I've tried templates but I realized that won't work since it's a runtime problem.
If I understand your question correctly, there are multiple ways how to solve this issue.
Re-think your architecture. You could introduce other virtual functions to drawable that every subclass implements. In these functions you'd implement all the checks/actions you need. Since they are implemented in the base class, they have access to the shape's body and since it is a virtual function of the base you can call these functions from the outside.
Since your drawable object has a virtual function, you could use RTTI to check the type at runtime and perform a dynamic_cast
See: https://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI
I'd prefer the first option whenever you can.
It sounds like you're having trouble deciding what functionality is generic to all drawable objects, and what is specific to rectangle, ball and so on. Attributes and methods that apply to all drawable objects can be declared within drawable, but anything that only applies to a particular kind of drawable (like the width and height of rectangle vs. the radius of a ball) go in the derived classes.
In your example, each of the derived classes must implement the draw method if you want to instantiate them (because it is declared pure virtual in the base drawable class). Each of these specific derived implementations can access the specific attributes of the derived class. So the rectangle::draw method can access the width and height, while the ball::draw method can access the radius.
Then, when you have a collection of pointers to drawable objects (which are really instances of the derived classes) you can simply call the draw method for each of them.
Sorry if this seems overly simplistic - I hope it's clear.

C++ - Recommended way to allow access objects in a class to access the class they are in

I have a class Game with class EnemyManager. EnemyManager deals with spawning of enemies and the logic behind it. The problem is that EnemyManager needs access to functions and other Game objects in the game class. I can think of two ways to handle this.
Pass the address of the class object Game* using this as one of the arguments in the EnemyManager.
Declare a global pointer to a Game object and set it when initializing the Game class. Then extern it into the enemymanager.cpp.
Which is the more advisable way to do this?
Whenever I encounter situations like this I review the overall design of the related classes. If EnemyManager is a member of a Game object and needs to call things within Game, maybe those functions in Game can be factored out into a separate component. If something you are writing is beginning to feel overly-complex or like a hack it's usually time to do some factoring.
When dealing with object oriented designs, it is typically good to think about who will act how on what to find a first version of a design. After having written this version, one often finds the weaknesses and rewrite it for the second iteration.
So, in this case, the Game class manages the world (I assume) and offers different ways to manipulate it. Your EnemyManager manages one aspect of the world, enemies, but they do live inside the world.
class Enemy {
public:
Enemy(Location& location, int hitpoints);
bool Move(Direction& direction);
};
class Game {
public:
bool CreateInitialState();
bool AddEnemy(Enemy& enemy);
bool AddBullet(Location& location, Direction& direction, int speed);
void Render();
};
class EnemyManager {
public:
EnemyManager(Game& game);
void MoveEnemies();
};
In this first version, all types see each other as proper classes and manipulates things by calling the appropriate method. This offers little support for expanding on the game if you want to add new things to it.
This is where interfaces become handy and you can try to think about how the different parts will interact instead of how they should be implemented.
class Canvas {
public:
// Different graphical primitives.
};
class GameObject {
public:
virtual ~GameObject() {};
virtual void Draw(Canvas& canvas) = 0;
virtual bool Move(Direction& direction) = 0;
};
class GlobalState {
public:
virtual AddGameObject(GameObject& gameObject) = 0;
};
class Game : public Canvas, public GlobalState {
public:
bool CreateInitialState();
void Render() {
// Send itself to the Draw method in all GameObjects that have been added
}
// Other game logic
};
class Enemy : public GameObject {
// This can be specialized even more if you need to
};
class Bullet : public GameObject {
// This can also be specialized even more if you need to
};
This separates design from implementation and, as I see it, is a good way to end up with a proper first attempt.
It is hard to say without knowing the overall architecture layout, but my 2 cents:
The way you describe as a first one is called the dependency injection and is widely used all around. You should keep an eye on what methods/fields you're making public.
I assume that Game class has the methods that should not be accessible from the EnemyManager class, thus is seems like it's a good idea to create the interface which has the declaration of the methods that are used by EnemyManager and then pass the pointer to the EnemyManager instance (instead of the Game).
For example: The Game class implements IGameEnemyManager, and you're passing IGameEnemyManager using this as one of the initialization arguments.
If you are handling game objects in EnemyManager, why is it part of the class Game ? I suppose you should consider reviewing your design as there are chances of circular reference problem if you don't handle the scenarios well.
Consider segregating both the classes to ensure a single responsibility principle.
Define proper interface in yourEnemyManagerto Game object as argument and act on the functions
These are little suggestions that I can think of with limited idea about your design
You're absolutely need to use the 1st approach, but with a few changes: you should disintegrate your Game class to more components. For example you can create a SceneManager class, which is responsible for all game object's creation/management. When you're instantiating the EnemyManager - just pass a pointer to it:
// in SceneManager
EnemyManager* emgr = new EnemyManager(this);
InterfaceManager* imgr = new InterfaceManager(this);
Note that your SceneManager class should provide a complete interface
// in EnemyManager
GameObject* spawnEnemyAt(string name, EnemyClass* eclass, Vector3 position, AIBehaviour* behaviour)
{
GameObject* myEnemy = smgr->createGameObject(name, position, etc...);
//register an enemy in the enemies list, initialize it's behaviour and do any other logic
return myEnemy
}
This approach should help you not to ruin your architecture and not to be captured in the friend(class)-zone.
[Upd.] Note that my approach assumes that all objects on the scene are GameObjects, there's neither Enemy nor Player classes. Every GameObject may has a Renderer, Animator, AIBehaviour components.

my c++ game architecture

I'm a fairly experienced programmer, but I'm still relatively new to OOP architecture and design in c++.
Most of my experience is with C# and Java. I recently endeavored to code up a simple game engine in c++.
I used SDL for the graphics. In this post, I would like to discuss my architecture and to get some feedback
on it. Particularly, I've run into a design issue that I would like some help with. So, here goes:
In my main function, I initialize all of the SDL stuff for drawing to the screen, etc.
Then I instantiate all of the objects that I intend to use: floor, wall, player, etc.
Next I start the main loop. This loop executes each object's movement, collision detection and collision handling functions, and redraws them.
The main loop runs until the application is quit, drawing one frame each iteration.
My problem is this:
I tried to do a kind of interface-style design. It involves a series of
abstract base classes that allow each object to implement a behavior. For example, if I want an object to be movable,
it would have to inherit from the movable base class which contains a virtual function called move() and some position
coordinates. If I wanted it to be collidable, the object would inherit from the collidable abstract class, which
contains the virtual functions checkCollision() and handleCollision() as well as a hitbox member variable. An object
like the player inherits from both of these base classes as well as several others.
This works well enough as long as I'm doing everything by hand in the main loop. I can just say:
player.move();
player.checkCollision();
player.handleCollision();
player.draw().
and it's fine. But I would like to
be able to have a vector or array of generic objects in the main loop and do something like this:
for each object in vector
if object is of type movable
object.move();
if object is of type collidable
object.checkCollision();
I thought that I could accomplish this with dynamic casting, but I really haven't been able to come up with anything.
I've tried storing them as void pointers, but that doesn't work the way I want it to. I've been reading about this
gameobject-component architecture for video games that I might try, but I'd really like to salvage what I've already
written. I figure this is a good learning opportunity. If anybody has any ideas I'd really appreciate it. How does my architecture compare to other simple game engine designs? does my interface architecture make sense or is it totally wonky?
If you work in C++, try SFML, it's faster than SDL, and if you know OpenGL, you can use it too.
For your problem:
class Entity {
//constructor and other stuff
void virtual exec() =0; ///<= pure virtual method
};
class Movable : Entity {
void move(); //do somthing
void exec() {move();};
};
class Collidable : Entity {
void col(); //do your job
void exec(){col();};
};
std::vector<Entity*> e_v;
///push some instance
for (Entity* e : e_v)
e->exec();
What about using the template method pattern and non-abstract empty virtual functions in the base class?
class Entity
{
void update()
{
move();
checkCollision();
}
virtual void move() {}
virtual void checkCollision() {}
};
class Movable : public virtual Entity
{
virtual void move() {} // Stuff
};
class Collidable : public virtual Entity
{
virtual void checkCollision() {} // Stuff
};

Designing classes for inheritance

Suppose I have a class Entity.
And then I have n number of classes which is derived from Entity
eg :
class Snake : public Entity{...};
class Mouse : public Entity{...};
Now I have a class player that is an entity.
Can I create a class player that inherits from any type of entity?
eg :
class Player : public Entity -->(but instead of entity be any type of entity)
Can this be done?
Is this achieved by using templates?
I've read that the templates can be explicitly specified in a cpp file i.e
template class Entity<Snake>;
I am trying to achieve the following
In my player class I have a moveCamera function inside move Now only when a player moves, the camera moves .. If an AI Snake moves the camera should not move.
this is my render function in the entity class which is virtual
void Entity::Render(float interpolation)
{
if(currentAnimation != 0){
float x = this->currLocation.x - (this->currentVelocity.x * (1.0f - interpolation)) - camera->getLocation(L_FACTOR_CURRENT).x;
float y = this->currLocation.y - (this->currentVelocity.y * (1.0f - interpolation)) - camera->getLocation(L_FACTOR_CURRENT).y;
currentAnimation->Render(x,y);
}
}
This is my gameUpdate function and basically moves an entity to its respective world co-ordinates
void Entity::GameUpdate(float gameUpdateDelta)
{
this->Move();
}
Therefore for my player's move function I will call the camera's move function and then call the base class's move function... Now is it possible to call the extended class of the base's class move function..
My Move function is virtual and therefore a snake and mouse can move differently..
You may want to write a template class Player that inherit from Template parameter.
template< typename Derived >
class Player:
public Derived, // we believe that Derived inherits Entity
public IPlayer // makes sense if Player is not a Entity only interface
{
... some declaration here ...
void update(); // some virtual method from Entity interaface
void player_action(); // some virtual method from IPlayer interaface
}
When create a concrete type of player, you may place it one your scene.
IPlayer* player1 = new Player<Snake>("Player1");
Entity* playerEntity = dynamic_cast< Entity* >( player1 );
if( playerEntity ) // test if object can be placed on scene
{
scene->add( playerEntity );
}
You may also need to know how to write partial template specialization of class methods.
Also you may find boost enable_if as a powerful toy.
It would be more helpful for people to help if you can publish the interface (just the class definition) of your current design. It looks like you need to make player own snake and mouse. Use observers if you want some action to be associated with other actions.