Moving a sprite

Started by
17 comments, last by kiznore 19 years, 12 months ago
const double UnitSpeed = 1.0;void ThrustShip(int speed){    int NewAngle;  //used for calculating percentages    bool XNeg, YNeg;    double xdir, ydir;        XNeg = YNeg = false;    //find out what quad the angle is in    if (angle >= 90 && angle < 180)    {         XNeg = true;         NewAngle = 90 - angle;    }    else if (angle >= 180 && angle < 270)    {         XNeg = true;         YNeg = true;         NewAngle = angle - 180;    }    else if (angle >= 270 && angle < 360)    {         YNeg = true;         NewAngle = 360 - angle;    }    //calculate the precentages angle will always be in favour of the x direction.    xdir = UnitSpeed * (NewAngle / 90);    ydir = UnitSpeed * (1 - NewAngle / 90);    //check to see if we are negating    if (XNeg)         xdir = -xdir;    if (YNeg)         ydir = -ydir;    ShipPosX += xdir * speed;    ShipPosY += ydir * speed;}


I believe this is correct off the top of my head. Try it out to see if it works and let me know. It also saves you from making calls to sin and cos which can be expensive if called enough times. If you want to have the motion constant then you need to have the unit speed like I want it to move one unit when I thrust then multiply that by the speed. If someone sees a mistake with my logic please point it out.

Thanks,

Richard
Advertisement
Richard, if I''m not wrong, your sin/cos replacement is not correct, since sin( 0 ) -> sin( 90 ) ( degrees ) does not interpolate liniary.

you tried to map the angle''s raport with respect to it''s quadran and use it as a linear interpolation time parameter, ranging from 0 to 1.

I do belive that this will transform the trygonometric circle into a 45 degrees rotated square around the origin which will result in unnatural movement

so, you''ll have to use sin() and cos(). if you want to make it faster, use lookup tables. one more hint : recalc sin and cos ONLY when angleShip is changing.

hope it helps,

benishor

---
novocaine thru yer veinz
---novocaine thru yer veinz
The original code without the if looks right. You don''t need that if. Just expriment with the sign until it works which will depend on your handedness (there are only 4 possiblities).

Mark
Sound Effects For Game Developers
http://www.indiesfx.co.uk
Flatspace is here: The ultimate space adventure
http://www.lostinflatspace.com
quote:Original post by benishor
Richard, if I''m not wrong, your sin/cos replacement is not correct, since sin( 0 ) -> sin( 90 ) ( degrees ) does not interpolate liniary.

you tried to map the angle''s raport with respect to it''s quadran and use it as a linear interpolation time parameter, ranging from 0 to 1.

I do belive that this will transform the trygonometric circle into a 45 degrees rotated square around the origin which will result in unnatural movement

so, you''ll have to use sin() and cos(). if you want to make it faster, use lookup tables. one more hint : recalc sin and cos ONLY when angleShip is changing.

hope it helps,

benishor

---
novocaine thru yer veinz



I really don''t think that my code is wrong as it calculates the amount of movement in the x direction and y direction based on the angle percentage. say your angle was 30 degrees:

x direction percentage: 30 / 90 = 0.3333...
y direction percentage: what is left over is 0.6666...
so if you have a velocity of 1 unit you just multiply the velocity by the percentage in the x direction and the y direction to get the new (x, y) coordinates. Again correct me if I am wrong but I do believe that I am not. I just tried to keep it as simple as possible.

Thanks,

Richard
Hi Richard,

sadly, I have to say you are wrong. I took some minutes to write a small php demo of both ideas. here''s the link :

http://benny.kappa.ro/sprive_movement/

p.s. even if you got the neg boolean variables wrong it still wouldn''t work as intended : you''re taking a value for xdir and then take the y dir value by substracting it from 1. the ship, though, will move on the distance represented by the hypotenuse. THAT distance has to be 1, not it''s projection on both axis added. thus, pythagora theorem brings us to : 1 * 1 = x_dir * x_dir + y_dir * y_dir, not 1 = x_dir + y_dir.

hope it helps,

benishor


---
novocaine thru yer veinz
---novocaine thru yer veinz
sorry, the link was http://benny.kappa.ro/sprite_movement/
---novocaine thru yer veinz
quote:Original post by benishor
Hi Richard,

sadly, I have to say you are wrong. I took some minutes to write a small php demo of both ideas. here's the link :

http://benny.kappa.ro/sprive_movement/

p.s. even if you got the neg boolean variables wrong it still wouldn't work as intended : you're taking a value for xdir and then take the y dir value by substracting it from 1. the ship, though, will move on the distance represented by the hypotenuse. THAT distance has to be 1, not it's projection on both axis added. thus, pythagora theorem brings us to : 1 * 1 = x_dir * x_dir + y_dir * y_dir, not 1 = x_dir + y_dir.

hope it helps,

benishor


---
novocaine thru yer veinz


Good Stuff. It is a good approximation if XDir and YDir were switched around ie:

XDir = UnitSpeed * (1 - NewAngle / 90)
YDir = UnitSpeed * (NewAngle / 90)

Also I think I made a mistake here

quote:
if (angle >= 90 && angle < 180)
{
XNeg = true;
NewAngle = 90 - angle;
}


I think I should have put 180 - angle not 90 - angle.

Thanks for pointing out my error but would it really look the movement really look awckward if it were implemented this way? [EDIT 2]I don't think that it would matter too much dealing with small velocities but it would make a huge deal with larger values. [/EDIT 2]

[EDIT]
But if we are dealing with exact values then you are 100% absolutley right. Don't think that I am arguing that I am right anymore . This is a link to the file containing my code changes. The link will be fixed later as I am in the process of installing my new server.
[/EDIT]

thanks,

Richard

[edited by - BigR on April 20, 2004 7:34:24 PM]

[edited by - BigR on April 20, 2004 9:55:15 PM]

[edited by - BigR on April 21, 2004 11:05:14 AM]
You don't need those ifs and elses.
const double DEG_TO_RAD = 0.01745; // PI / 180void ship::thrust( float speed ){   double rad_angle = angle * DEG_TO_RAD;   velx = cos(rad_angle) * speed;   vely = sin(rad_angle) * speed;   xpos += velx;   ypos += vely;}  

Will work just fine.

Oh, btw, use vectors, not std::vectors, but math/physics vectors. Much cleaner.
struct vector{   float i;   float j;};void ship::rotate( float angle, float speed ){   double rad_angle = angle * DEG_TO_RAD;   movement_vector.i = cos(rad_angle) * speed;   movement_vector.j = sin(rad_angle) * speed;}void ship::thrust(){   xpos += movement_vector.i;   ypos += movement_vector.j;}  


[edited by - alnite on April 21, 2004 2:42:51 PM]
quote:Original post by BigR
I don't think that it would matter too much dealing with small velocities but it would make a huge deal with larger values.



I'm afraid it does because in that function we're actually calculating the direction vector of the ship ( vector which by the way would need to be normalised in your code so that it will have the length of one ). think of it this way : those xdir and ydir values get added to the ship's position each frame, establishing the trajectory of the ship. if those xdir and ydir values aren't accurate, you will get unaccurate trajectories for different angle values.

alnite's code is correct. also remember to calculate the direction vector only when the angle changes.

regards,

benishor
---
novocaine thru yer veinz

[edited by - benishor on April 22, 2004 4:21:26 AM]
---novocaine thru yer veinz

This topic is closed to new replies.

Advertisement