You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在pygame中实现向鼠标位置以恒定速度发射子弹的功能

问题根源

  • 核心问题是pygame.Rect的所有坐标属性只支持整数,你传入的浮点坐标会被自动截断取整。你当前计算出的x_move、y_move是归一化后的单位向量,数值都小于等于1,累加后赋值给Rect会被直接舍去小数部分,子弹坐标几乎不会变化,看起来就卡住了。
  • 你之前直接用鼠标坐标差作为移动量的写法,等于子弹速度和鼠标到坦克的距离成正比,自然会出现近慢远快的问题。
  • 额外隐藏问题:在遍历子弹列表的过程中删除列表元素,会导致后续子弹被跳过遍历;每个子弹实例重复加载图片会拉低运行效率。

修复方案

你可以通过单独维护浮点类型的子弹坐标、添加固定速度系数、优化销毁逻辑来解决问题,修改后的完整代码如下:

import pygame
import math

pygame.init()

# 全局常量定义
SCREEN_SIZE = 400
BULLET_SPEED = 5  # 可自行调整子弹速度
# 子弹图片提前加载一次即可
BULLET_IMG = pygame.image.load("Bullet.png")

screen = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE))
pygame.display.set_caption("diep.io")

auto_shoot = False

class Bullet:
  def __init__(self, x_dir, y_dir, x_loc, y_loc):
    self.image = BULLET_IMG
    # 乘以速度系数得到每帧移动量
    self.x_move = x_dir * BULLET_SPEED
    self.y_move = y_dir * BULLET_SPEED
    # 单独维护浮点类型的坐标,避免精度丢失
    self.x_loc = float(x_loc)
    self.y_loc = float(y_loc)
    self.bullet_rect = self.image.get_rect()
  
  def update(self):
    # 先更新浮点坐标
    self.x_loc += self.x_move
    self.y_loc += self.y_move
    # 再赋值给Rect,自动转整数用于渲染
    self.bullet_rect.center = (self.x_loc, self.y_loc)
    screen.blit(self.image, self.bullet_rect)

    # 返回是否超出屏幕,用于后续销毁判断,避免遍历中删列表
    return (self.x_loc > SCREEN_SIZE or self.x_loc < 0 
            or self.y_loc > SCREEN_SIZE or self.y_loc < 0)

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.QUIT:
      pygame.quit()
      exit()
    if event.type == pygame.MOUSEBUTTONUP:
      mouse_x, mouse_y = pygame.mouse.get_pos()
      dx = mouse_x - 200
      dy = mouse_y - 200
      distance = math.hypot(dx, dy)
      # 避免鼠标和坦克完全重合时除以0
      if distance != 0:
        x_dir = dx / distance
        y_dir = dy / distance
        bullets.append(Bullet(x_dir, y_dir, 200, 200))
  # 更新子弹并过滤销毁超出屏幕的子弹
  bullets = [bullet for bullet in bullets if not bullet.update()]
  pygame.display.update()
  pygame.time.delay(10)

关键改动说明

  • 新增了固定的子弹速度系数BULLET_SPEED,归一化的方向向量乘以该系数后,不管鼠标距离坦克远近,子弹每帧移动的距离都固定,速度均匀。
  • 单独用浮点变量存储子弹坐标,更新完成后再赋值给Rect用于渲染,避免了自动取整导致的位置不更新问题。
  • 优化了子弹销毁逻辑,不在遍历过程中删除列表元素,避免遍历异常,同时补充了向左、向上飞出屏幕的销毁判断。
  • 新增了窗口关闭事件的处理,避免程序无法正常退出;新增了鼠标和坦克重合时的除0判断,避免运行报错。
  • 子弹图片统一提前加载一次,降低性能消耗。

内容的提问来源于stack exchange,提问作者ᴇɴᴅᴇʀᴍᴀɴ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:24:08