使用pyglet切换场景

3 投票
4 回答
3544 浏览
提问于 2025-04-16 15:16

有没有人能推荐一下在 pyglet 中如何切换场景?比如:

  • 从菜单切换到游戏
  • 从游戏切换到菜单
  • 从菜单切换到帮助
  • 等等

我想到的唯一方法就是使用不同的窗口,但我很确定这完全不是正确的做法。或者是重载所有窗口的事件函数。

抱歉如果我没有表达清楚,但任何帮助都会很感激。

4 个回答

2

cocos2d.org这个框架是建立在pyglet基础上的,并且它包含了场景管理的功能。

2

这里有一个大致的类结构图,可能对你有帮助:

class Game(object):
    "This class contains the Scene which is the current scene the user is look ing at."
    def __init__(self):
        self.current_level = 0
        self.current_screen = MainMenu(self)

    def load(self):
        "Load progress from disk"
        pass

    def save(self):
        "Save progress to disk"
        pass

    def clearCurrentScreen(self):
        self.current_screen.clear()
        self.window.remove_handlers()

    def startCurrentScreen(self):
        self.window.set_handler("on_key_press", self.current_screen.on_key_press)
        # etc

        self.current_screen.start()

    def gotoNextLevel(self):
        "called from within LevelPlayer when the player beats the level"
        self.clearCurrentScreen()
        self.current_level += 1
        self.current_screen = LevelPlayer(self, game, self.current_level)
        self.startCurrentScreen()

    def startPlaying(self):
        "called by the main menu when the user selects an option"
        self.clearCurrentScreen()
        self.current_screen = LevelPlayer(self, game, self.current_level)
        self.startCurrentScreen()

    def execute(self):
        self.window = pyglet.window.Window()
        self.startCurrentScene()
        pyglet.app.run()


class Screen(object):
    def __init__(self):
        pass

    def start():
        pass

    def clear():
        "delete all graphical objects on screen, batches, groups, etc. Clear all state in pyglet."
        pass

    def on_key_press(self, key, etc):
        pass

    def on_draw(self):
        pass

    # etc

class LevelPlayer(Screen):
    "This class contains all your game logic. This is the class that enables the user to play through a level."
    def __init__(self, game, level_to_play):
        pass

    # be sure to implement methods from Screen

class MainMenu(Screen):
    "This class presents the title screen and options for new game or continue."
    def __init__(self, game):
        self.game = game

    def handleNewGame(self):
        self.game.startPlaying()

    def handleContinue(self):
        self.game.load()
        self.game.startPlaying()

    # be sure to implement methods from Screen


game = Game()
game.execute()

你有一个游戏类(Game),它负责管理窗口,并决定给用户显示哪个界面。在这里,我用“界面”(Screen)来指代用户正在互动的部分,比如主菜单(MainMenu)或者关卡播放(LevelPlayer)。关键在于界面里的 clear() 方法,你需要实现这个方法来清除所有正在显示的精灵、媒体、组和批处理。你还需要在清除时移除窗口的处理程序,并在开始时重新设置它们。

你可以在这里看到这个解决方案的实际应用: https://github.com/superjoe30/lemming/tree/master/lemming

1

我不是很有经验,但我用的方法是这样的。它并不明确区分“状态”或“场景”,而是依赖于将不同的物品添加(或移除)到我的游戏世界中。每个物品可能都有自己的按键处理方法,并且知道如何以及何时创建其他类似的物品。

举个具体的例子:

GameItem是所有可以放入世界中的物品的一个子类。它只是一个简单的属性集合,没有任何行为。游戏世界中的物品,比如Bush(灌木)、Player(玩家)等,都是从这个类派生出来的,还有一些HUD(用户界面)物品,比如ScoreDisplay(得分显示)和MainMenu(主菜单)。

World就是一个GameItems的集合。

我的“更新”函数会遍历世界中的所有物品,如果它们有更新方法,就调用它。

我的“绘制”函数也会遍历世界中的所有物品,绘制每一个物品。(很多物品可以通过调用像pyglet的Batch.draw这样的方式一次性绘制出来)

在应用程序启动时,我首先添加到世界中的物品是一个MainMenu对象。它有一个on_key_down方法。

World.add会查看正在添加的物品。如果这个物品有on_key_down方法,就会把这个处理方法添加到pyglet的按键处理器堆栈中。(类似地,在World.remove时会撤销这个操作)(实际上,仔细想想,我觉得world.add在添加物品时会触发一个事件。如果应用程序的键盘处理模块感兴趣,那么在收到这些事件时,它会添加物品的按键处理器,但这和问题关系不大)

MainMenu.on_key_handler方法会查看按下的键,如果是开始游戏的键,就会进行一系列的调用:

# Do everything needed to start the game
# For dramatic pacing, any of these might be scheduled to be
# called in a second or so, using pyglet.clock.schedule_once
world.add(player)
camera.to_follow(player)
world.add(scoredisplay)

# Finally, remove the main menu from the world
# This will stop showing it on screen
# and it will remove its keyboard event handler
world.remove_item(self)

这只是一个简单的例子,但希望你能明白,主菜单可以通过将其他菜单添加到世界中,而不是直接开始游戏,来显示其他菜单。

一旦进入游戏,你可以通过简单地调用'world.remove'来移除所有不想显示的物品,然后调用'world.add'来添加新场景中的所有物品,从而改变“场景”。

使用这种技术的游戏例子是之前的pyweek参赛作品SinisterDucks: http://code.google.com/p/brokenspell/ (不过,公平地说,它在游戏过程中并没有明显的“场景”。它只是用这种技术来管理菜单、游戏结束画面等)

撰写回答