试图弄清楚如何跟踪Pygame事件并组织游戏的功能

时间:2013-09-09 07:18:37

标签: multithreading events loops pygame

我是Pygame的新手,所以我仍然在努力解决整个“事件”概念。

基本上,我目前面临的挑战是:

  1. 让pygame.event.get()在主循环之外工作,这样我就可以允许玩家从游戏的一个部分进入下一个部分(例如按空格键)。

  2. 找出一种在主线程中组织游戏的不同功能的方法,这样它们就不会一直反复循环并相互覆盖。

  3. 我理解主循环在许多游戏中是如何至关重要的,但是当游戏涉及从一个事件移动到另一个事件时,我无法理解如何在这个游戏中使用它(这是一个相对简单的基于文本的游戏,其中您将浏览不同的菜单并选择要进行的选择)。由于主循环是一个while循环,所以其中的所有内容都不断重复,所以我怎样才能从一个屏幕到另一个屏幕,而屏幕无法相互冲突?

    例如,我有一个介绍性序列(一个Intro()函数),该序列应该先于其他任何东西运行,然后让你通过点击空格键继续进行实际游戏。我已经在实际主循环之前放置了Intro()函数以防止它循环。但是,pygame.event.get()在其中不起作用(请记住,我已经在主循环中有“for”循环这样的事件),我希望能够通过点击进入游戏本身空格键。

    如果有人能够启发并给我一个逻辑和线程的教训,那将是很棒的。

    感谢。

1 个答案:

答案 0 :(得分:3)

坚持使用一个主循环,如果你真的不需要它们,不要使用线程。

你已经发现你的游戏包含不同的屏幕(让我们称之为Scene,所以我们不要把它与我们绘制东西的实际屏幕混淆,所以下一个合乎逻辑的步骤是将它们从主循环中分离出来。


假设您有以下场景:

  • 介绍
  • 主菜单
  • 游戏

然后你应该为每个人创建一个类,然后负责绘图/事件处理/本节中的任何需要。

一个简单的例子:

import pygame
pygame.init()

class Scene(object):
    screen = None

class Intro(Scene):
    def __init__(self):
        self.c = (32, 32, 100)

    def draw(self):
        Scene.screen.fill(self.c)

    def update(self):
        # since scenes are classes, they have a state that we can modify
        r,g,b = self.c
        r += 1
        g += 1
        b += 2
        if r > 255: r = 0
        if g > 255: g = 0
        if b > 255: b = 0
        self.c = r, g, b

    def handle(self, event):
        # move to Menu-scene when space is pressed
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                # returning a scene from handle or update changes the current scene
                return Menu()

class Menu(Scene):
    def draw(self):
        # draw menu
        Scene.screen.fill((200, 200, 100))

    def update(self):
        pass
        # do something

    def handle(self, event):
        # handle menu input
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                return Game()
            if event.key == pygame.K_b:
                return Intro()

class Game(Scene):
    pass # implement draw update handle

Scene.screen = pygame.display.set_mode((800, 600))

scene = Intro()
while True:
    if pygame.event.get(pygame.QUIT): break
    for e in pygame.event.get(): 
        scene = scene.handle(e) or scene
    scene = scene.update() or scene
    scene.draw()
    pygame.display.flip()

这样,您就拥有一个主循环,但游戏的不同部分由单独的类管理。在上面的简单示例中,每个场景都知道在某个事件上要激活的其他场景,但这不是必需的。您可以创建某种SceneHandler来管理场景之间的过渡。此外,您可能希望拥有某种想要传递场景的游戏状态对象(例如,在游戏场景中显示游戏场景中的点数)。