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

Author Topic: Rotation changes every time A key is pressed  (Read 4186 times)

0 Members and 1 Guest are viewing this topic.

Frostbite

  • Newbie
  • *
  • Posts: 17
    • View Profile
Rotation changes every time A key is pressed
« on: November 09, 2009, 06:08:03 am »
Hi, I (like many others it seems =P) am new to SFML (and C++ kinda) and I have been developing a simple game where currently a tank moves around the screen and his turret moves independently (it should always be pointed at the mouse) Then you can fire a missile. The problem is that whenever a button is pressed the rotation seems to switch to some seemingly random location. I think this has something to do with the way I make the turret track the mouse or maybe something to do with the way the tank moves, either way here is the code, and Thanks for help in advance, I know you probably have something better to do with your time than debug a newbs code.


The Turret to mouse tracking code

Code: [Select]

//I realize that I Didn't use the decimalCin and DecimalCos here, and that there is a conflict, but it works with the tank stationary, without buttons pressed
float ElapsedTime = App.GetFrameTime();
MouseY = Event.MouseMove.Y;
MouseX = Event.MouseMove.X;
       if ((PlayerTurret.GetPosition().y -MouseY) > 0 and (PlayerTurret.GetPosition().x-MouseX) > 0){ // If It has a Positive in the Num and denom
            PlayerTurret.SetRotation( -1 * (atan((MouseY - PlayerTurret.GetPosition().y)/(MouseX - PlayerTurret.GetPosition().x)))*(180/3.14) + 270 + 180);
        }
        if ((PlayerTurret.GetPosition().y -MouseY) > 0 and (PlayerTurret.GetPosition().x-MouseX) < 0){ //Has Positive Num and Negative Denom
            PlayerTurret.SetRotation( -1 * (atan((MouseY - PlayerTurret.GetPosition().y)/(MouseX - PlayerTurret.GetPosition().x))) *(180/3.14) + 90 + 180);
        }
        if ((PlayerTurret.GetPosition().y -MouseY) < 0 and (PlayerTurret.GetPosition().x-MouseX) > 0){ // has Negative Num and Positive Denome
            PlayerTurret.SetRotation( -1 * (atan((MouseY - PlayerTurret.GetPosition().y)/(MouseX - PlayerTurret.GetPosition().x))) *(180/3.14) + 270 + 180);
        }
        if ((PlayerTurret.GetPosition().y -MouseY) < 0 and (PlayerTurret.GetPosition().x-MouseX) < 0){ // Doesn't Not have double negatives
            PlayerTurret.SetRotation( ( -1 * (atan((MouseY - PlayerTurret.GetPosition().y)/(MouseX - PlayerTurret.GetPosition().x)))*(180/3.14)) + 90 + 180);
        }


The Tank and Missile Moving Code
Code: [Select]

//DecimalCos and DecimalSin  calculate the the Sin and Cos in decimals
       if (App.GetInput().IsKeyDown(sf::Key::D))  PlayerTank.Rotate(-100.0 * ElapsedTime);
        if (App.GetInput().IsKeyDown(sf::Key::A)) PlayerTank.Rotate( 100.0 * ElapsedTime );
        if (App.GetInput().IsKeyDown(sf::Key::W)){
            PlayerRotation = -1* PlayerTank.GetRotation() + 180 + 90;
            PlayerTank.Move(( DecimalCos(PlayerRotation)) * 5 * ElapsedTime, (DecimalSin(PlayerRotation)) * 5 * ElapsedTime);
        }
        if (App.GetInput().IsKeyDown(sf::Key::S)){
            PlayerRotation = -1* PlayerTank.GetRotation() + 180 + 90;
            PlayerTank.Move(( DecimalCos(PlayerRotation)) * 5 * ElapsedTime * -1, (DecimalSin(PlayerRotation)) * 5 * ElapsedTime * -1);
        }


            if (App.GetInput().IsKeyDown(sf::Key::Space) ){//and SystemTime + .0001 < App.GetFrameTime()
            MissileSprite.SetX(PlayerTurret.GetPosition().x);
            MissileSprite.SetY(PlayerTurret.GetPosition().y);
            MissileSprite.Rotate(PlayerTurret.GetRotation());
            SystemTime = App.GetFrameTime();
            }
            MissileSpriteRotation = -1* MissileSprite.GetRotation() + 180 + 90;
            MissileSprite.Move(( DecimalCos(MissileSpriteRotation)) * 10 * ElapsedTime, (DecimalSin(MissileSpriteRotation)) * 10 * ElapsedTime);


