Advertisement

Asteroids movement AI

Started by April 13, 2008 06:46 PM
6 comments, last by brandonman 16 years, 9 months ago
Hey, I'm currently working on a 2D shooter, with asteroids style movement. Right now, I have the player moving and the enemies just moving right to the player. I would like to be using headings, not just adding and subtracting x and y values, but instead turning and such, as the player does. I've come up with only 1 thought so far, but I am not sure how efficiant it might be, or if it would even work. OK, so the enemy ship has a vector of movement. Here's how I might plan to do this: 1) Get the movement vector 2) create 2 variables, x and y 3) Take these two points and move them across the view vector 4) If they collide with the player at any time in the loop, continue on the view vector and break from the loop, other wise, add 1 degree to the rotation Would this work well, or would it be to 'dumb'? Is this to inefficiant? If my explanation isn't clear, just let me know. Help appreciated, thanks in advance. -Brandonman
Your explanation is unclear. What is this 'view vector' you have mentioned?

The typical approach to a problem like this would involve:

  • computing the angle to the target from the current heading of the source object.

  • rotating so as to reduce this angle to zero

  • ...and usually constraining rotation to a fixed rate (so a fixed number of degrees per second) so as to make things look more realistic and to give the player a chance


  • Regards,

    Timkin
    Advertisement
    OK, this view vector is actually the vector for movement, ie: To go straight up the first value in the array might be '0' in the first value for 0 speed on x axis, and '1' in the second value to have speed on the Y axis.
    Speed and Heading is actually a different kind of coordinate system from cartesian x,y grid -- called polar coordinates.

    Just keep track of the facing of the ship, relative to your x,y axes. For instance, you could use an angle measured in degrees of counter-clockwise rotation away from facing in the same direction as the positive y axis. You can use Radians instead of degrees, if you're comfortable with them, or rads, or even a unit of measure of your own design; for instance you might just have six angles of facing for a hex map.

    Once you have a measure of which way the ship is facing, compared to the x/y axis of the grid, it is then possible to write a simple function that takes Heading and Speed (polar coordinates), and returns an x,y vector (cartesian coordinates).
    --"I'm not at home right now, but" = lights on, but no ones home
    I think you want a steering behavior.

    It's a simple idea that made Craig Reynolds really famous:
    http://www.red3d.com/cwr/steer/

    In your case, I'd do a steering behavior something like this:

    Let 'theta' be the angle of the AI ship's heading, and let 'THETA' be the angle of the vector from the AI ship to the target (you can get this by calling 'atan2' with the differences in the x and y coordinates of the two ships). Then, every frame, just adjust theta as,

    theta_new = (1-k)*theta + k*THETA

    where k is some number between zero and one. Or, you may want to clamp angular velocities:

    omega = k*(THETA-theta)if(omega > omegaMAX) {omega = omegaMAX;}else if(omega < omegaMIN) {omega = omegaMIN;}theta = theta + omega*deltaT;


    I'd do something like one of these two (very similar) things.
    OK, I messed with this all day, and got it implemented, pretty much. Now I just need a little inspiration for wingman AI.
    Advertisement
    Quote:
    Original post by brandonman
    OK, I messed with this all day, and got it implemented, pretty much. Now I just need a little inspiration for wingman AI.


    So you want an AI "wingman" to follow the player around and help him out?

    That sounds like another place to use a steering behavior! :-) Specifically: flocking. The player's ship can act as the leader, and the "wingman" (or wingmen!) can act as a follower. See the Craig Reynolds link I gave earlier; he made a name for himself by solving exactly these problems.
    I tried implementing flocking following this pseudo-code: HERE
    It has not worked out well. I currently get just the boids moving diagonally up, all of them, and nothing else happening. Here is my relevant code (Yes, a little messy with some globals, but just a rough implementation I tried)

    int formation=1;float rx;float ry;float rc;float pv[2];float pvj[2];float cr[2];void rule1(int b){   for(int i=0; i<10; i++)   {      if (i!=b)      {         pv[0]+=wing.x;         pv[1]+=wing.y;      }   pv[0]=pv[1]/10; //# of wingmen minus 1   pv[0]=pv[1]/10; //# of wingmen minus 1   rx=pv[0]-wing.x;   ry=pv[0]-wing.y;         }}void rule2(int b){   for(int i=0; i<10; i++)   {      if(i!=b)      {         if(wing.x-wing.x < 100 && wing.y-wing.y < 100)         {            cr[0]-=wing.x;            cr[1]-=wing.y;         }       }   }}void rule3(int b){   for(int i=0; i<10; i++)   {      if(b!=i)      {         pvj[0]+=wing.x;         pvj[1]+=wing.y;      }   }   pvj[0] = pvj[0]/1; //# of wing minus 1   pvj[1] = pvj[1]/1;}//................... for(int i=0; i<10; i++) {    if(formation==1)    {                          if(wing.x>=31)                {                   wing.x=-30.9;                }                if(wing.x<=-31)                {                   wing.x=30.9;                }                                if(wing.y>=31)                {                   wing.y=-30.9;                }                if(wing.y<=-31)                {                   wing.y=30.9;                }    float v1[2], v2[2], v3[2];    rule1(i);    rule2(i);    rule3(i);    v1[0]=rx/10;    v1[1]=ry/10;    v2[0]=cr[0]/10;    v2[1]=cr[1]/10;    v3[0]=pvj[0]/10;    v3[1]=pvj[1]/10;    wing.nv[0]+=v1[0]+v2[0]+v3[0];    wing.nv[1]+=v1[1]+v2[1]+v3[1];    wing.nv[0]+=rand()%10/15;    wing.nv[1]+=rand()%10/15;    wing.nv[0] = wing.nv[0]/10000;    wing.nv[1] = wing.nv[1]/10000;           wing.x+=wing.nv[0];       wing.y+=wing.nv[1];           glLoadIdentity();       glTranslatef(wing.x,wing.y,-50);       glBegin(GL_QUADS);       glColor3f(1.0f,1.0f,1.0f);       glVertex3f(0,0,0);       glVertex3f(1,0,0);       glVertex3f(1,-1,0);       glVertex3f(0,-1,0);       glEnd();       glLoadIdentity();      }}

    as you can see, I even tried adding a slight bit of randomness in there. Also, all the large divisions in the code are to help scale it down a bit, as these things are moving insanely fast.

    This topic is closed to new replies.

    Advertisement