用pyglet切换场景

时间:2011-04-07 12:58:49

标签: python pyglet

有人可以推荐如何在pyglet中切换场景。 即

  • 菜单>游戏
  • 游戏>菜单
  • 菜单>帮助
  • ECT

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

很抱歉,如果我没有说清楚,但任何帮助将不胜感激

4 个答案:

答案 0 :(得分: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类。在这里,我使用“屏幕”来表示用户正在与之交互的内容,例如MainMenu或LevelPlayer。这里的关键是Screen的clear()方法,您应该实现该方法来删除您正在显示的所有精灵,媒体,组和批次。您还必须清除窗口处理程序并将其设置为启动。

您可以在此处查看此解决方案:https://github.com/superjoe30/lemming/tree/master/lemming

答案 1 :(得分:2)

cocos2d.org框架基于pyglet构建,包括场景管理。

答案 2 :(得分:1)

我不是很有经验,但是对于它的价值,我使用的方法如下。它不能识别明确的“状态”或“场景”,而是依赖于将离散项目添加(和删除)到我的游戏世界中。每个这样的项目可能都有自己的密钥处理程序,并知道如何以及何时创建其他此类项目。

一个具体的例子:

GameItem是可以放入世界的所有物品的子类。它是一个简单的属性集合,没有任何行为。它由游戏世界中的项目(如布什,玩家等)以及像ScoreDisplay和MainMenu等HUD项目分类。

世界只是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/ (虽然,公平地说,它在游戏过程中没有明显的“场景”。它仅仅使用这种技术来管理菜单,屏幕上的游戏等)

答案 3 :(得分:0)

我最终使用的解决方案是给主窗口一个堆栈,让它将所有事件传递给堆栈顶部的项目。

class GameWindow(pyglet.window.Window):
    def __init__(self,*args, **kwargs):
        pyglet.window.Window.__init__(self, *args, **kwargs)
        self.states = [PlayLevel(self)] ## Starting State

    def on_draw(self):
        if hasattr(self.states[-1],"on_draw"):
            self.states[-1].on_draw()

    def on_mouse_press(self,*args):
        if hasattr(self.states[-1],"on_mouse_press"):
            self.states[-1].on_mouse_press(*args)

等。对于我使用的所有其他事件

我目前正在编写一些函数进入GameWindow,以管理从堆栈中推送和弹出场景