SFML community forums
Help => Graphics => Topic started by: Frostbite 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
//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
//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
-
Hi
First, you should remove all these useless "if (negative/positive)" tests and use atan2 rather than atan ;)
-
I'm trying to figure it out, but how do you use it? I have yet to come across this operator in math =P
-
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.
-
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
-
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.
-
Now that your code is much cleaner, can you post the new version?
-
Here, this is the entire thing now
I hope its not too confusing
sorry about this =(
#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;
}
-
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.
-
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 =)