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

玩家移动时子弹运动不符合预期的PyGame技术问题

问题搞定!相机偏移是罪魁祸首

我一眼就看出问题所在了——你的鼠标方向计算完全没考虑相机的偏移量!当玩家静止时,相机和屏幕中心对齐,所以用屏幕中心算角度没问题;但玩家斜向移动后,相机跟着偏移,此时屏幕上的鼠标位置对应的游戏世界坐标已经变了,你还拿屏幕中心来算角度,子弹不歪才怪呢!

具体修复步骤

1. 修正鼠标世界坐标的计算

在Player类的player_turning方法里,你需要把屏幕上的鼠标位置转换成游戏世界坐标(加上相机的偏移量),再和玩家的实际位置计算角度:

原来的错误代码:

self.x_change_mouse_player = (self.mouse_coords[0] - (WIDTH // 2))
self.y_change_mouse_player = (self.mouse_coords[1] - (HEIGHT // 2))

替换成:

# 把屏幕鼠标坐标转成游戏世界里的真实位置
mouse_world_pos = pygame.math.Vector2(self.mouse_coords) + camera.offset
# 计算玩家和鼠标在世界中的位置差
self.x_change_mouse_player = mouse_world_pos.x - self.base_player_rect.centerx
self.y_change_mouse_player = mouse_world_pos.y - self.base_player_rect.centery

2. 修复事件处理的作用域问题

另外,你在player_input方法里直接用了event变量,但这个变量只在主循环的事件遍历里存在,运行时会报错!得把空格键抬起的处理移到主循环里:

在主循环的事件处理块里添加:

if event.type == pygame.KEYUP:
    if event.key == pygame.K_SPACE:
        player.shoot = False

然后删掉player_input里的这段错误代码:

if event.type == pygame.KEYUP:
    if event.key == pygame.K_SPACE:
        self.shoot = False

修改后的关键代码片段

Player类的player_turning方法

def player_turning(self): 
    self.mouse_coords = pygame.mouse.get_pos() 

    # 核心修正:转换鼠标坐标到游戏世界
    mouse_world_pos = pygame.math.Vector2(self.mouse_coords) + camera.offset
    self.x_change_mouse_player = mouse_world_pos.x - self.base_player_rect.centerx
    self.y_change_mouse_player = mouse_world_pos.y - self.base_player_rect.centery
    
    self.angle = int(math.degrees(math.atan2(self.y_change_mouse_player, self.x_change_mouse_player)))
    self.angle = (self.angle) % 360 

    self.image = pygame.transform.rotate(self.base_player_image, -self.angle)
    self.rect = self.image.get_rect(center=self.base_player_rect.center)

Player类的player_input方法(移除错误的event处理)

def player_input(self):   
    self.velocity_x = 0
    self.velocity_y = 0

    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]:
        self.velocity_y = -self.player_speed
    if keys[pygame.K_s]:
        self.velocity_y = self.player_speed
    if keys[pygame.K_d]:
        self.velocity_x = self.player_speed
    if keys[pygame.K_a]:
        self.velocity_x = -self.player_speed
        
    if self.velocity_x != 0 and self.velocity_y != 0: # 斜向移动时减速,保持速度一致
        self.velocity_x /= math.sqrt(2)
        self.velocity_y /= math.sqrt(2)

    if keys[pygame.K_SPACE]:
        self.shoot = True
        self.is_shooting()        
    else:
        self.shoot = False

主循环的事件处理

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        # 移到这里处理空格键抬起事件,避免作用域错误
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_SPACE:
                player.shoot = False

原理说明

  • 相机的offset是玩家位置与屏幕中心的差值,所以屏幕鼠标位置加上offset,就能得到鼠标在游戏世界中的真实坐标。
  • 用世界坐标计算玩家和鼠标的角度,不管玩家怎么移动、相机怎么偏移,角度都是准确的,子弹自然就会精准指向鼠标位置。
  • 把事件处理移到主循环,解决了变量作用域的问题,避免运行时崩溃。

内容的提问来源于stack exchange,提问作者juba1029

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 11:35:30