2011-04-07 129 views
3

任何人都可以推薦如何在pyglet中切換場景。 也就是說使用pyglet切換場景

  • 菜單>遊戲
  • 遊戲>菜單
  • 菜單>幫助
  • ECT

,我能想到這樣做了我的頭頂部的唯一方法是通過使用不同的窗口,我相當肯定會是完全錯誤的做法。或者通過重載窗口的所有事件函數。

很抱歉,如果我沒有說清楚,但任何幫助,將不勝感激

回答

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) 

這只是一個簡單的例子,但我希望你能看到,而不是在開始遊戲時,MainMenu的可能,而不是將它們添加到世界,或任何這樣的事情顯示二級菜單。

一旦進入遊戲,您可以通過簡單地調用不再想要看到的所有項目上的'world.remove',並在新場景中的所有項目上調用'world.add'來更改'場景'。

使用這種技術遊戲的一個例子是以前pyweek進入SinisterDucks: http://code.google.com/p/brokenspell/ (不過,公平地說,它並不擁有在遊戲中獨特的「場景」這只是usesthis技術管理菜單,遊戲結束屏幕等)

+0

真的好主意我可能最終會在未來使用它 – Hugoagogo 2011-04-08 07:26:08

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() 

所以,你有一個遊戲他擁有該窗口並管理向用戶顯示哪個屏幕。這裏我使用「屏幕」來表示用戶正在與之交互的內容,例如MainMenu或LevelPlayer。這裏的關鍵是Screen的clear()方法,您應該執行該方法以刪除所顯示的所有精靈,媒體,組和批處理。您還必須清除窗口處理程序並將其設置爲開始。

您可以在這裏看到這些內容起作用的解決方案:https://github.com/superjoe30/lemming/tree/master/lemming

2

的cocos2d.org框架是建立在pyglet,包括現場管理。

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去將管理推動和從堆棧