Okay, I struggled a bit choosing wheter to put this on StackOverflow or here, Math. I concluded that it was actual math my problem and not "exactly" programming.

You see, I am making a 2d game, top-view where your character moves around and you can use your mouse as aim to shoot.

My problem is that I can't figure out the correct formula to get the "amount of pixels to move per frame". Let me explain:

The projectile being shot will not "stop" at the point your mouse clicked. Instead it will continuously move. Every frame, my projectile is supposed to "change X-position by {pixels}" and "change Y-position by {pixels}". I don't know how to figure out the {pixels} amount I need for both X and Y movements.

Here is some code. It is quite self-explanatory:

class PortalBall
  def initialize(sx,sy,dx,dy)     # sx,sy source points. dx,dy destination points
    @speed = 60
    x_per_frame = dx / @speed
    y_per_frame = dy / @speed
  def update
    @sprite.x += x_per_frame
    @sprite.y += y_per_frame

As you can see, my formula to figure out the amount of x pixels to move per frame is "destination X divided by speed". Speed is always 60 actually...

But this clearly isn't working properly. Can someone help me fixing my formula?

NOTE In this language, the higher on the screen means less Y position and the lower screen is more Y position. The top of the screen is Y 0, and the bottom is Y 600.

  • $\begingroup$ maybe you want to calculate the unit vector going into the direction of your bullet. Then every time step $t$ move $t$ times the unit vector. $\endgroup$ – Listing May 4 '11 at 6:02

First of all, whenever you have dx you actually want dx-sx and similarly for y. That's because you don't care about the absolute position of the destination, just the relative position of the source and the destination.

But your code is a little confused. Right now, if you increase @speed, the projectile moves slower. Also, if you increase the distance from the source to the destination, the projectile moves faster. I assume what you actually want is for the projectile to move at @speed regardless of the distance between the source and destination.

In that case, you want something like the following.

@speed = 60
dist = Sqrt[(dx-sx)^2+(dy-sy)^2]
x_per_frame = (dx-sx)/dist * @speed
y_per_frame = (dy-sy)/dist * @speed

(I'm not sure what square roots look like in your language.) The point of dividing by dist is to normalize the displacement vector so that it's a unit vector. You should probably also make some things floats as necessary to prevent rounding error.

  • $\begingroup$ Qiaochu: By "floats", maybe you meant "doubles" (i.e., double precision)? $\endgroup$ – J. M. is a poor mathematician May 4 '11 at 1:52
  • 1
    $\begingroup$ Sure. Whatever makes the gun not miss. $\endgroup$ – Qiaochu Yuan May 4 '11 at 1:55
  • $\begingroup$ Hmm... there are some scenarios the square root line throws me an error because the value I am giving it is negative. What do I do I that case? Also yeah, I want the bullet's speed to be the same no matter the distance between the mouse and the character, but I'm not sure of that either. $\endgroup$ – Zol Tun Kul May 6 '11 at 0:58
  • $\begingroup$ The value of $(dx-sx)^2 + (dy-sy)^2$ should never be negative. Are you sure you wrote that correctly? $\endgroup$ – Qiaochu Yuan May 6 '11 at 1:23
  • $\begingroup$ sx = 438, sy = 298, dx = 256, dy = 227. The value is -253. The code line is dist = Math.sqrt(((dx-sx)^2)+((dy-sy)^2)) $\endgroup$ – Zol Tun Kul May 6 '11 at 1:47

I will add to Qiaochu Yuan's answer that you'll probably want the (dx-sx) and (dy-sy) to be an absolute value. Otherwise you'll move in the opposite direction if (dx < sx) or if (dy < sy).

Here's my working example in Java:

float dist = (float) Math.sqrt( Math.pow((toX -fromX), 2) + Math.pow((toY -fromY), 2));

speedX = Math.abs(toX - fromX)/dist * speed ;
speedY = Math.abs(toY - fromY)/dist * speed ;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.