So I'm trying to test out a simple combat system in Pygame where the player can basically shoot a projectile towards an area based on where the mouse position is. So for example when he clicks on the top left of his screen, the projectile moves towards there at a steady speed. I've created a function that will move each bullet in a list, here's the function.
def move_bullet(bullet_pos, direction):
# TODO Make the speed of the bullet the same no matter which direction it's being fired at
bullet_pos[0] += direction[0]/50
bullet_pos[1] += direction[1]/50
bullet_rect = pygame.Rect((bullet_pos[0], bullet_pos[1]), BULLET_SIZE)
return bullet_rect
The direction is calculated by subtracting the mouse's vector position by the player's vector position when the mousebuttondown event is triggered.
However, I have noticed that the closer I get to the player/origin of the bullet, the slower the bullet goes because the direction vector is smaller so the speed is differs depending on your mouse's position. I've heard of Vector normalization but I have no idea how to implement it because after doing a bit of research, apparently you normalize Vectors by getting it's magnitude and dividing the X and Y values by the magnitude? I got it from Khan Academy but it doesn't actually work. And I'm pulling my hair out over this so I have no choice but to ask this question here.
TL; DR
How do I normalize a Vector in Pygame?
If you have to points
x1 = 10
y1 = 10
x2 = 100
y2 = 500
then you can calculate distance and use pygame.math.Vector2
import pygame
dx = x2-x1
dy = y2-y1
distance = pygame.math.Vector2(dx, dy)
or
v1 = pygame.math.Vector2(x1, y1)
v2 = pygame.math.Vector2(x2, y2)
distance = v2 - v1
and then you can normalize it
direction = distance.normalize()
It should always gives distance 1
print('distance:', direction[0]**2 + direction[1]**2) # 0.999999999999
# or
print('distance:', direction.length() )
And then you move object using speed
pos[0] += direction[0] * speed
pos[1] += direction[1] * speed
EDIT:
If you will use Rect
SIZE = (10, 10)
bullet_rect = pygame.Rect((0, 0), SIZE)
bullet_rect.center = (x1, y1)
then you can also calculate
distance = v2 - bullet_rect.center
direction = distance.normalize()
and move it with one line
bullet_rect.center += direction * speed
Rect
has many useful functions. But has one minus - it keeps position as integers
so it rounds float values and sometimes it gives strange moves or lost one pixel every few moves.
Doc: PyGame.math