SFML sprite rotation

Pages: 12
how do i indicate when user presses left arrow key for line 42 so it doesnt keep rotating 270 degrees, but only the ifrst time?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <SFML/Graphics.hpp>


int main()
{
    // Create the main rendering window
    sf::RenderWindow App(sf::VideoMode(800, 600, 32), "ship");

    // Load the sprite image from a file
    sf::Image Image;
    if (!Image.LoadFromFile("topdown.jpeg"))
        return EXIT_FAILURE;

    // Create the sprite
    sf::Sprite Sprite(Image);

    // Change its properties
    Sprite.SetColor(sf::Color(0, 255, 255, 128));
    Sprite.SetPosition(200.f, 100.f);
    Sprite.SetScale(0.f, 0.f);
    Sprite.Rotate(180.f);


    // Start game loop
    while (App.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }

        // Get elapsed time
        float ElapsedTime = App.GetFrameTime();

        // Move the sprite
        if (App.GetInput().IsKeyDown(sf::Key::Left))
        {
            if(Sprite.Rotate == 270.f)
            Sprite.Rotate(270.f);
            Sprite.Move(-200 * ElapsedTime, 0);
        }
        if (App.GetInput().IsKeyDown(sf::Key::Right)) Sprite.Move( 200 * ElapsedTime, 0);
        if (App.GetInput().IsKeyDown(sf::Key::Up))    Sprite.Move(0, -200 * ElapsedTime);
        if (App.GetInput().IsKeyDown(sf::Key::Down))  Sprite.Move(0,  200 * ElapsedTime);

        // Rotate the sprite
        if (App.GetInput().IsKeyDown(sf::Key::Add))      Sprite.Rotate(- 200 * ElapsedTime);
        if (App.GetInput().IsKeyDown(sf::Key::Subtract)) Sprite.Rotate(+ 200 * ElapsedTime);

        // Clear screen
        App.Clear();

        // Display sprite in our window
        App.Draw(Sprite);

        // Display window contents on screen
        App.Display();
    }

    return EXIT_SUCCESS;
}
Last edited on
IsKeyDown gives you the real-time status of the key. It will return true as long as the key is held down.

If you want to do something only when the key is pressed, then you have two options:

1) Catch the keypress event and do it there (keypress events occur only once when the key is pressed):

1
2
3
4
5
6
7
8
9
10
// in your event loop
if(Event.type == sf::Event::KeyPressed)
{
  switch(Event.Key.Code)
  {
  case sf::Key::Left:
    // rotate here
    break;
  }
}


or
2) Keep using the realtime IsKeyDown state, but keep track of when it transitions from released to pressed:

1
2
3
4
5
6
7
8
9
// at a higher scope
bool leftkeydown = false;

// when you want to rotate
if(!leftkeydown && App.GetInput().IsKeyDown(sf::Key::Left))
{
  // rotate here
}
leftkeydown = App.GetInput().IsKeyDown(sf::Key::Left);