If thats not enough info tell me and I can get more

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Rotation changes every time A key is pressed
« Reply #1 on: November 09, 2009, 08:15:37 am »
Hi

First, you should remove all these useless "if (negative/positive)" tests and use atan2 rather than atan ;)
Laurent Gomila - SFML developer

Frostbite

  • Newbie
  • *
  • Posts: 17
    • View Profile
Rotation changes every time A key is pressed
« Reply #2 on: November 09, 2009, 08:28:19 pm »
I'm trying to figure it out, but how do you use it? I have yet to come across this operator in math =P

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Rotation changes every time A key is pressed
« Reply #3 on: November 09, 2009, 08:37:04 pm »
It's the same as atan (it's not a new mathematical operator), except that it takes X and Y separately so that only one angle is possible for every combination of X and Y (whereas with one argument, X/Y is equal to -X/-Y although it is not the same angle).

Be careful: if I remember correctly, it takes first Y and then X.
Laurent Gomila - SFML developer

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Rotation changes every time A key is pressed
« Reply #4 on: November 09, 2009, 08:38:40 pm »
You may want to read this : http://www.dinkumware.com/manuals/?manual=compleat&Search=atan2&page=math.html#atan2 .

why everyone writes at the same time as me today?  :P
SFML / OS X developer

Frostbite

  • Newbie
  • *
  • Posts: 17
    • View Profile
Rotation changes every time A key is pressed
« Reply #5 on: November 09, 2009, 08:43:07 pm »
Thanks a ton, that simplified my code a lot =)

But I still have the problem of the mouse jumping all over the place (or at least Im pretty sure thats it) whenever a button is pressed Mouse or keyboard.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Rotation changes every time A key is pressed
« Reply #6 on: November 09, 2009, 08:44:14 pm »
Now that your code is much cleaner, can you post the new version?
Laurent Gomila - SFML developer

Frostbite

  • Newbie
  • *
  • Posts: 17
    • View Profile
Rotation changes every time A key is pressed
« Reply #7 on: November 09, 2009, 08:52:15 pm »
Here, this is the entire thing now

