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

如何修复《Python Crash Course》Alien Invasion项目飞船水平鼠标移动控制问题

问题:Alien Invasion游戏鼠标水平控制飞船功能失效

我正在修改《Python Crash Course》一书中的Alien Invasion游戏控制逻辑,想要实现仅通过鼠标水平控制飞船图片移动。我在Stack Overflow找到了如下参考代码:

import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
IMG = pg.Surface((120, 90))
IMG.fill((0, 120, 200))
x = 200
y = 300
done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == pg.MOUSEMOTION:
            if event.buttons[0]:  # Left mouse button pressed.
                x += event.rel[0]
                y += event.rel[1]

    screen.fill(BG_COLOR)
    screen.blit(IMG, (x, y))
    pg.display.flip()
    clock.tick(60)
pg.quit()

我尝试将该逻辑适配到我的项目中,但目前鼠标移动识别功能无法正常工作,以下是我的项目代码:

主程序 Alien_Invasion.py

import pygame
from settings import Settings
from ship import Ship
import game_functions as gf

def run_game():
    # Initialisiert das Spiel + erstellt ein screen-Objekt
    pygame.init()
    ai_settings = Settings()
    screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
    pygame.display.set_caption("Alien Invasion")
    # Erstellt das Schiff
    ship = Ship(ai_settings,screen)
    # Startet die Hauptschleife des Spiels.
    while gf.check_events(ship):
        ship.update()
        gf.update_screen(ai_settings, screen, ship)
run_game()

游戏功能模块 game_functions.py

import pygame,time 
import pygame.locals as pyl
clock = pygame.time.Clock()
x=0

def check_events(ship):
    # Lauscht auf Tastaturereignisse.
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            return False
        elif event.type == pyl.MOUSEMOTION:
            x = event.rel[0]
            if x>0:
                ship.moving_right=True
            if x<0:
                ship.moving_left=True
    clock.tick(60)
    return True     

def update_screen(ai_settings, screen, ship):
    #Zeichnet den Bildschirm bei jedem Schleifendurchlauf neu
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    # Macht den als letztes gezeichneten Bi1dschirm sichtbar
    pygame.display.flip()

飞船类模块 ship.py

import pygame
class Ship():
    def __init__(self,ai_settings,screen):
        self.screen = screen
        self.ai_settings = ai_settings
        # lädt das Bi1d des Schiffes und ruft dessen umgebendes Rechteck ab
        self.image=pygame.image.load('images/ship.bmp')
        self.rect=self.image.get_rect()  
        self.screen_rect= screen.get_rect()
        # Platziert jedes neue Schiff mittig am unteren Bildschirmrand
        self.rect.centerx = self.screen_rect.centerx
        self.rect.bottom = self.screen_rect.bottom
        # speichert einen Kommawert für den Schiffsmittelpunkt
        self.center=float(self.rect.centerx)

        self.moving_right=False
        self.moving_left=False
        
    def update(self):
        #Aktualisiert den Wert für den Mittelpunkt des Schiffs, nicht des Rechtecks
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.center += self.ai_settings.ship_speed_factor
        if self.moving_left and self.rect.left >0:
            self.center -= self.ai_settings.ship_speed_factor
        #Aktualisiert das rect-Objekt auf der Grundlage von self.center
        self.rect.centerx=self.center

    def blitme(self):
        self.screen.blit(self.image, self.rect)

配置类模块 settings.py

class Settings():
    def __init__(self):
        # Bildschirmeinstellungen
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (80,80,255)
        self.ship_speed_factor = 1.5
解决方案

你的代码有两个核心问题:

  1. 没有重置moving_right和moving_left的状态,只要触发过一次鼠标移动,这两个标记就会一直保持True,飞船会持续向对应方向移动,不会停止也无法正确响应后续鼠标操作
  2. 缺少参考代码中「按住鼠标左键才触发移动」的判断逻辑,默认只要鼠标移动就会触发位移

方案1:沿用拖动控制逻辑(和参考代码效果一致)

直接修改game_functions.py中的check_events函数即可:

def check_events(ship):
    # 每次循环先重置移动状态,避免状态残留
    ship.moving_right = False
    ship.moving_left = False
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            return False
        elif event.type == pyl.MOUSEMOTION:
            # 仅按住左键时响应移动
            if event.buttons[0]:
                x_offset = event.rel[0]
                if x_offset > 0:
                    ship.moving_right = True
                if x_offset < 0:
                    ship.moving_left = True
    clock.tick(60)
    return True

方案2:实现鼠标位置跟随(无需按住拖动,更顺滑)

如果不需要拖动控制,想让飞船直接跟着鼠标水平位置移动,可以用更简单的实现方式:

  1. 修改game_functions.py的check_events函数:
def check_events(ship):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            return False
        elif event.type == pyl.MOUSEMOTION:
            # 直接把鼠标的x坐标赋值给飞船中心
            ship.center = event.pos[0]
    clock.tick(60)
    return True
  1. 可以删掉ship.py中所有和moving_right、moving_left相关的逻辑,也可以保留不影响运行。

内容的提问来源于stack exchange,提问作者jörg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 16:57:05