views:

98

answers:

2

Hello all math masters, I got a problem for you:

I have a 2D game (top down), and I would like to make the character escape from a shot, but not just walk away from the shot (I mean, don't be pushed by the shot), I want it to have a good dodging skills.

The variables are:

  • shotX - shot x position
  • shotY - shot y position
  • shotSpeedX - shot x speed
  • shotSpeedY - shot x speed
  • charX - character x position
  • charY - character y position
  • keyLeft - Set to true to make the character press the to left key
  • keyRight - Set to true to make the character press the to right key
  • keyUp - Set to true to make the character press the to up key
  • keyDown - Set to true to make the character press the down key

I can understand the following languages:

  • C/C++
  • Java
  • Actionscript 2/3
  • Javascript

I got this code (Actionscript 3), but sometimes it doesn't work:

var escapeToLeft:Boolean = false;
var r:Number = Math.atan2(0 - shotSpeedY, 0 - shotSpeedX)
var angle:Number = Math.atan2(charY - (shotY + shotSpeedY), charX - (shotX + shotSpeedX));
var b:Number = diepix.fixRotation(r-angle); // This function make the number between -180 and 180
if(b<0) {
 escapeToLeft = true;
}
r += (escapeToLeft?1:0 - 1) * Math.PI / 2;
var cx:Number = Math.cos(r);
var cy:Number = Math.sin(r);
if(cx < 0.0) {
 keyLeft = true;
}else {
 keyRight = true;
}
if(cy < 0.0) {
 keyUp = true;
}else {
 keyDown = true;
}
+2  A: 

Some observations:

  • Optimal dodging probably involves moving at a 90 degree angle from the bullets direction. That way, you get out of harms way the quickest.
  • If you do err, you want to err in the direction of the bullet, as that buys you time.
  • you can calculate 90 degrees to bullet direction with the scalar product
  • find the closest compass direction to the calculated optimal angle (4 possible answers)
    • are you allowed to go up and left at the same time? Now you have 8 possible answers to a bullet
  • bonus points for dodging in optimal direction according to second point

The scalar product of two vectors (ax, ay) and (bx, by) is ax * bx + ay * by. This is 0 if they are orthogonal (90 degrees). So, given the bullet (ax, ay), find a direction (bx, by) to run that has a scalar product of 0:

ax * bx must equal ay * by, so  (bx, by) = (-ax, -ay)

Now to find the closest point on the compass for (bx, by), the direction you would like to run to. You can probably figure out the technique from the answer to a question of mine here on SO: http://stackoverflow.com/questions/1437790/how-to-snap-a-directional-2d-vector-to-a-compass-n-ne-e-se-s-sw-w-nw (note, thow, that I was using a wonky coordinate system there...)

If you have only 4 compass directions, your easiest path is to take:

 max(abs(bx), abs(by))

The bigger vector component will show you the general direction to go - for

  • bx positive: right
  • bx negative: left
  • by positive: up (unless (0, 0) is top left with y positive in bottom left...)
  • by negative: down

I guess you should be able to come up with the rest on your own - otherwise, good luck on writing your own game!

Daren Thomas
You should write the first example using a programming language >_>
M28
A: 

I am not following what the line

var angle:Number = Math.atan2(charY - (shotY + shotSpeedY), charX - (shotX + shotSpeedX));

is supposed to be doing. The vector ( charY - shotY, charX - shotX ) would be the radius vector pointing from the location of the shot to the location of the character. But what do you have when you subtract a speed vector from that, as you are doing in this line?

It seems to me that what you need to do is:

  1. Calculate the radius vector (rY, rX) where rY = shotY - charY; rX = xhotX - charX

  2. Calculate the optimal direction of jump, if the character weren't constrained to a compass point. Start with a vector rotated 90 degrees from the shot-character radius vector. Say vJump = ( rX, -rY ). (I think Daren has this calculation slightly wrong--you are transposing the two coordinates, and reversing one of their signs.) The character should either wants to jump in the direction of vJump or the direction of -vJump. To know which, take the scalar product of vJump with (shotSpeedY, shotSpeedX). If this is positive, then the character is jumping towards the bullet, which you don't want, obviously, so reverse the sign of both components of vJump in this case.

  3. Jump in the permissible direction that is closest to vJump. In the code you listed, you are constrained to jump in one of the diagonal directions--you will never jump in one of the cardinal directions. This may in fact be the mathematically optimal solution, since the diagonal jumps are probably longer than the cardinal jumps by a factor of 1.414.

If your jumps are actually equal distance, however, or if you just don't like how it looks if the character always jumps diagonally, you can test each of the eight cardinal and intermediate directions by calculating the scalar product between vJump and each of the eight direction vectors (0,1), (0.7071,0.7071), (1,0), (0.7071,-0.7071), etc. Take the direction that gives you the biggest positive scalar product. Given the patterns present, with some clever programming you can do this in fewer than eight tests.

Note that this algorithm avoids any math more complicated than addition and multiplication, so will likely have much better performance than something that requires trig functions.

Dan Menes
That line consider where the shot will be in the next frame :)
M28