Skip to content
Advertisement

How do you shoot a bullet towards mouse in pygame at a constant speed?

I am trying to shoot a bullet towards my mouse in pygame, here is my code:

import pygame
import math

pygame.init()

screen = pygame.display.set_mode((400, 400))

pygame.display.set_caption("diep.io")

screen.fill((255,255,255))

auto_shoot = False

class Bullet:
  def __init__(self, x_move, y_move, x_loc, y_loc):
    self.image = pygame.image.load("Bullet.png")
    self.x_move = x_move
    self.y_move = y_move
    self.x_loc = x_loc
    self.y_loc = y_loc
    self.bullet_rect = self.image.get_rect()
  
  def update(self):
    self.bullet_rect.center = (self.x_loc + self.x_move, self.y_loc + self.y_move)
    self.x_loc = self.bullet_rect.center[0]
    self.y_loc = self.bullet_rect.center[1]
    screen.blit(self.image, self.bullet_rect)

    if self.x_loc > 400 or self.y_loc > 400:
      bullets.remove(self)

bullet = None
bullets = []

while True:
  screen.fill((255, 255, 255))
  pygame.draw.rect(screen, (100, 100, 100), (205, 193, 25, 15))
  pygame.draw.circle(screen, (82, 219, 255), (200, 200), 15)
  for event in pygame.event.get():
    if event.type == pygame.MOUSEBUTTONUP:
      x = pygame.mouse.get_pos()[0] - 200
      y = pygame.mouse.get_pos()[1] - 200
      pythag = float(math.sqrt(x**2 + y**2))
      bullets.append(Bullet(x/pythag, y/pythag, 200, 200))
  for bullet in bullets:
    bullet.update()
  pygame.display.update()
  pygame.time.delay(10)

I am confused on how to make this work, I think somehow I am rounding something, but even after I put float() in, it still is not working. Also, before when I used the mouse coordinates, it works, but when close to tank, it shoots slow, and insanely fast farther from the tank. Somebody please help, thanks!

Advertisement

Answer

Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.

The coordinates for Rect objects are all integers. […]

The fraction part of the coordinates gets lost when the new position of the object is assigned to the Rect object.
You have to do it the other way around. Change self.x_loc and self.y_loc, but update self.bullet_rect.center:

class Bullet:
  # [...]

  def update(self):
    self.x_loc += self.x_move
    self.y_loc += self.y_move   
    self.bullet_rect.center = round(self.x_loc), round(self.y_loc)

    rect = screen.blit(self.image, self.bullet_rect)
    if not screen.get_rect().contains(rect):
      bullets.remove(self)

See also these questions: Shooting a bullet in pygame in the direction of mouse and How can you rotate the sprite and shoot the bullets towards the mouse position.

Advertisement