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

Author Topic: [SOLVED] Controlling sprite movement speed?  (Read 19212 times)

0 Members and 1 Guest are viewing this topic.

nvangogh

  • Newbie
  • *
  • Posts: 21
    • View Profile
[SOLVED] Controlling sprite movement speed?
« on: May 10, 2013, 06:21:36 pm »
I am having problems learning to move a missile up the y axis.
Now to move a sprite representing a space ship I used this:
int keycode(0);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
          keycode = 1;
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
          keycode = 2; 

        switch(keycode)
          {
          case 1:// move left
            {
            position = ship.getPosition();
            if(position.x <= 0.0)
              ship.setPosition(0.0,500);
            else
              ship.move(-0.130 * elapsed.asMilliseconds(),0);
            break;
            }
          case 2: // move right
          {
            position = ship.getPosition();
            if(position.x >= 700.0)
              ship.setPosition(800-shipsize.width,500);
            else
            ship.move(0.130 * elapsed.asMilliseconds(),0);
            break;
          }
         
          }
 
By trial & error I got it moving at the type of speed I wanted. The trouble is that I now want to give my ship a function to fire a missile. So say the window i use is 800x600 and the ship moves along the x axis only, but is set at position 500 on the y axis. - The y axis position of my ship does not change. A missile will always start at position 500 on the y axis and go up towards the top of the window. (Note that the xy axis in sfml is flipped so 0,0 is the top left corner of window.)

I have been trying to build a test program that moves a missile up the y axis once the left-shift button is pressed. It should work without a ship.
This code does make missile move - but it does not do what I want it to. Note that once i have working code i will turn this into a class & remove magic numbers etc. For simplicity, i'm not worried about doing that at the moment :

// an implementation of a missile.
#include <iostream>
#include<SFML/Graphics.hpp>
#include<SFML/System.hpp>
int main()
{
sf::RenderWindow mywindow(sf::VideoMode(800, 600, 32), "missile testing");
 mywindow.setVerticalSyncEnabled(true);
// create sprite
sf::Texture missilepic;
missilepic.loadFromFile("/home/game/images/missile.png");
sf::Sprite missile;
missile.setTexture(missilepic);
missile.setPosition(400,500);

 sf::Time elapsed;
 sf::Clock clock;

        bool running = true;
        while(mywindow.isOpen())
        {
           elapsed = clock.getElapsedTime();
          clock.restart();
               
        sf::Event event;
        while (mywindow.pollEvent(event))
          {
                if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                mywindow.close();
          }    
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::LShift))
          { // code to move missile
           
                missile.move(0, -2 * elapsed.asSeconds());    
             
          }

        mywindow.clear();
                mywindow.draw(missile);
 mywindow.display();
}
 return EXIT_SUCCESS;
}//main

 
problem 1. Unless I keep the l-shift key pressed, the missile will only move a short distance. I need it to move from it's origin on y-axis at 500 right up to 0 - with 1 key press. I think a loop will be needed but with what parameters?

problem 2. Adjusting speed. at first i experimented with the code that i used to move the ship left/right. But this does not work for the missile as that code depends on the left or right key remaining pressed. If i use the same settings, the missile moves too fast. So how can i make it move at a slower rate? What is the code to use?

I asked for help on another forum, but the answer i had was wrong as the person thought that the missile movement code was part of the event - polling code - it isn't as it appears outside of that loop. Anyway, i am mixed up about this as i cannot see how to move the missile up the y axis at a controlled speed (that can be changed easily).
« Last Edit: May 15, 2013, 04:15:18 pm by nvangogh »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Controlling sprite movement speed?
« Reply #1 on: May 10, 2013, 09:23:34 pm »
Do you not understand the code you have written? The code to move your "missile" is contained within a IF block. Only if the LShift is pressed will move the "missile". If you want to move it outside of the IF block set a bool inside your event loop for when the LShift button is pressed to true or whatever when you want to start moving the "missile". The check that bool and move the sprite accordingly. Note this code is example code.
bool movemissile = false;

while (mywindow.pollEvent(event))
      {
        if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::LShift))
movemissile = true;
      }