Also I noticed you're using 1.6 still (App.GetInput instead of sf::Keyboard). I really recommend using 2.0 instead.
i am still using 1.6, but still having trouble updating it to 2.0 on linux. Also, im still copy and pasting SFML example codes and playing around with them to see what happens, so even if i had 2.0 , i wouldnt know what in the example codes are using the 1.6 "terminology" "classes" (not sure what you'd call it)

what is the difference in SFML and Orge???
what is the difference in SFML and Orge???


SFML is a library for 2D graphics, input, audio, and networking.

Ogre is a library for 3D graphics.
why would anyone want to use SFML if technically Orge is better than???

Should i start and use SFML first before continuing on to Orge?

What other ADI are like Orge?
Last edited on
why would anyone want to use SFML if technically Orge is better than???


Who said one was better than the other?

They both do different things.

Should i start and use SFML first before continuing on to Orge?


Depends on what you want to do. If you want to do 2D stuff, you probably will want to use SFML. If you want to do 3D stuff, you probably will want to use Ogre.

What other ADI are like Orge?


I don't know of very many 3D APIs other than the low level ones (OpenGL, DirectX). AFAIK, Ogre is a wrapper that sits atop them, much like how SFML is a wrapper around OpenGL.
i still cannot figure out why this is not working?? im just trying to have the image turn in the direction that you move once and keep the object keep moving , but not keep turning?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <SFML/Graphics.hpp>


int main()
{
    // Create the main rendering window
    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "ship");

    // Load the sprite image from a file
    sf::Image Image;
    if (!Image.LoadFromFile("ship.png"))
        return EXIT_FAILURE;

    // Create the sprite
    sf::Sprite ship(Image);

    // Change its properties
    ship.SetColor(sf::Color(0, 255, 255, 128));
    ship.SetPosition(200.f, 100.f);
    ship.SetScale(0.f, 0.f);
    ship.Rotate(180.f);


    // Start game loop
    while (window.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (window.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                window.Close();

            if(Event.Type == sf::Event::KeyPressed)
            {
                switch(Event.Key.Code)
                {
                case sf::Key::A:
                    ship.Rotate(270.f);
                    break;
                }
            }

            if(Event.Type == sf::Event::KeyPressed)
            {
                switch(Event.Key.Code)
                {
                case sf::Key::W:
                    ship.Rotate(0.f);
                    break;
                }
            }

            if(Event.Type == sf::Event::KeyPressed)
            {
                switch(Event.Key.Code)
                {
                case sf::Key::D:
                    ship.Rotate(90.f);
                    break;
                }
            }

            if(Event.Type == sf::Event::KeyPressed)
            {
                switch(Event.Key.Code)
                {
                case sf::Key::S:
                    ship.Rotate(180.f);
                    break;
                }
            }
        }

        // Get elapsed time
        float ElapsedTime = window.GetFrameTime();

        // Move the sprite
        if (window.GetInput().IsKeyDown(sf::Key::A))
        {

            ship.Move(-200 * ElapsedTime, 0);
        }



        if (window.GetInput().IsKeyDown(sf::Key::D))  ship.Move( 200 * ElapsedTime, 0);
        if (window.GetInput().IsKeyDown(sf::Key::W))  ship.Move(0, -200 * ElapsedTime);
        if (window.GetInput().IsKeyDown(sf::Key::S))  ship.Move(0,  200 * ElapsedTime);

        // Rotate the sprite
        if (window.GetInput().IsKeyDown(sf::Key::Add))      ship.Rotate(- 200 * ElapsedTime);
        if (window.GetInput().IsKeyDown(sf::Key::Subtract)) ship.Rotate(+ 200 * ElapsedTime);

        // Clear screen
        window.Clear();

        // Display sprite in our window
        window.Draw(ship);

        // Display window contents on screen
        window.Display();
    }

    return EXIT_SUCCESS;
}
Last edited on
Holy copypasta. Lines 35-75 could be shrink down to about 6 lines. No need to check the event once for each button, just put all of those in the same if() block and put every key in the same switch statement. A general rule of thumb is that if you are copy/pasting your code and making minor modifications to it each time, you're probably doing something wrong.

Although that is just a cleanliness thing. It isn't the source of your problem.

It looks like you have W,A,S,D buttons doing 2 things. You have all of them rotating the sprite when pressed (although 'W' rotates by zero, which is pointless), and you have all of them moving the sprite when held.

I assume you want A and D to rotate, and W and S to move forward/backward, right? In that event, get rid of the W,S rotation stuff, and get rid of the A,D movement stuff.
this works , but W will never go any other direction than up, how would i implement W as the forward movement???

is there a way to set up a permanent graph, so i could say if ship is already 90.f, W will go X direction, if ship is already 270.f, W will go X direction, etc.???
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <SFML/Graphics.hpp>


