我笨手笨脚地用Python语言编写了一个蛇游戏,它的主循环出现了问题

对于任何草率之处,我提前道歉,我仍在制作原型:

import sys
import pygame
from pygame.locals import *

from libs.Touch import Touch

def sortPairs(*pairs):
    result = {}
    for pair in pairs:
        result[pair[0]] = pair[1]
        result[pair[1]] = pair[0]
    return result

DIR = {
    'LEFT':  (-1, +0),
    'RIGHT': (+1, +0),
    'UP':    (+0, -1),
    'DOWN':  (+0, +1)
}
DIR['INVERSE'] = sortPairs(
    (DIR['LEFT'], DIR['RIGHT']),
    (DIR['UP'],   DIR['DOWN']))

class Snake:
    def __init__(self,x, y):
        self.dir   = DIR['RIGHT']
        self.nodes = [[x, y]]
    
    def move(self):
        for i in range(len(self.nodes) - 1, 0, -1):
            self.nodes[i][0] = self.nodes[i - 1][0]
            self.nodes[i][1] = self.nodes[i - 1][1]
            
        self.nodes[0][0] += self.dir[0]
        self.nodes[0][1] += self.dir[1]
    
    def turn(self, turn):
        dir = DIR[turn]
        if len(self.nodes) == 1 or dir != DIR['INVERSE'][turn]:
            self.dir = dir
    
    def grow(self):
        self.nodes.appendLeft([
            self.nodes[0][0] + self.dir[0],
            self.nodes[0][1] + self.dir[1]])
    
    def draw(self, surface,x, y, node_size):
        rect = pygame.Rect(
            0, 0, node_size, node_size)
        
        for node in self.nodes:
            rect.left   = x + node[0] * node_size
            rect.top    = y + node[1] * node_size
            rect.right  = rect.left + node_size     
            rect.bottom = rect.top + node_size
            
            
            pygame.draw.rect(
                surface,
                pygame.Color("#FF0000"),
                rect)

class Game:
    def __init__(self, size, tick):
        self.size = size
        self.tick = tick
        self.snake = Snake(0, 0)
        
    def draw(self, surface):
        surface.fill(pygame.Color('#161616'))
        
        cell_size = min(
            surface.get_width(),
            surface.get_height()) / self.size
        
        bounds_stroke = int(cell_size / 10)
        
        bounds = pygame.Rect(
            surface.get_width() / 2,
            surface.get_height() / 2,
            cell_size * self.size - bounds_stroke,
            cell_size * self.size - bounds_stroke)
        bounds.center = (bounds.x, bounds.y)
        
        self.snake.draw(
            surface,
            int(bounds.left),
            int(bounds.top),
            int(cell_size))
        
        pygame.draw.rect(
            surface,
            pygame.Color('#6f91b3'),
            bounds,
            bounds_stroke)
        
    def update(self):
        self.snake.move()
    
    def handle_event(self, event):
        if event.type == MOUSEBUTTONDOWN:
            pygame.mouse.get_rel()
        if event.type == MOUSEBUTTONUP:
            swipe = Touch.reg_swipe(*pygame.mouse.get_rel())
            if swipe != -1:
                self.snake.turn(swipe)
            
        if event.type == QUIT:
            pygame.quit()

def main():
    game = Game(30, 100)
    
    pygame.init()
    
    # Resolution is ignored on Android
    surface = pygame.display.set_mode((640, 480))
    
    clock = pygame.time.Clock()
    
    delta = 0
    
    while True:
        for ev in pygame.event.get():
            game.handle_event(ev)
            
            delta += clock.tick(60)
            
            if delta >= game.tick:
                game.update()
                delta = 0
            
            game.draw(surface)
            pygame.display.flip()

if __name__ == '__main__':
    main()

./libs/Touch.py:

class Touch:
    max_touch_dist = 15
    min_swipe_dist = 50
    
    @staticmethod
    def reg_swipe(rel_x, rel_y):
        min = Touch.min_swipe_dist
        if abs(rel_y) < min:
            if rel_x <= -min:
                return 'LEFT'
            elif rel_x >= min:
                return 'RIGHT'
        if rel_y <= -min:
            return 'UP'
        elif rel_y >= min:
            return 'DOWN'
            
        return -1

我在我的手机上使用了Pydroid,但在一个在线解释器上测试它得到了同样的结果:游戏运行了两次,然后冻结,然后只有当我touch 屏幕(或触发我想象中的事件)时才运行,我已经将我的代码(特别是事件循环)与PyGame样本进行了比较,但一切看起来都很好,那么发生了什么?

推荐答案

您必须运行游戏逻辑并在应用程序循环中绘制场景,而不是在事件循环中.事件循环仅在事件发生时执行,但应用程序循环每帧执行一次,并且帧的数量由clock.tick(60)控制.

def main():
    # [...]

    while True:
        for ev in pygame.event.get():
            game.handle_event(ev)
            
        delta += clock.tick(60)    
        if delta >= game.tick:
            game.update()
            delta = 0
            
        game.draw(surface)
        pygame.display.flip()

Python相关问答推荐

Python -Polars库中的滚动索引?

在应用循环中间保存pandas DataFrame

如何在BeautifulSoup中链接Find()方法并处理无?

Python上的Instagram API:缺少client_id参数"

带条件计算最小值

Python中的嵌套Ruby哈希

如何在Python脚本中附加一个Google tab(已经打开)

形状弃用警告与组合多边形和多边形如何解决

连接一个rabrame和另一个1d rabrame不是问题,但当使用[...]'运算符会产生不同的结果

如何根据一列的值有条件地 Select 前N组?

在www.example.com中使用`package_data`包含不包含__init__. py的非Python文件

如何更改groupby作用域以找到满足掩码条件的第一个值?

在输入行运行时停止代码

用SymPy在Python中求解指数函数

Numpyro AR(1)均值切换模型抽样不一致性

关于两个表达式的区别

巨 Python :逆向猜谜游戏

Pandas—堆栈多索引头,但不包括第一列

使用Python异步地持久跟踪用户输入

如何提高Pandas DataFrame中随机列 Select 和分配的效率?