当我尝试旋转 Actor 时,为什么我的 Pygame Zero 程序“没有响应”?

问题描述

我刚刚开始尝试自学 Pygame Zero,因为下学期我们要在课堂上做作业,我想做好准备。

我试着做一个简单的程序,让你的飞船不断向前加速,你可以使用左右箭头来转动它。问题是我的代码在两个方面被窃听。首先,当程序第一次启动时,船是朝上的,但它不断向右移动,没有什么可以阻止它,即使它应该和船在同一个方向上加速。此外,当我尝试按左右箭头转动它时,程序会冻结,然后停止响应。我已尽最大努力修复它,但网上关于 Pygame Zero 的信息很少。如果有人能帮助我,我将不胜感激。

这是我的代码

import pgzrun
ship=Actor('ship')
WIDTH = 800
HEIGHT = 450
def draw():
    screen.clear()
    screen.blit("background",(WIDTH,HEIGHT))
    screen.fill((255,255,255))
    ship.draw()
def on_key_down(key):
    if key == keys.LEFT:
        left = True
        while left == True:
            ship.angle += 10
    if key == keys.RIGHT:
        right = True
        while right == True:
            ship.angle -= 10
def on_key_up(key):
    if key == keys.LEFT:
        left = False
    if key == keys.RIGHT:
        right = False
    
def update():
    if ship.angle >= 350:
        ship.x += 0
        ship.y -= 3.5
    elif ship.angle >= 330:
        ship.x += 0.1
        ship.y -= 3.3
    elif ship.angle >= 310:
        ship.x += 0.3
        ship.y -= 3.1
    elif ship.angle >= 290:
        ship.x += 0.5
        ship.y -= 2.9
    elif ship.angle >= 270:
        ship.x += 0.7
        ship.y -= 2.7
    elif ship.angle >= 250:
        ship.x += 0.9
        ship.y -= 2.5
    elif ship.angle >= 230:
        ship.x += 1.1
        ship.y -= 2.3
    elif ship.angle >= 210:
        ship.x += 1.3
        ship.y -= 2.1
    elif ship.angle >= 190:
        ship.x += 1.5
        ship.y -= 1.9
    elif ship.angle >= 170:
        ship.x += 1.7
        ship.y -= 1.7
    elif ship.angle >= 150:
        ship.x += 1.9
        ship.y -= 1.5
    elif ship.angle >= 130:
        ship.x += 2.1
        ship.y -= 1.3
    elif ship.angle >= 110:
        ship.x += 2.3
        ship.y -= 1.1
    elif ship.angle >= 90:
        ship.x += 2.5
        ship.y -= 0.9
    elif ship.angle >= 70:
        ship.x += 2.7
        ship.y -= 0.7
    elif ship.angle >= 50:
        ship.x += 2.9
        ship.y -= 0.5
    elif ship.angle >= 30:
        ship.x += 3.1
        ship.y -= 0.3
    elif ship.angle >= 10:
        ship.x += 3.3
        ship.y -= 0.1
    else:
        ship.x += 3.5
        ship.y -= 0


pgzrun.go()

解决方法

这是导致冻结的部分:

def on_key_down(key):
    if key == keys.LEFT:
        left = True
        while left == True:
            ship.angle += 10
    if key == keys.RIGHT:
        right = True
        while right == True:
            ship.angle -= 10

如您所见,您以始终为 while 的条件开始一个 True 循环。该代码的构建假设 on_key_up 方法将在密钥被释放后立即被调用,并且控制 while 条件的变量将更改为 False。如果此代码是多线程的,则可能会发生这种情况 - 然后可以并发调用另一个函数。事实并非如此:pygame zero 的主循环是单线程的,并且依赖于每个被调用的函数在游戏状态可以更新之前运行完成并返回。

(即使它是多线程的,而且 pygamezero 可以将 leftright 检查更改为 False,两条线 while 循环每秒会更新船舶角度数百万次,当您可能希望它在每个游戏帧更新 10 度(或更少)。

您需要做的就是升级 rightleft 变量,指示“keyup”和“keydown”事件的旋转,并在更新函数中改变角度 - 即每帧调用一次(我想 - 自从我尝试 pygame zero 以来已经有很多时间了)。

顺便说一句,你可以得到一个基于角度更新船舶位置的数学公式,而不是依赖 if/elifs 链 - 虽然它可以工作,但它不是最花哨的代码。


import math

...

def draw(...):
    ...

left = right = False
def on_key_down(key):
    global left,right
    if key == keys.LEFT:
        left = True
    if key == keys.RIGHT:
        right = True

def on_key_up(key):
    global left,right
    if key == keys.LEFT:
        left = False
    if key == keys.RIGHT:
        right = False
        

def update():
   global left,right

   if left:
       ship.angle += 10
   elif right: 
       ship.angle -= 10
   # constrain the angle to 0-360 range:
   ship.angle %= 360

   ship.x += 3.5 * sin(math.radians(angle))
   ship.y -= 3.5 * cos(math.radians(angle))