Welcome, Guest. Please login or register.

Author Topic: Moving a sprite in a specified angle  (Read 6465 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Moving a sprite in a specified angle
« on: August 27, 2007, 08:03:16 PM »
In C++/SDL, how can I tell a sprite to move in a specific angle, in degrees? Currently I only know how to move it a certain number of pixels on the x or y axis, which doesn't really help when I want to move it at an angle of, say, 30 degrees.

Note this is moving in a straight line at that angle, not rotating the sprite.

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Moving a sprite in a specified angle
« Reply #1 on: August 27, 2007, 08:42:51 PM »
Two possible approaches:

1) Use component velocities (velocities in X and Y axes). You can work this out from taking the sine and cosine of the angle and using them to factor your sprite's overall speed into the vX and vY components (which will allow you to position the sprite at any time along the trajectory).

2) Use a bresenham style line drawing algorithm to calculate your sprite position over successive iterations. This is only really useful if your sprite moves a fixed distance every frame.

Since you know how to move the sprite in X and Y, you could use either of the above. I'd go for (1) myself.
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #2 on: August 27, 2007, 09:14:00 PM »
Thanks Karlos! Here's what I've knocked together in the move() function:

if ( x <= 20 ) if ( xVel < 0 ) xVel = -xVel;
if ( y <= 20 ) if ( yVel < 0 ) yVel = -yVel;
       
if ( x >= 620 ) if ( xVel > 0 ) xVel = -xVel;
if ( y >= 440 ) if ( yVel > 0 ) yVel = -yVel;

x+=xVel*cos(angle);
y+=yVel*sin(angle);



This does work, and makes the sprite move in the angle specified by int angle, and bounce off the edges of the screen if it reaches the edge of the playfield. However, if I have lots of the same sprite (a vector of the same class) lots of the sprites seem to go off the edge of the screen instead of bouncing back in to the playfield :-?
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Moving a sprite in a specified angle
« Reply #3 on: August 27, 2007, 09:33:07 PM »
Strange. You're not using threads or anything like that are you?

Incidentally, I had something like this in mind for the components:

vX = sprite->speed*cos(sprite->angle);
vY = sprite->speed*sin(sprite->angle);

ie, you only have speed and angle and calculate vX amd vY as required.

I'd probably go for a basic lookup table or something for the sin/cos too if my angle is an integer with a small enough range. Or cache the cos/sin angle values and recalculate only when angle changes. Or both :lol:
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #4 on: August 27, 2007, 09:50:13 PM »
No threads. It just runs through the vector of sprites and moves/checks/recalculates/shows them one at a time. I'm wondering if my variables are declared as public when they should be private, or vice versa? I'm not sure I fully understand the difference, but if a variable were public might that mean the velocity for all of the sprites was being adjusted the same instead of them each having their own velocity?

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #5 on: August 27, 2007, 10:06:40 PM »
Looks like I had some of the < and > signs the wrong way round. Also I expanded the nested if statements out, and it seems to be working now.

    if ( x <= 20 )
    {
         if ( xVel > 0 )
         {
              xVel = -xVel;
         }
    }
    if ( y <= 20 )
    {
         if ( yVel < 0 )
         {
              yVel = -yVel;
         }
    }
    if ( x >= 620 )
    {
         if ( xVel < 0 )
         {
              xVel = -xVel;
         }
    }
    if ( y >= 440 )
    {
         if ( yVel > 0 )
         {
              yVel = -yVel;
         }
    }

    x+=xVel*cos(angle);
    y+=yVel*sin(angle);



Not sure how this is different to your last example Karlos, but at least it works now :-D

Cheers!

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #6 on: August 27, 2007, 10:10:51 PM »
Hmmm, I borked it again :lol: I found out what is causing it, but I don't know why.

When the enemy is created its initial angle is set. If I set this to, e.g., 40 degrees, then the enemies all stay within the playfield. If I set it to rand() % 350 + 10 (should be an angle betwen 10 and 350 degrees) then they start flying off the screen :-?

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Moving a sprite in a specified angle
« Reply #7 on: August 27, 2007, 10:13:23 PM »
Right. I was looking at the if statements and was pretty sure something weird must be happening, but as it worked in the single sprite case and failed in the many sprite case, simple boundary detection didn't seem the obvious cause ;-)
 
