I'm working on a grid to speed up collision detection, and the way I have this set up is that a GridSquare class holds a std::vector of all the objects that are within that specific grid square (determined by using a sf::FloatRect::intersects()). Here is what I mean by this class: class GridSquare{
public:
GridSquare(float x, float y, float px, float py); //position.x, position.y, width, height,
~GridSquare();
sf::RectangleShape &GetVisual();
sf::FloatRect &GetGridSquare();
void AddStationaryObject(sf::Transformable &object);
void AddMovableObject(sf::Transformable &object);
std::vector<sf::Transformable> &GetStationaryObjects();
std::vector<sf::Transformable> &GetMovableObjects();
std::vector<sf::Transformable> &GetGridObjects();
private:
//so in the gameloop I'll check for what objects intersect this float rect, and...
sf::FloatRect gridSquare;
//...add these objects to the respective vectors below
//stationary objects hold walls and such, movable objects would be player and projectiles
std::vector<sf::Transformable> stationaryObjects_, movableObjects_, gridObjects_;
};
The issue is that sf::RenderWindow::draw() does not take a sf::Transformable as a parameter, so when I declare the vectors above as "std::vector<sf::Transformable>" and try to loop through the vector and draw the objects, this compiler error is thrown:
IntelliSense: no instance of overloaded function "sf::RenderWindow::draw" matches the argument list
argument types are: (sf::Transformable)
object type is: sf::RenderWindow c:\Users\jordan\Documents\Visual Studio 2012\Projects\SFML Test\SFML Test\SFML Test.cpp 20
Here is a small code example to see for yourself:int _tmain(int argc, _TCHAR* argv[]){
sf::RenderWindow window;
window.create(sf::VideoMode(500, 500, 32), "Test");
//a vector of sf::Transformable, can't be drawn on screen because a transformable isn't a drawable
std::vector<sf::Transformable> objectsToDraw;
objectsToDraw.push_back(sf::RectangleShape(sf::Vector2f(20, 20)));
while(window.isOpen()){
//just calling the draw function here, no need to worry about updating because nothing is being updated
window.clear();
window.draw(objectsToDraw[0]); //throws an error that draw() doesn't take an argument of sf::Transformable
window.display();
}
return 0;
}
So, the ideal fix would be to declare those std::vectors as std::vector<sf::Drawable>, that way their objects can be drawn, right? Well, that throws a different error:
Error 2 error C2259: 'sf::Drawable' : cannot instantiate abstract class c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0 617
Again, a small code example:#include "stdafx.h"
#include "SFML\Graphics.hpp"
int _tmain(int argc, _TCHAR* argv[]){
sf::RenderWindow window;
window.create(sf::VideoMode(500, 500, 32), "Test");
//a vector of sf::Drawable, throws an error that the abstract class can't be instantiated
std::vector<sf::Drawable> objectsToDraw;
objectsToDraw.push_back(sf::RectangleShape(sf::Vector2f(20, 20)));
while(window.isOpen()){
//just calling the draw function here, no need to worry about updating because nothing is being updated
window.clear();
//window.draw(objectsToDraw[0]); //the error isn't thrown here, but above when the vector is declared
window.display();
}
return 0;
}
I don't understand this error. I just want a std::vector that will hold all types of sfml drawable objects, which I can then iterate through and draw all the objects on screen. Any suggestions?
This quite basic C++ knowledge. sf::Drawable is abstract (Meaning it cannot be directly instanciated, only inherited from), therefore you cannot have a container of it (Or a class/struct member etc). You can however, have a pointer (Smart or raw) to sf::Drawable and it will work.
This will not solve your problem however. sf::Transformable has positional data which I'm guessing you need for the position of your grid cells, but how are you supposed to draw a position (Not to mention sf::Window::draw takes an sf::Drawable not sf::Transforamble)?
My advice is to make your own class inherited from both sf::Transformable and sf::Drawable, that way you can draw the instances AND transform them.
As for looping, there are a few ways of doing them:
Pre C++11:
std::vector<MyDrawableTransformable> x;
...
std::vector<MyDrawableTransformable>::iterator it;
for (it = x.begin(); it != x.end(); ++it)
window.draw(**it);
C++11/14
std::vector<MyDrawableTransformable> x;
...
for (auto obj : x)
window.draw(obj);
I didnt test the code (Plus its pseudo code anyway) so theres probably something I missed but thats the idea.
Thanks for the replies, but I know how to do the actual for loop, the title may have been a bit misleading. As for creating my own class inhertied from sf::Transformable and sf::Drawable, that is new to me. I know I would declare the class like so: class MyDrawableTransformable : sf::Transformable, sf::Drawable{
//...
};
But the question is how would that change how I declare my std::vectors? When Gambit typed std::vector<MyDrawableTransformable> x;
...
for (auto obj : x)
window.draw(obj);
I assume that means that I would be looping through a vector of class objects and drawing the sf::Drawables owned by those class objects instead of directly looping through sfml objects?
So let's compare that to my GridSquare class that I gave earlier: class GridSquare{
//...
//stationary objects hold walls and such, movable objects would be player and projectiles
//have each GridSquare object own a vector of class objects, and all my objects I want to draw, such as walls, projectiles, etc, inherit from MyDrawableTransformable?
std::vector<sf::MyDrawableTransformable> stationaryObjects_, movableObjects_, gridObjects_;
};
So does MyDrawbleTransformable hold all of my world objects, or do all the objects I want to draw inherit from MyDrawableTransformable?
Edit: a little bit of research and that was answered, all my object classes need to inherit from MyDrawableTransformable. The question I have now is what does the class MyDrawableTransformable need to look like?
Okay, so I'm undertsnading that the code would look something like this: #include "SFML\Graphics.hpp"
class MyDrawableTransformable : sf::Drawable, sf::Transformable{
public:
MyDrawableTransformable() {};
~MyDrawableTransformable() {};
};
class Player : MyDrawableTransformable {
//...
sf::CircleShape circle;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform(); /*error: getTransform() is inaccessible*/
target.draw(circle, states);
}
}
//I leave out class GridSquare because it doesn't have to be drawn, it is just a bunch of
//sf::FloatRects making up the grid. Instead, class GridSquare would hold a vector of objects that
//inherit from MyDrawableTransformable and are inside its sf:FloatRect
But like the comment says, getTransform() is inaccessible. Am I implementing draw() incorrectly?
I know I would declare the class like so: class MyDrawableTransformable : sf::Transformable, sf::Drawable{
//...
};
You also need the public keyword for each base as shown here in this tutorial (http://www.sfml-dev.org/tutorials/2.2/graphics-vertex-array.php#creating-an-sfml-like-entity).
In that tutorial, it also shows examples of how to implement the draw method.