0

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?

Daniel Tam
  • 908
  • 1
  • 12
  • 25
  • 2
    [http://man.hubwiz.com/docset/PyGame.docset/Contents/Resources/Documents/ref/math.html#pygame.math.Vector2.normalize](http://man.hubwiz.com/docset/PyGame.docset/Contents/Resources/Documents/ref/math.html#pygame.math.Vector2.normalize) – Taxel Jul 26 '21 at 10:52
  • you could use all time `bullet_rect` instead of `bullet_pos[0]` and `bullet_pos[1]` , And you even set size in `bullet_rect` so later you don't need `BULLET_SIZE`. And it has functions to detect collisons. – furas Jul 26 '21 at 11:43

1 Answers1

0

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

furas
  • 134,197
  • 12
  • 106
  • 148