if (movemissle){ //move it}
 
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

nvangogh

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Controlling sprite movement speed?
« Reply #2 on: May 11, 2013, 12:48:46 am »
Hi - my question is mainly about the movement speed of the sprite.

speed = distance/ time
The distance is 400 pixels. I do not know what / how to adjust time to make it a reasonable speed.

- can you shed any light on that?

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Controlling sprite movement speed?
« Reply #3 on: May 11, 2013, 02:27:49 am »
Google "delta time" for more information on the topic of framerate independent speed.
https://www.scirra.com/tutorials/67/delta-time-and-framerate-independence

As directly for your question, the formula speed = distance / time can also be written as time * speed = distance. Note that your distance will not be 400 pixels. Therefore multiple time (elapsed ms) * speed (how fast you want the sprite to move) = distance (how far to move the sprite in that frame). Then simple move your sprite that distance. Then if you do not want the sprite to move farther than 400 pixels do a simple if statement and simple move the sprite position to the maximum distance you want it to move.

if (sprite.postion.y > 400)
{
sprite.position = 400;
}
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

nvangogh

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Controlling sprite movement speed?
« Reply #4 on: May 12, 2013, 06:12:50 pm »
Hey, can someone please help me with this?
So far, I have had answers that have told me that my code to capture the event of a key press was incorrect. I have fixed that now, but the other problem i had - and the main problem - was concerning the movement speed of a sprite. I have asked if someone could kindly post the single line of code that shows the correct syntax to achieve what i want, but I have only been given vague answers that have not really helped.

I need to make a sprite move over a defined number of pixels, in 2 seconds

I understand that speed is calculated by distance / time. I really don't need to know the speed - I just need to see the sprite move along for 2 seconds. As you can see I have not provided 'clock' or 'time' with any values as they are not being used.

[while(mywindow.isOpen())
        {
          sf::Clock clock;
          sf::Time dt;
                       
        sf::Event event;
        while (mywindow.pollEvent(event))
          {
                if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                mywindow.close();
         
                if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::LShift))
                  {
                    // fire 1 missile!
                    while(position.y >= 0)
                      {
                        missile.move(0, -1);
                        --position.y;
                       
                      }                  
                  }
         
}
 
This test works to move my sprite the distance I want, but obviously there are no speed or time considerations.

The documentation says about member function move( ):
void    move (float offsetX, float offsetY)
        Move the object by a given offset.
 


In the test code above the offset is -1 on each iteration. What I am asking for is the code that simply makes my sprite move over the distance stated in 2 seconds.

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: Controlling sprite movement speed?
« Reply #5 on: May 12, 2013, 07:08:00 pm »
What you wrote:
missile.move(0, -2 * elapsed.asSeconds());
speed = distance/ time

So you already have everything. Your speed here is 2.
If you want your missile to travel 400px in 2 seconds, give it a speed of 400 / 2 = 200. (200px/s)
missile.move(0, -200 * elapsed.asSeconds());

It will travel a "defined number of pixels (400px) in 2 seconds".
« Last Edit: May 12, 2013, 07:10:46 pm by G. »

nvangogh

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Controlling sprite movement speed?
« Reply #6 on: May 12, 2013, 07:45:08 pm »
But this does not work. What happens now - with one key press, is that the sprite moves only halfway up the window - and it is not moving at a slow rate either.


#include<SFML/Graphics.hpp>
#include<SFML/System.hpp>
int main()
{
sf::RenderWindow mywindow(sf::VideoMode(800, 600, 32), "missile testing");
 mywindow.setVerticalSyncEnabled(true);
// create sprite
sf::Texture missilepic;
missilepic.loadFromFile("/home/game/images/missile.png");
sf::Sprite missile;
missile.setTexture(missilepic);
missile.setPosition(400,500);
//size of sprite
missile.setScale(0.01f,0.02f);
 sf::Vector2f position(400,500);
 
sf::Time elapsed;
 sf::Clock clock;

        bool running = true;
        while(mywindow.isOpen())
        {
      elapsed = clock.getElapsedTime();
                sf::Event event;
        while (mywindow.pollEvent(event))
          {
                if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                mywindow.close();
         
                if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::LShift))
                  {
                    // fire 1 missile          
                        missile.move(0, -200 * elapsed.asSeconds() );
                        clock.restart();
                  }
          }

        mywindow.clear();
        mywindow.draw(missile);
        mywindow.display();
} // while window is open
 return EXIT_SUCCESS;
}//main

 
Why is it moving halfway up only? I removed the loop that was there before. Now, the time setting does not seem to have had any effect other than to stop the sprite halfway.
Please can someone post some code so that i can see what the syntax should look like?

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: Controlling sprite movement speed?
« Reply #7 on: May 12, 2013, 09:04:34 pm »
The correct way to measure the elapsed frame time is shown at the very end of the time tutorial.
You should restart your clock every frame, so that elapsed time measures the elapsed time of each frame.
(= remove your clock.restart() and replace your clock.getElapsedTime() by clock.restart())

