Making custom types drawable with SFML - c++

I picked up using SFML recently, and I decided as a learning experience I would make a pong clone using it. I've defined a class called Ball which draws uses SFML to draw a RectangleShape. When I try to draw this custom type to the screen with the window.draw() function however, I get errors because Ball isn't an sf::Drawable. I would appreciate help with this, being new to SFML.

To use window.draw(object) object's class must inherit the drawable interface and implement the abstract sf::Drawable::draw function.
It sounds like the sf::RectangleShape is a member of Ball. SFML knows how to render the shape, but not Ball itself. Ball's class declaration should look like this:
class Ball : public sf::Drawable //,...
{
//...
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
//...
};
And draw should be implemented like this:
void Ball::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
//assuming m_shape is the sf::RectangleShape
target.draw(m_shape, states);
}

Related

Aesthetically correct code for storing/displaying basic shapes

I'm using ES 3.0 (basically GL 3.3 without geometry shaders) to be able to port my programs to almost everything
My helpful framework/wrapper written on C++. Basically its everything what can be found inside of quick reference card: Buffer/Shader/ShaderProgram/Framebuffer/Texture/etc. (pretty basic stuff, I do believe everyone have classes like that)
I noticed that when I need to draw a basic shapes such as full-screen quad, triangles, spheres I always doing it in-place, its not a part of my framework. And I kinda hate it, because I'm repeating myself again and again. It is really unpleasant thing to do
How aesthetically and technically right I can add such a functionality to my framework?
(in advance: for platforms like android context loss is possible, so pause/restore mechanism required)
SFML has similar functionality. Here's its structural frame:
class Drawable {
friend class RenderTarget;
protected: // hidden from everyone but subclasses and RenderTarget
virtual void draw(RenderTarget&) const = 0;
};
class RenderTarget {
public:
void draw(Drawable& drawable) {
drawable.draw(*this);
}
};
class RectangleShape : public Drawable {
protected:
void draw(RenderTarget&) const override {
// the algorithm
}
};
void use() {
RectangleShape shape;
RenderTarget& target = get();
target.draw(shape);
}
(Actually it's more complicated: I omitted virtual destructors, unnecessary inheritance levels etc.)

I cant acces functions of a base class

Currently, I am learning c++ and just for fun, I wanted to code a little chess game (without an AI of course). I use visual studio community aside and SFML 2.5 as a renderer and for graphical objects. I tried to make a model called "figure" for all figures. So I have a figure class that inherits from sfml sprite (a drawable) and a pawn class f.e. that inherits from the figure. Sf:: sprite -> figure-> pawn/queen/tower etc... but for some reason, I can't use the pawn as a sprite, for example, I can't draw it with the draw function of my windowRenderer.
But the function documentation says it requires a drawable object. I get an error message that says something like: the conversation in the base class that is not accessible is not valid. Have I done something wrong or is it not possible to use a sprite like this. Here are my constructors because I think I its most likely I made an error there. I have only coded in java so far so the separation into header and implementation file is a little foreign for me also the constructor syntax is different.
figure.h:
class figure : sf::Sprite {
public:
figure(int startPosition);
void changeImage(std::string);
void dissapear();
void loadImage(std::string);
private:
sf::Image img;
};
figure.cpp:
figure::figure(int startPosition):sf::Sprite(){
}
pawn.h:
class pawn :
public figure
{
public:
pawn(int startPosition);
~pawn();
private:
void move(bool canBeat, bool isAsStart);
};
pawn.cpp:
pawn::pawn(int startPosition):figure (startPosition)
{
}
in main.cpp:
pawn pawn1(position);
sf::RenderWindow window(sf::VideoMode(sets.windowX, sets.windowY), "frame");
window.draw(pawn1);
Try this
class figure : public sf::Sprite
Inheritence for classes is private by default.

How should I pass an object to a class to check for collisions?

I'm making a Breakout game in C++ using the SFML library, I have a "paddle" class as well as a "ball" class, both being updated and rendered in a "game" class, which uses a render window from a "window" class.
My issue is that in order to determine whether the Ball object has collided with the Paddle object, I obviously need access to the Paddle object's x/y position data members. I'm using an update (or tick) function for each object, I'd rather not just pass a reference to the Paddle object into the Ball's update function.
What is the general accepted way to do achieve my desired functionality?
Here is my Ball header:
class Ball
{
public:
Ball(float x, float y, int size, sf::Vector2f moveSpeed);
~Ball();
void Tick();
void Move();
void Render(sf::RenderWindow& window);
void Reset();
sf::Vector2f GetMoveSpeed() { return m_moveSpeed; }
private:
void CheckCollision();
int m_size;
sf::Vector2f m_moveSpeed;
sf::Vector2f m_position;
sf::CircleShape m_ballCircle;
};
Here is my Game update function:
void Game::Update()
{
m_window.Update();
m_ball.Tick();
m_paddle.Tick();
}
Use separate object which implements algorithm for updating ball. This object knows about all your data: ball and paddle, and calculates new position.
You can inject algorithm into your game class, which would hold pointer to interface. This allows you to change algorithm without changing Game, Ball or Paddle classes.
Let your Game check collision and handle them appropriately:
void Game::Update()
{
m_window.Update();
m_ball.Tick();
m_paddle.Tick();
if(areColliding(m_ball, m_paddle))
{
resolveCollision(m_ball, m_paddle);
}
}
In this case, areColliding and resolveCollision could be private member functions of Game.

Variable not passing trough (maybe end of scope)

So I am trying to assign a variable trough a function. The code in the function would normally exist in the constructor but because I dont want to have to write it in the constructor for all the classes that inherite the same parent I made a function.
But the function doesnt seem to work properly or assign the vallue properly.
This is the code in the constructor:
sf::Texture holdTexture;
sf::Sprite holdSprite;
Wolf::Wolf(float speed, Player& p) :
Monster(speed, p)
{
holdTexture.loadFromFile("Assets\\Wolf.png");
sprite.setTexture(holdTexture);
sprite.setOrigin(24,22);
}
The sprite value is declared in a parent-parent-parent called Entity.h
class Entity {
public:
Entity();
sf::Sprite sprite;
public:
sf::Vector2f getEntityCoords();
protected:
void loadSprite(const std::string &filename);
};
Which has the function:
void Entity::loadSprite(const std::string &filename) {
sf::Texture holdTexture;
holdTexture.loadFromFile(filename);
sprite.setTexture(holdTexture);
}
So now my constructor looks like:
Wolf::Wolf(float speed, Player& p) :
Monster(speed, p)
{
loadSprite("Assets\\Wolf.png");
}
Wolf is derived from Monster. Monster is derived from Entity. And the call to loadSprite works.
But now the sprite just turns into a white box. As the title says, it may be an end of scope issue but I am not experienced enough with c++ to know for sure. Looking around hasnt gotten me an answer too. I hope this is not a stupid question. If you need to see more code please ask, it would be great if someone could help :)
As long as the sprite lives the sprite needs an existing texture to be present. As soon as the method ends the sf::Texture holdtexturewould be cleared from the memory and because of that it would display an white square.
I fixed it by adding an sf::Texture to the Entity class and assigning that texture to the sprite.

