How can I refractor the following, to move my drawing functions from the h-file into a GraphicsManager class?
//drawingFunctions.h
void drawTexturedQuad( Texture texture, Vector2 pos, Vector2 dim) {
// bind texture...
glBegin(...); // draw
//...
glEnd(...);
}
//class file
#include "drawingFunctions.h"
class Player {
void drawPlayer(){ drawTexturedQuad( texture, pos, dim) }
};
class Enemy {
void drawEnemy(){ drawTexturedQuad( texture, pos, dim) }
};
class Item {
void drawItem(){ drawTexturedQuad( texture, pos, dim) }
};
// and so on for the other components
//gameloop file
// instantiate components objects
while (true) {
// input, logic
Player.drawPlayer();
Enemy.drawEnemy();
Item.drawItem();
// and so on
}
(The code is obviously simplified, I am just asking about the drawing here)
Should I...
pass a pointer to the GraphicsManager to every call of drawPlayer, drawEnemy etc from within the gameloop
have Player, Enemy etc have a pointer to GraphicsManger as a data member
have Player, Enemy etc extend a drawableGameComponent class that has a pointer to GraphicsManager as a data member
something else?
That sounds like a perfect use case for inheritance:
class Drawable
{
public:
void draw()
{
// gl stuff
}
protected:
Texture _texture;
Vector2 _pos;
Vector2 _dim;
};
class Player : Drawable
{
public:
// should modify _texture _pos and _dim somewhere.
};
// same thing for the other objects.
I would pass a renderer to the model, and ask it to draw itself.
class Player
{
public:
void draw(Renderer& renderer);
};
class Enemy
{
public:
void draw(Renderer& renderer);
};
Note you don't have to name the function drawPlayer or drawEnemy, because you already know that it's a Player or an Enemy by the class type. This uniform calling convention is perfect for extracting into a common interface:
class Model
{
public:
virtual void draw(Renderer& renderer) = 0;
virtual ~Model() {}
};
Then you can have each of your models inherit from Model, and each implement draw.
As I mentioned in a comment on #J.N.'s answer you can also have Renderer be an abstract class. For example I worked on a project which used OpenGL, GDI+, and also needed to create printouts of schematics.
class Renderer
{
public:
virtual render(const Triangle& triangle, const Texture& texture) = 0;
virtual ~Renderer() {}
};
I would go for the first possibility: passing the pointer to the GraphicsManager in the call. Eventhough it seems a bit overkill, the knowledge of which GraphicsManager is used is maintained on higher level and can be modified easier later on.
Having said this, I would still inherit from a Drawable interface and put the items that need to be drawn in a container, so you can just iterate through it to display the items via a virtual drawItem() function.
Like so (C++03, not tested):
std::vector<Drawable*> Items;
Items.push_back(&player);
Items.push_back(&enemy);
...
for (std::vector<Drawable*>::iterator it = Items.begin(); it != Items.end(): ++it)
{
(*it)->drawItem(&graphMgr);
}
Related
(sorry for my bad english)
I have a base class with vector of pointers on Drawable objects in it and method draw() that uses data from this vector.
class GameObject
{
protected:
std::vector<Drawable*> drawable;
...
void GameObject::draw() { for (const auto& object : drawable) window.draw(*object); }
In the derived classes I want to have an ability to add some Drawable objects
class Player : public GameObject
{
protected:
RectangleShape shape;
...
Player::Player(float x, float y, float z)
{
shape.setPosition [...]
drawable.push_back(&shape);
...
and draw them using method of base class pointer
std::vector<GameObject*> gameObjects;
...
for (auto& gameObject : gameObjects) gameObject->draw();
The program crashes (I think because the base class don't know anything about vector data in derived class).
I understand that I could make this method pure virtual and define it in the derived classes, but it's not that convenient. Maybe there is another way more similar to this?
upd:
Level::Level()
{
player = Player(500.f, 500.f); //Player player; in header file
gameObjects.push_back(&player);
}
void Level::display()
{
for (auto gameObject : gameObjects) gameObject->draw();
}
The problem is in the code added by your edit -- it looks like my crystal ball is working today.
You're creating a temporary Player and moving it into the player member variable. That ends up with a vector holding the address of the shape inside the temporary Player, which is immediately destroyed, leaving a dangling pointer.
Use a ctor-initializer-list to avoid the move:
Level::Level()
: player(500.f, 500.f /* where did Z go? */)
{
gameObjects.push_back(&player);
}
And disable the assignment operators to prevent doing this by accident in other places:
class Player
{
// ...
Player& operator=(const Player&) = delete;
Player& operator=(Player&&) = delete;
};
here is the structure of my program:
class Game
{
public:
unsigned int progressFlags;
sf::RenderWindow appWindow;
Screen* currentScreen;
Game(const unsigned int& width, const unsigned int& height,
const unsigned int& bitsPerPixel, const std::string& windowName);
~Game();
void drawScreen();
};
Game contains a Screen which is defined as:
class Screen
{
public:
std::vector<sf::Drawable*> sceneElements;
sf::Sprite backgroundSprite;
Screen();
virtual ~Screen();
protected:
sf::Texture backgroundTexture;
};
Elements of std::vector sceneElements are collected from screens like this:
sceneElements.push_back(&backgroundSprite);
At last, I am trying to draw all my graphic objects using a simple method:
void Game::drawScreen()
{
for (unsigned int i = 0; i < currentScreen->sceneElements.size(); i++)
appWindow.draw(*currentScreen->sceneElements(i));
}
But appWindow.draw() fails. I think it is something about dereferencing pointers (some basic c++ knowledge I cant just remember), but I don't know how to fix it. I would appreciate any help.
I'd just derive your custom classes from sf::Drawable (and potentially sf::Transformable). This way drawing hierarchically is very easy and basically done by SFML. The following snippets are written from memory; there might be typos. :)
You'll just have to subclass your Screen class:
class Screen : public sf::Drawable
{
public:
std::vector<sf::Drawable*> sceneElements;
sf::Sprite backgroundSprite;
Screen();
virtual ~Screen();
virtual void draw(sf::RenderTarget &rt, sf::RenderStates states) const;
protected:
sf::Texture backgroundTexture;
};
Inside draw() you'd just iterate over all your elements (similar to the way you do already):
void draw(sf::RenderTarget &rt, sf::RenderStates states) const
{
for (const auto &e : sceneElements)
rt.draw(*e, states);
}
Here we're dereferencing once to get from a pointer back to the object, which is then passed by reference (where inheritance does the rest).
Game::drawScreen() becomes more simple as well:
void Game::drawScreen()
{
appWindow.draw(*currentScreen);
}
Once again, derefrencing once to go from the pointer to the actual object (passed by reference).
Also note that your original design violates encapuslation, by Game having to know how to work with stuff that's inside your Scene. So if you change things inside Scene, you'll have to adjust Game accordingly. Using inheritance, you're avoiding this issue.
In the following code I can't reach my subclass. I have to have my subclass underneath the superclass to inherit it, but the superclass won't know what to point to unless the subclass is defined before it.
class ParticleSystem
{
Particle *ptr_to_particles;
void update()
{ // Loop through number of particles
// and call their update method.
ptr_to_particles[i].update();
}
}
class Particle : public ParticleSystem //Inherits ParticleSystem
{
void update();
}
Or if anyone can offer suggestions about how to do it differently, I welcome it. Thanks.
I think you should reconsider your design. A ParticleSystem should have a number of Particle (e.g. std::vector<Particle>). It doesn't seem correct for a Particle to be a type of ParticleSystem. Something like this
class Particle
{
public:
void update();
};
class ParticleSystem
{
public:
void update()
{
for (auto particle : _particles)
{
particle->update();
}
}
private:
std::vector<Particle*> _particles;
};
You should probably change your design. A Particle is not a logical subtype of a ParticleSystem. A ParticleSystem is just a composition of Particles, not a supertype of Particle.
class Particle
{
void update();
};
class ParticleSystem
{
Particle* particles;
void update()
{
// forall i
particle[i].update();
}
};
I'm coding a game engine and I have this class set up for objects:
class SceneManager //controls everything in the "world" game
{
public:
void Add(SceneObject* object); //adds to the vector
private:
vector<SceneObject*> _worldObjects; //the vector that contains all of them
}
And all classes I work on the game inherit from SceneObject:
class SceneObject
{
public:
virtual void Draw() = 0;
}
class Image : public SceneObject
{ }
class Sprite : public SceneObject
{ }
class Model3D : public SceneObject
{ }
So I know I can call Draw() for all objects in my vector.
But I've been working on optimizations and I'm trying to get rid of all inheritance and virtual functions, and use composition instead, since they can't be inlined and seems to be a major performance issue when performed on a per-object basis.
I'm looking for some C++ technique that I can use to be able to store a bunch of SceneObjects in my vector, and then call Draw() on it and it properly draws the object related to it. This will also work for the Update() function I'm using as virtual.
So this code:
void SceneManager::Add(SceneObject* object)
{
_worldObjects.push_back(object);
}
void SceneManager::DrawTheWorld()
{
for(unsigned int i = 0; i < _worldObjects.size(); i++)
{
_worldObjects[i]->Draw(); //SceneObject's being called
}
}
...would become:
void SceneManager::Add(Image* image)
{
SceneObject* object = new SceneObject();
//link object to image somehow, tried to use it as a member of image
_worldObjects.push_back(object);
}
void SceneManager::DrawTheWorld()
{
for(unsigned int i = 0; i < _worldObjects.size(); i++)
{
//_worldObjects[i]->
//I need somehow to be able to get the pointer back to the original class
//It can be an image, sprite, model3d, anything
}
}
I don't think if I add a switch or if/elses and removing the virtual I'd gain any performance, so I'm trying to figure if there's a clean way to deal with this.
Any ideas?
You can use free functions to model the drawable aspect of your objects:
#include <iostream>
class Image { };
class Sprite { };
class Model3D { };
namespace draw_aspect
{
void draw(Image const& image) { std::cout << "drawing image\n"; }
void draw(Sprite const& sprite) { std::cout << "drawing sprite\n"; }
void draw(Model3D const& model3D) { std::cout << "drawing model3D\n"; }
}
Now, either use three separate vectors (this could well be most optimal, depending on the ordering relationship between the objects across collections?), or consider a variant type vector:
1. Using variant types
#include <boost/variant.hpp>
using SceneObject = boost::variant<Image, Sprite, Model3D>;
namespace draw_aspect {
struct draw_visitor : boost::static_visitor<> {
template <typename T> void operator()(T const& t) const { draw(t); }
};
void draw(SceneObject const& sobj) {
static const draw_visitor _vis;
boost::apply_visitor(_vis, sobj);
}
}
A complete proof of concept of the latter: Live on Coliru
#include <vector>
class SceneManager //controls everything in the "world" game
{
public:
void Add(SceneObject v) { _worldObjects.emplace_back(std::move(v)); }
friend void draw(SceneManager const& sm) { return sm.draw(); }
private:
void draw() const {
for(auto& sobj : _worldObjects)
draw_aspect::draw(sobj);
}
std::vector<SceneObject> _worldObjects; //the vector that contains all of them
};
int main()
{
SceneManager sman;
sman.Add(Image());
sman.Add(Sprite());
sman.Add(Model3D());
sman.Add(Image());
draw(sman);
}
Outputs
drawing image
drawing sprite
drawing model3D
drawing image
2. Separate collections
The alternative using separate vectors: Live on Coliru
class SceneManager //controls everything in the "world" game
{
public:
void Add(Image v) { _images .emplace_back(std::move(v)); }
void Add(Sprite v) { _sprites .emplace_back(std::move(v)); }
void Add(Model3D v) { _model3Ds.emplace_back(std::move(v)); }
friend void draw(SceneManager const& sm) { return sm.draw(); }
private:
void draw() const {
for(auto& sobj : _images) draw_aspect::draw(sobj);
for(auto& sobj : _sprites) draw_aspect::draw(sobj);
for(auto& sobj : _model3Ds) draw_aspect::draw(sobj);
}
std::vector<Image> _images;
std::vector<Sprite> _sprites;
std::vector<Model3D> _model3Ds;
};
int main()
{
SceneManager sman;
sman.Add(Image());
sman.Add(Sprite());
sman.Add(Model3D());
sman.Add(Image());
draw(sman);
}
Note that the output is different (ordering):
drawing image
drawing image
drawing sprite
drawing model3D
Solving your specific petition is one thing that others have already done.
However, I think you should take a step back and consider the whole picture. Is this a wise step to take? Any possible alternative to virtual functions will introduce maintainability problems, i.e., difficulty to modify and even to understand code.
The question is: is this really necessary? Will it really compensate?
Virtual functions involve derreferencing two pointers instead of only one. And yes, it is true it won't be inlined. I don't think, however, this being a real issue. I would indeed concentrate in algorithm-level optimization, and waste all other approaches before removing virtual funcions.
Take into account that at least one solution involves converting virtual functions to regular functions (not member functions), removing the well-known advantage of a virtual function (i.e., the class of the object itself) vs. a chain of if's.
That's said, it is your call.
Since you seem to have a fixed number types, it seems a reasonable approach would be the use of one vector per type and applying the operations separately for each type: processing a sequence of heterogeneous objects will amount to some disruption whether it is using virtual functions are not. Putting the framework of how the respective objects are called into a function template will conveniently deal with the commonality.
I have a problem designing a class that will allow me to draw objects of various shapes.
Shape is the base class
Triangle, Square, Rectangle are derived classes from Shape class
I have a vector<Shape*> ShapeCollection that stores the derived objects i.e. Triangle,Square, Rectangle
Once I pick the an object from the vector I need to draw the object onto the screen.
At this point I am stuck at what the design of a class should be where as a single 'Drawing' class will do the drawing, consuming an object of 'Shape' class. As the vector will contain different objects of the same base class Shape. As I have a thread that picks up an object from the vector and once I have an object I must be able to draw it properly.
So more or less below is what I say
class Drawing
{
public:
void Draw(Shape* shape, string objectName)
{
// Now draw the object.
// But I need to know which Object I am drawing or use
// switch statements to identify somehow which object I have
// And then draw. I know this is very BAD!!!
// e.g.
switch(objectName)
{
case "rectangle":
DrawRectangle((Rectangle*) shape)
break;
//Rest of cases follow
}
}
}
Where as I will have a DrawSquare, DrawTriangle function which will do the drawing.
This must be something that has been solved. There must be a better way of doing this as
all this switch statement has to go away somehow!
Any guidance is much appreciated.
Thanks
#Adrian and #Jerry suggested to use virtual function, I thought of it, but I need to have my Drawing away from the base class Shape
You would use polymorphism.
Make a pure virtual function in your base class (i.e. when declaring the function assign it to 0 as in void DrawShape() = 0;)
Declare and define that function in your derived classes.
That way you can just call DrawShape() on each of these objects even if it is passed as a Shape object.
Alternatives (NOTE: code has not been tested):
Function pointer, which is like building your own vtable aka delegate.
struct square
{
void (*draw)(square&);
};
void drawSquare(square& obj)
{
// draw square code
// there is no 'this'. must access members via `obj`.
}
square s;
s.draw = drawSquare;
s.draw(s);
Functor, which is a class that overrides operator() and also is like a delegate
struct square
{
// Note that std::function can hold a function pointer as well as a functor.
function<void(square&)> draw;
};
struct drawSquare
{
void oparator()(square& obj)
{
// draw square code
// there is no 'this'. must access members via `obj`.
}
};
square s;
square s.draw = drawSquare();
s.draw(s);
NOTE: 1 and 2 can also be initialised with lambda functions:
square s;
s.draw = [](square& obj) {
// draw square code
// there is no 'this'. must access members via `obj`.
};
s.draw(s);
NOTE: 1 could be done with a template:
struct square;
template <void (*DRAW)(square&)>
struct square
{
void draw()
{
DRAW(*this);
}
};
void drawSquare(square& obj)
{
// draw square code
// there is no 'this'. must access members via `obj`.
}
square s<&drawSquare>;
s.draw();
NOTE: 2 could be done with a template as well:
template <typename DRAW>
struct square
{
void draw()
{
// First set of parentheses instantiate the DRAW object.
// The second calls the functor.
DRAW()(*this);
}
};
struct drawSquare
{
void oparator()(square& obj)
{
// draw square code
// there is no 'this'. must access members via `obj`.
}
};
square s<drawSquare>;
s.draw();
Or alternatively, which would allow the passing of a stateful functor:
template <typename DRAW>
struct square
{
DRAW draw;
};
struct drawSquare
{
void operator()(square& obj)
{
// draw square code
// there is no 'this'. must access members via `obj`.
}
};
square s<drawSquare>;
s.draw = drawSquare();
s.draw(s);
Inherit from another class that implements the function you want either with a templated base class (IIRC, this was done in the ATL). This is just rolling your own hard-coded vtable and is called the Curiously Recurring Type Pattern (CRTP).
template <class D>
struct shape
{
inline void draw() { return static_cast<D&>(*this).draw(); }
};
void draw(square& obj)
{
// draw square code
// No 'this' available. must access shape members via `obj`.
}
struct square : public D<square>
{
void draw()
{
drawSquare(*this);
}
};
Other examples can be found here and here.
Have your draw class inherit from the type of shape class which inherits from the base shape class.
struct shape
{
virtual void draw() = 0;
};
struct square : public shape
{
};
struct drawSquare : public square
{
virtual void draw()
{
// draw square code
// you access the square's public or protected members from here
}
};
Use a std::unordered_map
#include <unordered_map>
#include <typeinfo>
#include <functional>
struct shape { };
struct square : public shape { };
void drawSquare(shape& o)
{
// this will throw an exception if dynamic cast fails, but should
// never fail if called from function void draw(shape& obj).
square& obj = dynamic_cast<square&>(o);
// draw square code
// must access shape members via `obj`.
}
std::unordered_map<size_t, std::function<void(shape&)>> draw_map
{
{ type_id(square).hash(), drawSquare }
};
void draw(shape& obj)
{
// This requires the RTTI (Run-time type information) to be available.
auto it = draw_map.find(type_id(obj).hash());
if (it == draw_map.end())
throw std::exception(); // throw some exception
(*it)(obj);
}
NOTE: if you are using g++ 4.7, be warned unordered_map has been shown to have performance issues.
This is pretty much the classic demonstration of when you want a virtual function. Define a draw in your base class, then override it in each derived class. Then to draw all the objects, you step through the collection and call the draw() member for each.
class shape {
// ...
virtual void draw(canvas &c) = 0;
};
class square : public shape {
int x, y, size;
// ...
virtual void draw(canvas &c) {
c.move_to(x, y);
c.draw_to(x+size, y);
c.draw_to(x+size, y+size);
c.draw_to(x, y+size);
c.draw_to(x, y);
}
};
...and so on for each type of shape you care about.
Edit: using a strategy class, you'd end up with code vaguely along this line:
template <class draw>
class shape {
// ...
virtual void draw(canvas &c) = 0;
};
template <class d>
class square : public shape<d> {
// ...
virtual void draw(canvas &c) {
d.square(x, y, size, c);
}
};
Another possibility would be to use a Visitor pattern. This is typically used when you need/want to traverse a more complex structure instead of a simple linear sequence, but could be used here as well. This is enough more complex that it's probably a bit much to go into here, but if you search for "Visitor pattern", you should turn up a fair amount of material.