Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Possible sf::Shape positioning bug  (Read 3517 times)

0 Members and 1 Guest are viewing this topic.

xarxer

  • Newbie
  • *
  • Posts: 35
    • View Profile
Possible sf::Shape positioning bug
« 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..

Code: [Select]
   
       // 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  :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Possible sf::Shape positioning bug
« Reply #1 on: July 16, 2010, 01:49:50 pm »
It works for me, the triangle rotates around its center.

Can you provide a complete source code?

Which version of SFML do you use?
Laurent Gomila - SFML developer

xarxer

  • Newbie
  • *
  • Posts: 35
    • View Profile
Possible sf::Shape positioning bug
« Reply #2 on: July 16, 2010, 02:18:45 pm »
Obviously something is wrong in my more complex source code since this example works well.

Code: [Select]

#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:

Code: [Select]


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

Code: [Select]

       players.push_back(new CPlayer(sf::Color::Blue));


and the game-constructor looks like this:


Code: [Select]


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

Code: [Select]

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:

xarxer

  • Newbie
  • *
  • Posts: 35
    • View Profile
Possible sf::Shape positioning bug
« Reply #3 on: July 16, 2010, 02:28:30 pm »
I have narrowed down the problem to the CPlayer constructor:

Code: [Select]

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

Code: [Select]

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?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Possible sf::Shape positioning bug
« Reply #4 on: July 16, 2010, 02:44:21 pm »
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 ;)
Laurent Gomila - SFML developer

xarxer

  • Newbie
  • *
  • Posts: 35
    • View Profile
Possible sf::Shape positioning bug
« Reply #5 on: July 16, 2010, 05:30:08 pm »
oh.. yeah I see what you mean now.

I should use this->SetPosition(); in the CPlayer constructor :)

Thanks a bunch :)

xarxer

  • Newbie
  • *
  • Posts: 35
    • View Profile
Possible sf::Shape positioning bug
« Reply #6 on: July 17, 2010, 05:02:53 pm »
Okay now I've run into another problem..

As posted before this is my CPlayer class

Code: [Select]

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

Code: [Select]

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

Code: [Select]

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

Code: [Select]

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?  :(

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Possible sf::Shape positioning bug
« Reply #7 on: July 18, 2010, 04:40:16 pm »
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).
Laurent Gomila - SFML developer