SFML community forums

Help => General => Topic started by: Ionut on May 05, 2017, 03:44:40 pm

Title: [SOLVED]Smart Moving Problem
Post by: Ionut on May 05, 2017, 03:44:40 pm
Hey! I have a little problem with the "smart moving"(smart moving means : if the player is like (http://cdn.onlinewebfonts.com/svg/download_1410.png) and it presses up the spaceship will go in the direction where it is oriented(I mean it won't go simply up).So the question is : How to do smart moving in a game ?
Title: Re: Smart Moving Problem
Post by: Arcade on May 05, 2017, 04:42:50 pm
Make a variable that keeps track of the angle of the spaceship. Use trigonometric functions (such as sin and cos) to calculate how much the spaceship should be moved in the x and y directions based on that angle when the 'up' key is pressed.
Title: Re: Smart Moving Problem
Post by: sjaustirni on May 05, 2017, 04:44:55 pm
Store velocity and acceleration of spaceship and iterate on that. Here's a great tutorial on this subject: http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/
Title: Re: Smart Moving Problem
Post by: Ionut on May 05, 2017, 05:40:36 pm
Ok I've readed it, can you give me an example how to wrote this ?
Title: Re: Smart Moving Problem
Post by: eXpl0it3r on May 05, 2017, 06:08:38 pm
You want to use atan2. It's a very, very common problem and a simple Google search will result in many tutorials and examples (e.g. like this: http://www.gamefromscratch.com/post/2012/11/18/GameDev-math-recipes-Rotating-to-face-a-point.aspx).
Don't expect others to write you a working example that you copy&paste, but try to understand the problem and the solution.
Title: Re: Smart Moving Problem
Post by: sjaustirni on May 05, 2017, 09:15:33 pm
Firstly, notice there are 3 parts of the tutorial, make sure you read all of them.
Secondly, as you may have noticed, this assumes you're familiar with vector math. Now, I don't know if you have learnt about vectors in school, but if you haven't, I suggest you to look up the vector math on the Internet and only once you have a fair understanding of it to come back to programming. There really are no shortcuts here, trust me, I've been there.
Title: Re: Smart Moving Problem
Post by: Ionut on May 06, 2017, 09:08:32 am
Ok, I've readed wolffire all 3 parts, but I don't have any how to put it in my code.I tried and atan2 but it returns 0(sprite.rotate(angle) doesn't move it, I did a cout << angle and it said 0)
Title: Re: Smart Moving Problem
Post by: eXpl0it3r on May 06, 2017, 10:37:22 am
Don't forget that the C++ math function operate with radian and SFML uses degree, so you'll have to convert.

Not sure what you're implying with the cout. If the rotation angle is 0, nothing will be rotated.

Did you actually understand the math or did you just copy&paste the code?
Title: Re: Smart Moving Problem
Post by: sjaustirni on May 06, 2017, 02:03:40 pm
Ok, I've readed wolffire all 3 parts, but I don't have any how to put it in my code.I tried and atan2 but it returns 0(sprite.rotate(angle) doesn't move it, I did a cout << angle and it said 0)

I feel like I am repeating myself, but I'll tell you anyway. If you don't know the vector math, don't bother yourself with the programming.
Go through this instead: https://www.khanacademy.org/math/precalculus/vectors-precalc
Title: Re: Smart Moving Problem
Post by: Ionut on May 06, 2017, 08:52:10 pm
Ok, I've learened all about vectors(and  understood it), but what are the functions to do it(bad exprimation, I know... I don't have any idea how to use vectors to make the rotation(bad exprimation again).

And...
Quote
If you don't know the vector math, don't bother yourself with the programming.
Sjaustirni you don't have to be so harsh with me because I am a beginner...
Title: Re: Smart Moving Problem
Post by: sjaustirni on May 06, 2017, 10:58:08 pm
I am sorry if it sounds harsh, it wasn't meant to be harsh, just bold, because it can save you a lot of time.

As to the vector rotation, you actually may not need it. What are you trying to achieve?
Title: Re: Smart Moving Problem
Post by: Ionut on May 07, 2017, 07:30:01 am
Quote
What are you trying to achieve?
If the Player presses Left the Spaceship will rotate to Left and if the Player presses Up the Spaceship will go in that direction,not simple acceleration(I mean to simply accelerate in front, uhh it's so hard to explain that...).
Title: Re: Smart Moving Problem
Post by: sjaustirni on May 07, 2017, 08:57:17 am
I am a bit confused.

In your model, what happens when you press Left key for an infinitely long time? Does the ship go round in a circle or does it go parallel with the y axis?
Title: Re: Smart Moving Problem
Post by: Ionut on May 07, 2017, 09:52:12 am
So let say the ship is like  that up sign https://www.warningsignsdirect.co.uk/index.php?cPath=513_1068&osCsid=jivfi8rv5bkh44k565rvcrdj62 (https://www.warningsignsdirect.co.uk/index.php?cPath=513_1068&osCsid=jivfi8rv5bkh44k565rvcrdj62)
when the player will press left it will go to angle 359 (from 360, when the spaceship is up her angle is 360,no?)
,now if the player presses up the spaceship will go ahead from that angle(359) and it won't change it's angle till the player will press Left or Right. This is what I was trying to explain.So how to do that how to rotate the ship and how to accelerate in that position?
Title: Re: Smart Moving Problem
Post by: GameBear on May 07, 2017, 10:39:25 am
So.. im still not 100% sure what part you want..
So, this is a compleate (if a bit hacky) way to rotate, accelerate, and move a space ship (m_Ship)
In my example I just use a ractangeShape for the ship, but you can use a sprite just fine.
you will need the values.

float m_xVel = 0, m_yVel = 0, m_accel = 0.01;
hidden somewhere where MoveShip can accec them.
the x and y Val is the current speed that the ship is moving at the x and y axis.
the m_accel is how fast it accelerates in a given direction.

in addition you will need a sf::Keyboard m_Key
This can be done differently, but for this short code that is all i made.

    //in the header//
float m_xVel = 0, m_yVel = 0, m_accel = 0.001;
sf::Keyboard m_Key;


    //In the class//
void Game::MoveShip() {
        //Rotate right and left
        if (m_Key.isKeyPressed(sf::Keyboard().Right)) {
                m_Ship.setRotation(m_Ship.getRotation() + 1);
        }
        if (m_Key.isKeyPressed(sf::Keyboard().Left)) {
                m_Ship.setRotation(m_Ship.getRotation() - 1);
        }
        //Accelerate the ship forward.
        if (m_Key.isKeyPressed(sf::Keyboard().Up)) {
                m_xVel += (cos(m_Ship.getRotation() / 180 * 3.1415)) * m_accel;
                m_yVel += (sin(m_Ship.getRotation() / 180 * 3.1415)) * m_accel;
        }

        //Make the actual movement of the ship.
        m_Ship.setPosition(m_Ship.getPosition().x + m_xVel, m_Ship.getPosition().y + m_yVel);
}
 

this code will rotate the ship and move it around using the Up, Right and Left button.
the first two If statements simply looks for pressing the Right and Left key. and apply rotation to the ship accordingly.
the third, as the first two looks for a key press, but this time the up key.
if the up key is pressed, it grasp the current rotation, and using cos and sin, it calculates how much to add to the ships x and y speed (velocity).

note that the ships rotation is divided by 180*PI, the reason for this is that SFML rotation uses 360 degree rotation, where the math con and sin is geard towards radiant (rotation = 0-1)

In this case, a rotation of 0 or 360 is horizontal fazing right.

This will give you movement like in the asteroids games where your ship will float around in whatever direction until it is accelerated in another direction.

i Hope that helps.

if you want the full code to look over, i can upload that somewhere.
Title: Re: Smart Moving Problem
Post by: sjaustirni on May 07, 2017, 11:36:04 am
I would like to point out that ship velocity and ship rotation are 2 different things in the real world. So you should separate them in your model as well.

As you may have noticed, I am not a big fan of posting production-ready code. I will rather guide through the process, giving you hints and nudges to the right direction ;-)

Firstly, the ship rotation. You change it with Left and Right keys. For that purpose you can use for instance sf::Transformable::rotate(angle) (https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1Transformable.php#af8a5ffddc0d93f238fee3bf8efe1ebda)
ship.rotate(dt*omega);
(Note that this is a bit of oversimplification, as in the real world you rotate yourself using your side thrusts or similiar, but for your purposes, I believe it suffices)

Secondly, there's ship velocity which you should store as a 2D vector. You change it with Up and Down keys. In code, this is achieved by adding the ship acceleration to its velocity every frame Up and Down keys are pressed down:
ship.velocity += ship.acceleration
I see what you're saying - how do you get ship.acceleration?
Out of the ship angle, obviously (using sf::Transformable::getRotation() (https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1Transformable.php#ad783a7e9971398ec613d22455252809e)).
OK, you say, but how exactly?
Well, this is when vector math kicks in. I'll leave you here with this SO post (http://stackoverflow.com/questions/12959237/get-point-coordinates-based-on-direction-and-distance-vector).

Note: GameBear posted de facto the same solution (https://en.sfml-dev.org/forums/index.php?topic=21922.msg155324#msg155324), I just hadn't noticed before he made me aware of it :)
Title: Re: Smart Moving Problem
Post by: Ionut on May 08, 2017, 04:12:25 pm
GameBear I have some questions ...

First, why did you use m_Key and didn't used Keyboard::isKeyPressed(Keyboard::Key) ?
Second, I tried your code and the spaceship only rotate, but if I press up nothing happens.
PS: I am wrong or you mistake Val with Vel ?
PPS : I wrote the code with my hands( I would be a hypocritical if I say I didn't use your code,I wrote it with my things like m_spaceship to SSpaceship(the sprite) and others) and I wrote Vel not Val, it is right ?
Title: Re: Smart Moving Problem
Post by: GameBear on May 08, 2017, 04:42:24 pm
Ah, you are correct, Val should be Vel..
About keyboard, that's a preference from my side, I find it faster to type over multiple usages.

Please, can you copy pace your code Here.   I'll see if I can spot the error..just tried the code myself, and it works fine :)
Title: Re: Smart Moving Problem
Post by: Ionut on May 08, 2017, 05:08:50 pm
Here is my code... I have another question : When I press Up the spaceship goes to right instead of ahead(it is oriented to up(north) from start) and the if I press Up the spaceship continues to go, it doesn't stops, why ?
#include <SFML/Graphics.hpp>
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;
using namespace sf;
int main()
{
    float m_xVel = 0, m_yVel = 0, m_accel = 0.001;
    Keyboard m_Key;
    int x = 0;
    int y = 0;
    const float PI = 3.14159265;
    RenderWindow window(VideoMode(800,600),"Endless");
    window.setFramerateLimit(60);
    window.setVerticalSyncEnabled(1);
    Texture TSpaceship;
    if(!TSpaceship.loadFromFile("Spaceship.png"))
    {
        cout<<"Error"<<endl;
    }
    TSpaceship.setSmooth(1);
    Sprite SSpaceship;
    SSpaceship.setTexture(TSpaceship);
    SSpaceship.setOrigin(0,0);
    SSpaceship.setPosition(400,300);
    while(window.isOpen())
    {
        Event event;
        while(window.pollEvent(event))
        {
            if(event.type == Event::Closed)
            {
                window.close();
            }
        }
        if (m_Key.isKeyPressed(Keyboard().Right)) {
                SSpaceship.setRotation(SSpaceship.getRotation() + 1);
        }
        if (m_Key.isKeyPressed(Keyboard().Left)) {
                SSpaceship.setRotation(SSpaceship.getRotation() - 1);
        }
        if (m_Key.isKeyPressed(Keyboard().Up)) {
                m_xVel += (cos(SSpaceship.getRotation() / 180 * 3.1415)) * m_accel;
                m_yVel += (sin(SSpaceship.getRotation() / 180 * 3.1415)) * m_accel;
        }
        SSpaceship.setPosition(SSpaceship.getPosition().x + m_xVel, SSpaceship.getPosition().y + m_yVel);
        window.clear();
        window.draw(SSpaceship);
        window.display();
    }
}
 
Title: Re: Smart Moving Problem
Post by: GameBear on May 08, 2017, 05:56:43 pm
Okay, I just tested your code, and it works as it should.

But I think i know where you get confused.

360 or 0 degrees (Start position) is horizontal facing right like this arrow -->
or said in another way, if your ship image is facing north, you should rotate it 90 degrees so it faces east in the image file.

Secondly, as mentioned in my post, this is an asteroids like movement, the longer you hold UP, the faster the ship will go.

look at this code part:


        if (m_Key.isKeyPressed(Keyboard().Up)) {
                m_xVel += (cos(SSpaceship.getRotation() / 180 * 3.1415)) * m_accel;
                m_yVel += (sin(SSpaceship.getRotation() / 180 * 3.1415)) * m_accel;
        }
        SSpaceship.setPosition(SSpaceship.getPosition().x + m_xVel, SSpaceship.getPosition().y + m_yVel);



each time the UP key is pressed, m_xVel and m_yVel is changed.
what happens from the start is this,
-the ship is standing still (m_xVel = 0 and m_yVel = 0) and is rotated 360 degrees.
- UP is pressed, and because of this, the system adds a value to m_xVel and m_yVel (that is the cos and sin code up there) for simplicitys sake, lets say they change to m_xVel = 1, and m_yVel = 0;
-Then m_xVel and m_yVel is added to the ships current position. moving the ship på 1 on the X axis.
-Each update from now on, m_xVel and m_yVel will be the same, and will be added to the ships position, moving it at 1 per update.
-IF UP is pressed again, m_xVel and m_yVel will again get a new value, this value will be added to the old value.
so if whe have not rotated, the new values will be m_xVel = 2, and m_yVel = 0;
-The ship will now be updated and moved twice as fast in the X direction (2 instead of 1)
-IF we then rotate 90 degrees clock vice (the ship facing down) and press UP again. the m_xVel and m_yVel will be changed again, but this time, it would be yVel that gets 1 added to it.
so the nev values are now m_Xvel = 2, and m_yVel = 1.
-The ship is now updated, and moves +2 X and +1 Y (or East-South-East if you will)

Things you should try to make it more easy for yourself to see.
Try to change the value of m_accel to 0.01 or even 0.1.

After the if Key pressed but before SSpaceship.setPosition
Try and add:

      m_xVel = m_xVel * 0.99;
      m_yVel = m_yVel * 0.99;

This will "Stop" the space ship after some time.
See what happens if you write * 0.5 or * 0.999 instead...

Try to rotate your image in all directions in the editor.
What you should notes is that ite does not effect the code at all, just the "looks"

After SSpaceship.setPosition
try to add:
      if (SSpaceship.getPosition().x > 800) SSpaceship.setPosition(0, SSpaceship.getPosition().y);
      else if (SSpaceship.getPosition().x < 0) SSpaceship.setPosition(800, SSpaceship.getPosition().y);
      if (SSpaceship.getPosition().y > 600) SSpaceship.setPosition(SSpaceship.getPosition().x, 0);
      else if (SSpaceship.getPosition().y < 0) SSpaceship.setPosition(SSpaceship.getPosition().x, 600);

This will keep the space ship looping inside the window.

Edit, lastly, I notes that you have two values you never use, int x and int y.
and that you have made a definition of PI.
If you look at your code, there is a place where an approximation of PI is used, if you wish, you could just as well go ahead and and exchange that approximation for your own PI, that would both be more correct mathematical, but also more easy to write in the future.
Title: Re: Smart Moving Problem
Post by: Ionut on May 10, 2017, 05:13:16 pm
Ok, I've finally finished the code, ;D and I modified the acceleration(if it is bigger it makes the car move faster, logically) , the vel(I really don't know why it does like that, I mean why the difference between 0.99 and 0.999 or 0.5, the longer(bigger) the number is the faster it stops), the MOST IMPORTANT thing is to rotate the spaceship to RIGHT(rotate it from the .png(I mean rightclick on the photo and click rotate clockwise,DON'T do it with rotate() function this won't work).I will post my code here and explain it for all newbies like me :P.
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
#include <math.h>
#include <vector> //I tried to this many times so I don't know if you need this.
using namespace std;
using namespace sf;
int main()
{
    float m_xVel = 0, m_yVel = 0, m_accel = 0.1;  //Setting the vel and acceleration
    Keyboard m_Key;
    RenderWindow window(VideoMode(800,600),"Endless");  //Creating the window
    window.setFramerateLimit(60);  //Limiting the framelimit to 60
    window.setVerticalSyncEnabled(1); //Enable the VSync
    Music music;
    if(!music.openFromFile("Music.ogg"))
    {
        cout<<"Error"<<endl;
    }
    music.play();     //Playing some nice music
    music.setLoop(1);     //If it ends it will start again
    music.setVolume(10);  //I don't know but .setVolume() doesn't work for me, I mean it doesn't changes the volume of the music
    Texture TStars;                   //Setting the Texture for the Background
    if(!TStars.loadFromFile("Stars.png"))
    {
        cout<<"Error"<<endl;
    }
    TStars.setSmooth(1);     //Smoothing it to look nicer
    Sprite SStars;  
    SStars.setTexture(TStars); //Setting the Texure to the Sprite
    Texture TSpaceship; //Setting the Texture
    if(!TSpaceship.loadFromFile("Spaceship.png"))
    {
        cout<<"Error"<<endl;
    }
    TSpaceship.setSmooth(1);  //Smoothing it
    Sprite SSpaceship;
    SSpaceship.setTexture(TSpaceship);      //Setting the Texure to the Sprite
    SSpaceship.setOrigin(0,0);    //Setting the Origin
    SSpaceship.setPosition(400,300);   //Setting the position in the middle of the window
    while(window.isOpen())
    {
        Event event;
        while(window.pollEvent(event))
        {
            if(event.type == Event::Closed)
            {
                window.close();     //Checking if the User clicks "X", if so the window will close
            }
        }
        if (m_Key.isKeyPressed(Keyboard().Right)) {
                SSpaceship.setRotation(SSpaceship.getRotation() + 1); //If right is pressed the spaceship will rotate to right
        }
        if (m_Key.isKeyPressed(Keyboard().Left)) {
                SSpaceship.setRotation(SSpaceship.getRotation() - 1);   //If left is pressed the spaceship will rotate to left
        }
        if (m_Key.isKeyPressed(Keyboard().Up)) {
                m_xVel += (cos(SSpaceship.getRotation() / 180 * 3.1415)) * m_accel;
                m_yVel += (sin(SSpaceship.getRotation() / 180 * 3.1415)) * m_accel;
//If up is pressed the spaceship will go ahead at the same angle
        }
        m_xVel = m_xVel * 0.99;  //Stop the ship after some time
        m_yVel = m_yVel * 0.99;
        SSpaceship.setPosition(SSpaceship.getPosition().x + m_xVel, SSpaceship.getPosition().y + m_yVel); //Setting the Position(almost the most important thing here,without it the spaceship won't move)
        if (SSpaceship.getPosition().x > 800 + 74)
        SSpaceship.setPosition(0, SSpaceship.getPosition().y);
       else if (SSpaceship.getPosition().x < 0 - 74 )
        SSpaceship.setPosition(800, SSpaceship.getPosition().y);
       if (SSpaceship.getPosition().y > 600 + 84)
       SSpaceship.setPosition(SSpaceship.getPosition().x, 0);
       else if (SSpaceship.getPosition().y < 0 - 84)
        SSpaceship.setPosition(SSpaceship.getPosition().x, 600);
//This keeps the spaceship looping inside the window, I think it's called world-wrapping
        window.clear();  //Clear the window
        window.draw(SStars);  //Drawing the Stars(Background)
        window.draw(SSpaceship); //Drawing the Spaceship(Player)
        window.display();  //Display it
    }
}
 
Title: Re: Smart Moving Problem
Post by: GameBear on May 10, 2017, 05:41:03 pm
Great work :)
Just looked it over, and it works great.

about why the ship stops when you multiply m_yVel and m_xVel with 0.99 or something:
as you know, the two Vel is the velocity, or speed of the object if you will.
if the objects xVel is 10, and you then multiply it by 0.9, it becomes 9.
next time you multiply it, it will become 8.1
then it will become 7,29, then 6,561.
the reason is that each time, you multiply vel by 0.9, its the same as removing 10% of the speed, multiplying by 0.99 is removing 1%, and multiplying by 1 is removing nothing. basically multiplying by 1 means keep 100%, 0,5 means keep 50% and 0.25 means keep 25%

I also notes you write this line:
#include <vector> //I tried to this many times so I don't know if you need this.
 
Best way to figure that out is to just delete the line and see if anything happens, if it does, place it right back in ;)
Title: Re: Smart Moving Problem
Post by: Ionut on May 11, 2017, 05:35:53 pm
Thank you all ! You are the BEST ;)! Oh, and about #include <vector> I didn't had codeblocks opened to verify that and I was too lazy to open it  ;D .

PS:Thanks for all the help, sorry I confused you for a while :P.
PPS: GameBear and I am a fan of Dragon Ball too,I love your "logo". :)
Title: Re: Smart Moving Problem
Post by: Hapax on May 12, 2017, 12:14:39 am
I also notes you write this line:
#include <vector> //I tried to this many times so I don't know if you need this.
 
Best way to figure that out is to just delete the line and see if anything happens, if it does, place it right back in ;)
I disagree with this advice. Something you include may include it for you but then if, in the future, you stop needing the other thing, you may still need it. It's best to explicitly include it if you need it regardless of if its already included elsewhere.

You include "<vector> (http://www.cplusplus.com/reference/vector/)" if you wish to use a vector. That is, if you have a std::vector (http://www.cplusplus.com/reference/vector/vector/) in your code, you should include it.
Title: Re: Smart Moving Problem
Post by: GameBear on May 12, 2017, 01:34:59 pm
I also notes you write this line:
#include <vector> //I tried to this many times so I don't know if you need this.
 
Best way to figure that out is to just delete the line and see if anything happens, if it does, place it right back in ;)
I disagree with this advice. Something you include may include it for you but then if, in the future, you stop needing the other thing, you may still need it. It's best to explicitly include it if you need it regardless of if its already included elsewhere.

You include "<vector> (http://www.cplusplus.com/reference/vector/)" if you wish to use a vector. That is, if you have a std::vector (http://www.cplusplus.com/reference/vector/vector/) in your code, you should include it.

I guess i did not conveyed what i meant properly.
I meant that if you do not know if the code "as is" need the inclusion. that is, if your current code uses that inclusion.
The fastes way to figure that out is to just delete the line, that will tell you if it is used.

*Also, this advice only counts for inclusions. doing the same to other inline code may not show it self as an error right away...
Title: Re: Smart Moving Problem
Post by: Ionut on May 14, 2017, 08:03:00 am
Ok let's make light, you don't need to include "#include <vector>" and I wrote that comment because I was too lazy to check if you need it or not.And I've included it in the first place because I tried to do the "smart moving" with vectors(I tried this from a tutorial).