Also since you move your missile inside the event loop, your missile only moves when a lshift KeyPressed event is triggered.
If you hold the lshift key, only one lshift KeyPressed event is triggered (so the missile moves ONCE) unless keyRepeat is enabled. If KeyRepeat is enabled, it's similar to holding a key in a text editor: the first keypressed event is triggered, then after a few ms with no event, the keypressed event is continuously triggered. (so even with keyrepeat, it probably wouldn't look good on your missile)
Events are not "good" for continuous key press, (sf::Keyboard::isKeyPressed is) they are good for ponctual events.
If you want to solve this, you'll either have to use sf::Keyboard::isKeyPressed (the sprite will move only while lshift is pressed), or implement something like zsbzsb said in the first answer (the sprite will move after lshift has been pressed).

Here's what the latter would look like in your weirdly indented code:
#include<SFML/Graphics.hpp>
#include<SFML/System.hpp>
int main()
{
sf::RenderWindow mywindow(sf::VideoMode(800, 600, 32), "missile testing");
 mywindow.setVerticalSyncEnabled(true);
 mywindow.setKeyRepeatEnabled(false);
// create sprite
sf::Texture missilepic;
missilepic.loadFromFile("/home/game/images/missile.png");
sf::Sprite missile;
missile.setTexture(missilepic);
missile.setPosition(400,500);
//size of sprite
missile.setScale(0.01f,0.02f);
 sf::Vector2f position(400,500);
 
sf::Time elapsed;
 sf::Clock clock;

    bool running = true;
   bool fireMissile = false;
    while(mywindow.isOpen())
        {
      elapsed = clock.restart();
                sf::Event event;
    while (mywindow.pollEvent(event))
      {
        if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
            mywindow.close();
     
        if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::LShift))
          {
            // fire 1 missile      
            fireMissile = true;
          }
      }

   // move the missile if it has been fired
   if(fireMissile)
   {
      missile.move(0, -200 * elapsed.asSeconds() );
   }

    mywindow.clear();
    mywindow.draw(missile);
    mywindow.display();
} // while window is open
 return EXIT_SUCCESS;
}//main

With this code, the sprite doesn't move. If you press (hold or not) the LShift key, the sprite will start to move at the steady speed of 200 pixels per second and will never stop.
Is this what you want ?
« Last Edit: May 12, 2013, 09:07:07 pm by G. »

nvangogh

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Controlling sprite movement speed?
« Reply #8 on: May 12, 2013, 09:36:13 pm »
Hi thanks G. This is the effect i wanted.
Now i know how to control the speed - i can easily define where the sprite stops. This was a long journey to get to this. No one can look me in the eye and tell me that this is clearly explained in the tutorial.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Controlling sprite movement speed?
« Reply #9 on: May 12, 2013, 10:28:38 pm »
Quote
I have asked if someone could kindly post the single line of code that shows the correct syntax to achieve what i want, but I have only been given vague answers that have not really helped.
We are not here to write your code. I already told you in a very DETAILED answer what you needed to know. If you can not convert what I told you (like G. did) into code then you need to take a step back and make sure that you are really ready to make games. What you are asking is something that is a basic part of any type of game.

And by the way, G. your code will continue to move the sprite past 400 pixels (total movement length). But if nvangogh wants it to stop after 400 pixels lets see if he can do it himself (look at my explanation of how to do it above).
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

nvangogh

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Controlling sprite movement speed?
« Reply #10 on: May 13, 2013, 12:00:00 am »
Yes and I am not here to be insulted by you or anyone else. One person kindly took the time to explain something to me I had trouble understanding. You seem to have a chip on your shoulder as I did NOT find your contribution helpful. Don't bother replying to any questions I raise in the future as I intensely dislike people like you who seem to indicate by your language that you are somehow a cut above anyone else.
And finally I don't need you to tell me what I should be doing with my time. I never asked your opinion.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Controlling sprite movement speed?
« Reply #11 on: May 13, 2013, 02:29:33 am »
Quote
Yes and I am not here to be insulted by you or anyone else.

First off I have no intention of insulting you, so please stop calling out that people are trying to insult you. All this does is turn a thread into a flame war and that is not needed here. If it makes you feel better, I am sorry unintentionally insulting you.


