Using Trig To Calculate dx,dy From Angle (bullet shot from gun)

112 Views Asked by At

For a school project on CMU CS I am trying to use trig to calculate the speed/velocity for the dx and dy in order to make it move in the angle that the gun was pointing when shot. The code below is just related to the bullet and gun, thanks for your help! The grid goes from the top right(0) to bottom left (400.) (edit: forgot to mention game is top-down)

import math

player.gunAngle = angleTo(player.centerX,player.centerY,mouseX,mouseY) 
player.rotateAngle = player.gunAngle

-

bullet = Circle(gun.centerX,gun.centerY,4,rotateAngle = player.gunAngle)
bullet.angle = player.gunAngle
bullet.spawnX = gun.centerX
bullet.spawnY = gun.centerY

bullet.angle = math.radians(bullet.angle)

bullet.dx = 3 * math.cos(bullet.angle)
bullet.dy = 3 * math.sin(bullet.angle)

-

for i in bullets.children:
i.centerX += rounded(i.dx)
i.centerY -= rounded(i.dy)

When I shoot it, I think I did something wrong with the calculations but it goes it the wrong direction, even if I shoot multiple times in the same spot they all shoot in the same wrong direction, and im not sure what is wrong with the calculations so I don't know how to fix it. The grid goes from the top right(0) to bottom left (400.)

2

There are 2 best solutions below

0
Pete Kirkham On BEST ANSWER

If you don't need the angle for something else, you can just use the vector components and convert the difference between player and mouse positions into a unit vector, then scale than vector's components by however fast you want the bullet to move:

To get a unit vector you divide the components by the euclidean magnitude:

gun_dx = mouseX-player.centerX
gun_dy = mouseY-player.centerY
gun_mag = math.sqrt(gun_dx*gun_dx + gun_dy*gun_dy)
bullet.dx = bullet_speed * gun_dx / gun_mag
bullet.dy = bullet_speed * gun_dy / gun_mag

You will need to add a check for division by zero magnitude, either here or before firing the gun on mouse event.

0
Blindman67 On

Good performance habits.

  • Reduce number of divisions whenever possible.

  • Prefer branchless code whenever possible. ie avoid conditional statements.

Appling good habits

A slight improvement on the given answer removes some multiplication and divisions. The two divisions become multiplications with the division being done once by calculating the inverse distance to mouse normalized to the bullet speed.

To avoid a divide by zero or a conditional branch, add a tiny fraction (of smallest visible unit eg pixel size) to the mag. It's so small it has no visible effect on the bullet speed.

gun_dx = mouseX-player.centerX
gun_dy = mouseY-player.centerY
gun_delta_scale = bullet_speed / (math.sqrt(gun_dx * gun_dx + gun_dy * gun_dy) + 0.0001)
bullet.dx = gun_dx * gun_delta_scale
bullet.dy = gun_dy * gun_delta_scale

Totally insignificant if only done once per frame. But it can quickly become worthwhile if you have many things needing normalized vectors to coordinates.