How to edit SFML source code to add a new Drawable Object?

Hey i'm working on a class called a "Body" which holds shapes and sprites together as one object. I would like to get into the source code and add a new overload RenderWindow's Draw() function, so this new object can be taken in and drawn easily. How do i do this?
I'm currently using
Windows 7
SFML 1.6
Newly msVS++ 2010 compiled static debug libraries and dlls
original include folder
EDIT:
I also found this in the Drawable.hpp header:
private :
friend class RenderTarget;
////////////////////////////////////////////////////////////
/// Draw the object into the specified window
///
/// \param Target : Target into which render the object
///
////////////////////////////////////////////////////////////
void Draw(RenderTarget& Target) const;
////////////////////////////////////////////////////////////
/// Render the specific geometry of the object
///
/// \param Target : Target into which render the object
///
////////////////////////////////////////////////////////////
virtual void Render(RenderTarget& Target) const = 0;
but i can't figure out where the full code of each function is, just the declarations.
I didn't find a mini tutorial there either unfortunately...
Note:
Before you derive from and implemented your own Drawable, you may want to consider if you need to do it at all. The author of SFML has stated that sf::Drawable was not initially meant to be subclassed outside of SFML.
That aside,
For SFML 1.6:
It appears that all you need to do is derive your class from sf::Drawable, and then implement a virtual Render function.
class MyDrawable : public sf::Drawable {
private:
virtual void Render(RenderTarget& target) const {
// Do some rendering of whatever...
target.Draw(mySubSprite);
}
sf::Sprite mySubSprite;
};
An example of this can be found on the SFML forums.
For SFML 2.0:
The Drawable header file from SFML contains comments that describe how to derive your own Drawable classes. You do not need to modify the SFML source code to create new Drawables.
It also includes a simple example:
class MyDrawable : public sf::Drawable
{
public :
...
private :
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
// You can draw other high-level objects
target.draw(m_sprite, states);
// ... or use the low-level API
states.texture = &m_texture;
target.draw(m_vertices, states);
// ... or draw with OpenGL directly
glBegin(GL_QUADS);
...
glEnd();
}
sf::Sprite m_sprite;
sf::Texture m_texture;
sf::VertexArray m_vertices;
};
This example may apply to SFML 2.0, but if you inspect the Drawable.hpp from whatever version of SFML you have it should contain a similar example.
RenderWindow::Draw takes an object of the abstract class type Drawable. Which means that, in theory, you can just make your Body class a child of Drawable and overload some virtual methods to make it render.
But that doesn't seem to be the case. The docs for Drawable show that there's only one virtual function in that class: the destructor. Which is... kinda stupid.
However, looks can be deceiving. I was checking the 2.0 documentation to see if they had figured out how to make an inheritance hierarchy correctly, and it turns out that they do have virtual methods to override. It's just that they're all private (which itself is fine, and in fact a very good thing), and the SFML guys didn't tell Doxygen to generate documentation for private members. I filed a bug with them on this.
Until they update their docs, the only thing I can say is to look at the header, and maybe the source code to Sprite, and try to figure out how to create a derived Drawable class correctly.