0

I'm currently making a game using Pygame, Python 3 and one of the bugs I have in it is they way shots move. The game is a 2D top-down shooter, and the code for the player shooting mechanic is below:

(player_rect is the Rect for the player, bullet_speed is a pre-defined int)

if pygame.mouse.get_pressed()[0]:
    dx = mouse_pos[0]-player_rect.centerx
    dy = mouse_pos[1]-player_rect.centery
    x_speed = bullet_speed/(math.sqrt(1+((dy**2)/(dx**2))))
    y_speed = bullet_speed/(math.sqrt(1+((dx**2)/(dy**2))))
    if dx < 0:
        x_speed *= -1
    if dy < 0:
        y_speed *= -1
    #surface, rect, x-speed, y-speed
    player_shots.append([player_shot_image, player_shot_image.get_rect(centerx=player_rect.centerx, centery=player_rect.centery), x_speed, y_speed])

Later in the loop, there is this part of code:

for player_shot_counter in range(len(player_shots)):
    player_shots[player_shot_counter][1][0] += player_shots[player_shot_counter][2]
    player_shots[player_shot_counter][1][1] += player_shots[player_shot_counter][3]

This mechanic works mostly fine, with the exception of one major bug: the slower the shot, the less accurate it is as pygame.Rect[0] and pygame.Rect[1] can only be integer values. For example if the player_rect.center is (0, 0), the position of the mouse is (100, 115) and bullet_speed is 10, then x_speed will automatically round to 7 and y_speed to 8, resulting in the bullet eventually passing through the point (98, 112). However, if bullet_speed is 5, then the bullet will pass through the point (99, 132).

Is there any way to get around this in pygame?

Thanks in advance for any help!

Alec
  • 31,829
  • 7
  • 67
  • 114
Vladimir Shevyakov
  • 2,511
  • 4
  • 19
  • 40
  • 1
    As far as I am aware, the best solution you have at this point is to track the real position in floating point coordinates and then when it comes to blitting your sprite to screen, round it accordingly. This resource was helpful for me: [going sub-pixel with pygame](https://www.willmcgugan.com/blog/tech/post/going-sub-pixel-with-pygame/). Something that will also be affecting you is, you don't appear to be taking into account `time` when adjusting bullet speed. This will cause a greater margin for error in your bullet positioning. – Jonathon Ogden Jul 22 '16 at 20:55
  • 1
    A further suggestion regarding your positioning code and lines such as this: `math.sqrt(1+((dx**2)/(dy**2)))`: are you aware pygame has [Vector2](http://www.pygame.org/docs/ref/math.html#pygame.math.Vector2) which represents _x_, _y_ coordinates and has functions such as `math.length` which save you having to write your positioning code like that? – Jonathon Ogden Jul 22 '16 at 20:59
  • @JonathonOgden Thanks, I actually was not aware that pygame has a Vector2 class and was just using a list with 2 enteries instead. But what is `math.length`? – Vladimir Shevyakov Jul 22 '16 at 21:04
  • `math.length` is the equivalent of `math.sqrt(vec.x**2 + vec.y**2)` i.e. the magnitude or length of the vector. Reference [Vector2.length](http://www.pygame.org/docs/ref/math.html#pygame.math.Vector2.length) – Jonathon Ogden Jul 22 '16 at 21:12

1 Answers1

1

I don't know a whole lot about Pygame, but have you thought of storing your positions as non-integer values, only converting to integers on display? The internal representation can be more precise than what is displayed to the user.

awerries
  • 86
  • 2