int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test");

    sf::Image Image;
    if (!Image.LoadFromFile("ship.png"))
        return EXIT_FAILURE;

    sf::Sprite ship(Image);

    ship.SetColor(sf::Color(50, 50, 50, 255));
    ship.SetPosition(200.f, 100.f);
    ship.SetScale(0.f,0.f);
    ship.Rotate(0.f);


    // Start game loop
    while (window.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (window.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                window.Close();

            if(Event.Type == sf::Event::KeyPressed)
            {
                    switch(Event.Key.Code)
                    {
                    case sf::Key::A:
                        ship.Rotate(270.f);
                        break;
                    case sf::Key::W:
                        ship.Move(0,-5);
                        break;
                    case sf::Key::D:
                        ship.Rotate(90.f);
                        break;
                    case sf::Key::S:
                        ship.Move(0,5);
                        break;
                    }
            }
        }
        window.Clear(sf::Color::White);

        window.Draw(ship);

        window.Display();
    }

    return EXIT_SUCCESS;
}


i cant think of how to code it, but my original thought is
user holds D, if ship is already facing (right) 90 degrees , ship moves right, or else ship rotates to 90 degrees....and the same with the rest of WASD

initially i tried
1
2
3
4
5
6
                    case sf::Key::A:
                        if(ship.Rotate(270.f))
                            ship.Move(-5, 0);
                        else
                            ship.Rotate(270.f);
                        break;

but error says couldnt convert to bool, but something along those lines is what im trying to do
Last edited on
I see. So you want the controls to be sort of like pokemon or old zelda games. Where the button you press is the direction you go in and you face that direction.
yes, zelda was what i was thinking about
Last edited on
Okay. So I'm guessing .Rotate(float) changes the rotation of the sprite that amount each time it is run. setRotation() is what you want.
use setRotation and get rid of rotation?
It's worth a shot. You will also need setRotation calls for 'W' and 'S' as well as Move calls for 'A' and 'D'.
this appears to be working
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <SFML/Graphics.hpp>


int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test");

    sf::Image Image;
    if (!Image.LoadFromFile("ship.png"))
        return EXIT_FAILURE;

    sf::Sprite ship(Image);
    ship.SetColor(sf::Color(50, 50, 50, 255));
    ship.SetPosition(200.f, 100.f);
    ship.SetScale(0.f,0.f);
    ship.Rotate(0.f);


    // Start game loop
    while (window.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (window.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                window.Close();

            if(Event.Type == sf::Event::KeyPressed)
            {
                    switch(Event.Key.Code)
                    {
                    case sf::Key::A:
                        ship.SetRotation(270.f);
                        ship.Move(-5, 0);
                        break;
                    case sf::Key::W:
                        ship.SetRotation(180.f);
                        ship.Move(0,-5);
                        break;
                    case sf::Key::D:
                        ship.SetRotation(90.f);
                        ship.Move(5, 0);
                        break;
                    case sf::Key::S:
                        ship.SetRotation(0.f);
                        ship.Move(0,5);
                        break;
                    }
            }
        }
        window.Clear(sf::Color::White);

        window.Draw(ship);

        window.Display();
    }

    return EXIT_SUCCESS;
}
it does appear to be working , but ihave a question on its axis? how would you center it on the image? currently its rotating on a specific corner, so if i was to go from right to left it jumps down and to the left. I would be hoping to be able to center it so it looks like it is turning around instead of glitching?

i could use GIMP to crop the pic down but it would still jump a little...any ideas?
Last edited on
A little research SFML has a setCenter (or setOrigin in later versions). This sets the origin of all transformations. So you would call ship.setOrigin( half_ships_Width, half_ships_Height ).
im still using 1.6 (in linux) and having trouble figuring out how to update to 2.0

i read through one of their forums asking the same thing, but it doesnt make sense to me how they are doing it
http://www.sfml-dev.org/forum/viewtopic.php?t=5699

how would you get the height and width of an image?
Does sfml have a sprite.getSize() maybe?
Pages: 12