With respect to the calculation stuff, it's different in that you have have already separated the velocities into xVel and yVel which you then multiply by the corresponding component factor (cos(angle) / sin(angle) in the respective direction.

Or in English, you already have separate xVel / yVel which you then multiply by the cos/sin, which is quite different from having single speed which is then used to derive xVel / yVel.

In other words, I'm saying:

xVel = speed*cos(angle)

where as you have

xVel*cos(angle)

...what was xVel initialised with?
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #8 on: August 27, 2007, 10:22:08 PM »
OIC. xVel and yVel are initialised with enemyspeed, which is in turn initialised at the top of my code, just to make it easy to tweak sprite speeds and have the changes cascade through the code. xVel and yVel end up (currently) with a value of 3.

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Moving a sprite in a specified angle
« Reply #9 on: August 27, 2007, 10:32:12 PM »
Right.

I'd suggest it's more numerically correct to stick with either totally separate 'vectorized' style xVel / yVel (ie no angle) or have speed and angle and derive xVel/yVel from the speed and angle.

In the latter case, the component velocities xVel and yVel, at any time, will always be:

xVel = speed*cos(angle);
yVel = speed*sin(angle);

which you derive just as you need them. For example, you can say, at any time:

sprite->posX += sprite->speed*cos(sprite->angle);
sprite->posY += sprite->speed*sin(sprite->angle);

to reposition the sprite. As an optimisation, if angle doesn't vary much, I'd consider storing the result of cos(angle) and sin(angle), but not xVel/yVel, eg:

sprite->scaleVelX = cos(sprite->angle);
sprite->scaleVelY = sin(sprite->angle);

...

sprite->posX += sprite->speed*sprite->scaleVelX;
sprite->posY += sprite->speed*sprite->scaleVelY;

I'm obviously not taking edge rebound into consideration here, but you get the general idea.


Having just one speed/angle pair per sprite makes things a bit easier to understand. It also allows you to alter the speed and angle (to simulate acceleration etc) with relative ease. The correct coordinates will always be found by the expressions above for any given value of speed/angle.

Also, unless your sprites always all move with the same speed, you'd want to make the speed/angle properties part of the sprite structure.
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #10 on: August 27, 2007, 10:42:06 PM »
The reason for having two separate velocity variables (xVel and yVel) is for the edge rebound code. If the sprite hits the top or bottom then yVel is made negative, and if it hits the left or right then xVel is made negative.

If I only use one variable for the velocity then I can't do this, since changing the velocity variable would affect the direction on both the X and Y axes.

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Moving a sprite in a specified angle
« Reply #11 on: August 27, 2007, 10:58:52 PM »
True, but remember, you could alter the angle instead.
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #12 on: August 27, 2007, 11:01:58 PM »
The problem there is that sometimes the sprite crosses a couple of pixels over the edge of the playfield boundary. This is not a problem aesthetically, but it does mean that it keeps having its angle reversed over and over again so gets stuck. At least if I check whether the velocity is going to take the sprite further out of the playfield before changing it then I can stop this from happening.

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Moving a sprite in a specified angle
« Reply #13 on: August 27, 2007, 11:24:46 PM »
Hey, all is fair in love, warfare and game physics ;-)

I remember doing trajectory stuff for objects bouncing over a polygon mesh. Not much fun at all :lol:
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: Moving a sprite in a specified angle
« Reply #14 on: August 27, 2007, 11:29:13 PM »
Ok this works:

    if ( x <= 20 )
    {
        x=21;
        angle=(180-angle);
    }
    if ( y <= 20 )
    {
        y=21;
        angle=(180-angle)-180;
    }
    if ( x >= 620 )
    {
        x=619;
        angle=(180-angle);
    }
    if ( y >= 440 )
    {
        y=439;
        angle=(180-angle)-180;
    }

    x+=pinwheelspeed*cos(angle);
    y+=pinwheelspeed*sin(angle);




But every so often the sprite hits the wall at an angle which means it can't escape for some reason. It's probably due to the fact that certain angle can't be represented precisely at such a low resolution. I think it might be better to have tables of x and y velocities to give a variety of "angles" rather than trying to calculate actual angles.

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10