Quote
You seem to have a chip on your shoulder
Quote
I intensely dislike people like you who seem to indicate by your language that you are somehow a cut above anyone else.

I have never claimed to "have a chip on my shoulder" by saying I am above other people. In fact there are quite a few people on this forum that have way more experience than me (laurent, exploiter, nexus...).


Quote
And finally I don't need you to tell me what I should be doing with my time.

By simply stating that you should maybe check yourself and make sure that you are ready for making a game is not telling you what to do with your time. Lots of people on this forum will echo me in saying that you should have a good grasp of C++ and programming before you attempt to use SFML to make games.


Quote
One person kindly took the time to explain something to me I had trouble understanding.

I refer to my point directly above, the code I gave you in my first post in this thread should have been plenty enough to get you to the point where you moved the movement code outside of your event handling, but yet the next two times you posted code your movement code was still contained inside the event handling. It took until G. had to literately post code that you can copy and paste and compile until you said "this is the effect I wanted". Which still makes me doubt whether even understand what makes the code work.

For the record, if you have code contained inside event handling that code will only execute when that event is fired, which explains why the sprite would only move a small distance.

As for you second problem, movement speed. I explained in my second post that the formula, velocity = distance / time, that in this instance the distance is not the total length you want the sprite to move. Once again I explained it nice and simple, "time * speed = distance" The distance is not the total distance, it is how far you move it in that frame (think sprite.move()). This is exactly what G.'s code does with...

missile.move(0, -200 * elapsed.asSeconds() );

Notice the formula in here? distance (-200) * time (elapsed) = distance (to move)



Quote
No one can look me in the eye and tell me that this is clearly explained in the tutorial.

I just checked the tutorials and I will agree with you on that, they clearly do not explain delta timing. However had you followed me advice to punch into google "delta timing" most if not all of your speed issues would have been resolved sooner (and you actually might feel better about it since you found the information yourself).


Now after you look back and see what I posted was exactly what you wanted (just not in code form) I hope you can start to understand why we want people to learn to do things on their own and not just ask us to write code for them. If you had taken time to understand what I told you G. would never had to double this thread size with the same information and you would have had your answers much sooner and we would never have to be "at odds" with each other.

That's all I have to say, once again I have never intended to insult you or act like I have a chip on my shoulder. Welcome to SFML and good luck.
« Last Edit: May 13, 2013, 02:32:01 am by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: Controlling sprite movement speed?
« Reply #12 on: May 13, 2013, 04:23:35 am »
Lots of people on this forum will echo me in saying that you should have a good grasp of C++ and programming before you attempt to use SFML to make games.
Prepare to be shat upon. :D
Last time I implied he should  maybe learn a little more C++, he got angry and insulted me on a few posts and Laurent eventually deleted the thread. It was almost a year ago.
« Last Edit: May 13, 2013, 04:25:32 am by G. »

nvangogh

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Controlling sprite movement speed?
« Reply #13 on: May 13, 2013, 05:35:27 pm »
Lots of people on this forum will echo me in saying that you should have a good grasp of C++ and programming before you attempt to use SFML to make games.
Prepare to be shat upon. :D
Last time I implied he should  maybe learn a little more C++, he got angry and insulted me on a few posts and Laurent eventually deleted the thread. It was almost a year ago.

You have the wrong person. I have not 'got angry' and insulted anyone here in a few posts or more. It confuses me that you are making this claim. I am sure you have your reasons for doing so.

Anyway, i do not need to be 'shat upon' by anyone because I am perfectly capable of reading and learning myself. I may not have '100 forum posts' to my name, but I have solid experience of using c++. There are many forums online and many people who actually like helping others out. I've had help from c++ experts in learning standard c++ and continue to learn. Even the most incredibly experienced programmers do not know and cannot know everything. My point is that if - as you imply - there are people here who go out of their way to post 'put downs' or whatever at others - I don't need to get involved as there are many other options for help open to me. I was simply posting here to learn - not to get into arguments or upset anyone. If people cannot give me the same level of courtesy that I give them I don't have any business engaging in communications of that type.

I should make it clear i was grateful for your help - I was not taking the mic - i just needed to see some example code for the speed control. I was not comfortable simply copying some code and hacking it until it worked. I was actually trying to understand a few whys and hows. My difficulties did not stem from lack of c++ knowledge but because i have not ever used this particular library before. There are some classes and features that are intuitive - the issue that i raised was not and I needed further information / examples. So thanks for your help.