I hope its not too confusing
sorry about this =(


Code: [Select]

#include <iostream>

using namespace std;


////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>


////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////

float DecimalCos(float Num){
    return (cos(Num*(3.14/180)))*(180/3.14);
}
float DecimalSin(float Num){
    return (sin(Num*(3.14/180)))*(180/3.14);
}

int main()
{
    // Create the main rendering window
    sf::RenderWindow App(sf::VideoMode(1200, 600, 32), "SFML Graphics");
    int MouseX,MouseY;
    // Load the sprite image from a file
    sf::Image Image;
    sf::Image turret;
    sf::Image Missiletastic;
    sf::Image Kursor;
    float MissileSpriteRotation;
    if (!Image.LoadFromFile("Tank.png"))
        return EXIT_FAILURE;
    if (!turret.LoadFromFile("Turret.png"))
        return EXIT_FAILURE;
    if (!Missiletastic.LoadFromFile("Missile.png"))
        return EXIT_FAILURE;
    if (!Kursor.LoadFromFile("Cursor.png"))
        return EXIT_FAILURE;

    // Create the sprite
    sf::Sprite PlayerTank(Image);
    sf::Sprite PlayerTurret(turret);
    App.ShowMouseCursor(0);
    // Change its properties

    PlayerTank.SetPosition(200.f, 100.f);
    PlayerTank.SetCenter(25.f,27.f);
    PlayerTurret.SetCenter(25.f,25.f);

    float PlayerX;
    float PlayerY;
    float PlayerRotation;
    float SystemTime = App.GetFrameTime();
    sf::Event Mouse;

    sf::Sprite MissileSprite(Missiletastic);
    MissileSprite.SetCenter(5.f,8.f);
    sf::Sprite Cursor(Kursor);
    Cursor.SetCenter(25.f,25.f);
        sf::Event Event;

    // Start game loop
    while (App.IsOpened())
    {
        // Process events

        while (App.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }

        // Get elapsed time
        float ElapsedTime = App.GetFrameTime();
        MouseY = Event.MouseMove.Y;
        MouseX = Event.MouseMove.X;

       
        //Moves the turret along with the tank and moves the cursor
        PlayerTurret.SetX(PlayerTank.GetPosition().x);
        PlayerTurret.SetY(PlayerTank.GetPosition().y);
        Cursor.SetX(MouseX);
        Cursor.SetY(MouseY);
        // Moves the tank
        if (App.GetInput().IsKeyDown(sf::Key::D))  PlayerTank.Rotate(-100.0 * ElapsedTime);
        if (App.GetInput().IsKeyDown(sf::Key::A)) PlayerTank.Rotate( 100.0 * ElapsedTime );
        if (App.GetInput().IsKeyDown(sf::Key::W)){
            PlayerRotation = -1* PlayerTank.GetRotation() + 180 + 90;
            PlayerTank.Move(( DecimalCos(PlayerRotation)) * 5 * ElapsedTime, (DecimalSin(PlayerRotation)) * 5 * ElapsedTime);
        }
        if (App.GetInput().IsKeyDown(sf::Key::S)){
            PlayerRotation = -1* PlayerTank.GetRotation() + 180 + 90;
            PlayerTank.Move(( DecimalCos(PlayerRotation)) * 5 * ElapsedTime * -1, (DecimalSin(PlayerRotation)) * 5 * ElapsedTime * -1);
        }

            //fires the missile
            if (App.GetInput().IsKeyDown(sf::Key::Space) ){//and SystemTime + .0001 < App.GetFrameTime()
            MissileSprite.SetX(PlayerTurret.GetPosition().x);
            MissileSprite.SetY(PlayerTurret.GetPosition().y);
            MissileSprite.Rotate(PlayerTurret.GetRotation());
            SystemTime = App.GetFrameTime();
            }

             MissileSpriteRotation = -1* MissileSprite.GetRotation() + 180 + 90;
            MissileSprite.Move(( DecimalCos(MissileSpriteRotation)) * 10 * ElapsedTime, (DecimalSin(MissileSpriteRotation)) * 10 * ElapsedTime);

        //Sets the players turret rotation
        PlayerTurret.SetRotation (-1*static_cast<float>(atan2(static_cast<double>(MouseY - PlayerTurret.GetPosition().y),static_cast<double>(MouseX - PlayerTurret.GetPosition().x))* 180 / 3.14) - 90);


        // Clear screen
        App.Clear();

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

        App.Draw(PlayerTank);
        App.Draw(PlayerTurret);
        App.Draw(Cursor);


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

    return EXIT_SUCCESS;
}

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Rotation changes every time A key is pressed
« Reply #8 on: November 09, 2009, 10:10:13 pm »
Code: [Select]
MouseY = Event.MouseMove.Y;
        MouseX = Event.MouseMove.X;

Here it is.

You can access to these variables only if the event type is about mouse (see doc/tutorial).

The fact is that SFML events are bases on union (see source/google). So when a key event occurs the variables are not the same and accessing to mouse related variables may give strange value.
SFML / OS X developer

Frostbite

  • Newbie
  • *
  • Posts: 17
    • View Profile
Rotation changes every time A key is pressed
« Reply #9 on: November 09, 2009, 10:41:11 pm »
Hooray!!! Thanks to both of you =) I couldn't have done it without both of you. The darn things finaly working as it should. Thanks tons for your great patience and insight =)