SFML community forums
Help => Graphics => Topic started by: xarxer on July 16, 2010, 01:19:32 pm
-
This code, where shape is an sf::Shape, sets the position of shape to 200, 200. But it's still rotating around 12, 12..
// Generates a triangle
shape.AddPoint(12.f, 0.f, color, color);
shape.AddPoint(0.f, 24.f, color, color);
shape.AddPoint(24.f, 24.f, color, color);
shape.EnableFill(false);
shape.EnableOutline(true);
shape.SetOutlineWidth(2.f);
shape.SetCenter(12.f, 12.f);
shape.Move(200.f, 200.f);
Is this a bug or am I missing something?
Thanks / xarxer :)
-
It works for me, the triangle rotates around its center.
Can you provide a complete source code?
Which version of SFML do you use?
-
Obviously something is wrong in my more complex source code since this example works well.
#include <SFML/Graphics.hpp>
using namespace std;
int main(int argc, char** argv)
{
sf::RenderWindow App;
sf::VideoMode VidMode;
sf::Event Event;
VidMode = sf::VideoMode::GetDesktopMode();
VidMode.Width = 1024;
VidMode.Height = 768;
sf::Color color = sf::Color::Blue;
App.Create(VidMode, "Test shape", sf::Style::Close);
sf::Shape triangle;
triangle.AddPoint(12.f, 0.f, color, color);
triangle.AddPoint(0.f, 24.f, color, color);
triangle.AddPoint(24.f, 24.f, color, color);
triangle.EnableFill(false);
triangle.EnableOutline(true);
triangle.SetOutlineWidth(2.f);
triangle.SetCenter(12.f, 12.f);
triangle.Move(200.f, 200.f);
while(App.IsOpened())
{
while(App.GetEvent(Event))
{
if(Event.Type == sf::Event::Closed)
App.Close();
}
if(App.GetInput().IsKeyDown(sf::Key::Left))
triangle.Rotate(180.f*App.GetFrameTime());
if(App.GetInput().IsKeyDown(sf::Key::Right))
triangle.Rotate(-180.f*App.GetFrameTime());
triangle.Move(20.f*App.GetFrameTime(), 20.f*App.GetFrameTime());
App.Clear();
App.Draw(triangle);
App.Display();
}
return 0;
}
In my source code I have a class called CPlayer which inherits from sf::Drawable. It is structured like this:
class CPlayer : public sf::Drawable
{
public:
CPlayer(sf::Color color);
private:
// Irrelevant variables and functions removed
sf::Shape shape;
virtual void Render(sf::RenderTarget& Target) const;
};
CPlayer::CPlayer(sf::Color color)
{
///Triangle
shape.AddPoint(12.f, 0.f, color, color);
shape.AddPoint(0.f, 24.f, color, color);
shape.AddPoint(24.f, 24.f, color, color);
shape.EnableFill(false);
shape.EnableOutline(true);
shape.SetOutlineWidth(2.f);
///Set center to center of shape
shape.SetCenter(12.f, 12.f);
///Move the shape to a more centerified position
shape.Move(200.f, 200.f);
}
void CPlayer::Render(sf::RenderTarget& Target) const
{
Target.Draw(shape);
}
In CGame, players are added to a vector by using
players.push_back(new CPlayer(sf::Color::Blue));
and the game-constructor looks like this:
CGame::CGame(sf::RenderWindow& _App) : App(_App), input(App.GetInput())
{
this->add_player(sf::Color::Blue);
}
void CGame::add_player(sf::Color col)
{
players.push_back(new CPlayer(col));
}
and here's the game-loop
int CGame::Run()
{
while(App.IsOpened())
{
while(App.GetEvent(event))
{
if(event.Type == sf::Event::Closed)
App.Close();
}
if(input.IsKeyDown(sf::Key::Left))
players[0]->Rotate(180.f*App.GetFrameTime());
if(input.IsKeyDown(sf::Key::Right))
players[0]->Rotate(-180.f*App.GetFrameTime());
///Testing some movement
players[0]->Move(20.f*App.GetFrameTime(), 20.f*App.GetFrameTime());
///Drawing
App.Clear();
for(unsigned int i=0 ; i<players.size() ; i++)
App.Draw(*players[i]);
App.Display();
}
return -1;
}
With this code, the triangle is spawned in the top left corner, its center is set to the center of the triangle, then it's moved away to 200, 200.
When pressing left- or right-key it's rotating around 12, 12.
Observe though that my shape is moving by 20 pixels per second diagonally, and so is the spot of rotation.
I'm sorry if the source code is a bit messy! :oops:
-
I have narrowed down the problem to the CPlayer constructor:
CPlayer::CPlayer(sf::Color color)
{
///Triangle
shape.AddPoint(12.f, 0.f, color, color);
shape.AddPoint(0.f, 24.f, color, color);
shape.AddPoint(24.f, 24.f, color, color);
shape.EnableFill(false);
shape.EnableOutline(true);
shape.SetOutlineWidth(2.f);
///Set center to center of shape
shape.SetCenter(12.f, 12.f);
///Move the shape to a more centerified position
shape.Move(200.f, 200.f);
}
Because if I comment out the last line and do the repositioning in CGame::add_player(sf::Color col)
like this
void CGame::add_player(sf::Color col)
{
players.push_back(new CPlayer(col));
players.back()->SetPosition(200.f, 200.f);
}
it works like a charm..
Question now is, why can't I position it in the CPlayer constructor?
-
You badly mix the player and its shape:
- in your code you rotate the player, not the shape. Thus the rotation is centered around the player's center, not the shape's one.
- your first code is different from the second one because you move the shape in the former, and the player in the latter
You should really take a moment to think about what happens in your code, and how the player and its shape move/rotate ;)
-
oh.. yeah I see what you mean now.
I should use this->SetPosition(); in the CPlayer constructor :)
Thanks a bunch :)
-
Okay now I've run into another problem..
As posted before this is my CPlayer class
class CPlayer : public sf::Drawable
{
public:
CPlayer(sf::Color color);
private:
// Irrelevant variables and functions removed
sf::Shape shape;
virtual void Render(sf::RenderTarget& Target) const;
};
CPlayer::CPlayer(sf::Color color)
{
///Irrelevant code removed
shape.AddPoint(0.f, 0.f, color, color);
shape.AddPoint(0.f, 24.f, color, color);
shape.AddPoint(32.f, 12.f, color, color);
shape.EnableFill(false);
shape.EnableOutline(true);
shape.SetOutlineWidth(1.f);
shape.SetCenter(16.f, 12.f);
}
and to add a player I use
void CGame::add_player(sf::Color col, sf::Vector2f pos)
{
players.push_back(new CPlayer(col));
players.back()->SetPosition(pos);
players.back()->SetRotation(90.f);
}
and to move players I use
for(unsigned int i=0 ; i<players.size() ; i++)
players[i]->Move(players[i]->x_vel, players[i]->y_vel);
So when I create a player, it is "born" in the upper left corner, then it's rotated and moved to the center of the screen (declared as variable pos in this example).
But it seems that the sf::Shape shape itself is still in the upper left corner, because
shape.GetPointPosition(0);
returns a vector containing 0,0 even though I have moved the CPlayer instance.
No matter where on the screen the instance is, it always return 0,0..
Explanation? :(
-
These are local coordinates, independant from the transformations that you apply to the shape. You then have to use TransformFromLocal to get the corresponding global position on screen (maybe twice in your case, because you have two levels of transformations -- the player and the shape).