-1

我正在使用 Python 和模块 Pygame 创建一个小游戏。

我尝试实现一个非常基本的(我猜是一个非常幼稚的)状态管理器。

但是,
我目前有一个问题:
一旦切换“播放”状态,我就无法切换回“菜单”。
这是我设计状态管理器的缺陷吗?

我有两种方法,

  1. state_change方法采用一个参数,即所需的状态。
  2. state_check方法将状态作为唯一参数并将其作为当前状态返回。

以下是两种方法:

def state_check(self, state):
    self.current_state = state
    print self.current_state
    return self.current_state

def state_change(self, state):
    self.state = state

在主循环之前,
第一个state被初始化为“菜单”。
在主循环内部,
state_check位于 if 语句之前,用于指示从哪个状态开始。

def game_loop(self):                                                                       

    running = True
    self.test_car = car()
    self.state = "menu"
    while running:
        pygame.display.set_caption("Project G")
        self.state_check(self.state)
        if self.current_state ==  "menu":
            self.state_check(self.state)
            self.screen.blit(self.background, (0,0))
            #Blits the current state on the screen for testing purposes.
            self.screen.blit(self.menu_text, (700, 580))
            self.event_handler()
            pygame.display.flip()
        if self.current_state == "play":
            self.state_check(self.state)
            self.screen.blit(self.background, (0,0))
            #Blits the current state on the screen.
            self.screen.blit(self.play_text, (700, 580))
            self.test_car.event_handler()
            self.test_car.update(self.test_car.x_speed, self.test_car.y_speed)
            pygame.display.flip()

在 if 语句中,
是事件处理程序方法,我目前使用键盘输入在状态之间切换(通过调用state_change方法)并退出程序。

使用一些打印方法,我已经排除了键未注册的可能性

#Event handler for the menu

def event_handler(self):

    for event in pygame.event.get():
        if event.type == QUIT:
           pygame.quit()
           sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_p:
                self.state_change("play")
                print "Key Pressed: p"
            if event.key == K_q:
                print "Key Pressed: q"
                pygame.quit()
                sys.exit()
#Sample of the Event handler for "play"

def event_handler(self):
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_m:
                self.state_change("menu")
                print "Key Pressed: m"
            if event.key == K_q:
                print "Key Pressed: q"
                pygame.quit()
                sys.exit()
4

4 回答 4

1

一些可能性,以下行可能指的是错误的对象(test_car什么时候应该是菜单?),但如果没有其余的代码,我真的无法判断。

self.test_car.event_handler()

但如果这应该发生,那么在test_car.event_handler你调用self.state_change的那个可能不会改变你所期望的状态,因为到那时,菜单self是而不是实际的。test_car这意味着您永远不会真正更改menu.state(或任何main_loop正在运行的对象),而是在更改test_car.state.

于 2013-01-31T04:36:18.483 回答
1

我认为您使事情变得有些复杂-您真的需要 check_state 和 set_state 函数以及两个变量吗?

我会做这样的事情:

class State(object):
    menu = "menu"
    play = "play"

class Game(??):

    def event_handler(self):
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_m:
                    self.state = State.menu
                    print "Key Pressed: m"
                elif event.key == K_p:
                    self.state = State.play
                    print "Key Pressed: p"

    def game_loop(self):
        self.state = State.menu

        while running:
            if self.state is State.menu:
                # Do menu things
            elif self.state is State.play:
                # Play game! 
于 2013-01-31T04:41:56.863 回答
0

您在运行循环中一个接一个地使用两个if语句。尝试改用ifelif语句。

于 2013-01-31T04:41:14.217 回答
0

我相信你已经使你的游戏状态管理复杂化了。

  1. 不需要功能,
    • state_change
    • state_check.
  2. 或用于处理状态的 2 个变量。
    • self.state
    • self.current_state

对于游戏状态,您可以使用一个变量
- <type 'bool'>如果有 2 个。
- <type 'int'>如果有超过 2 个。
但是使用字符串使代码可读。

在这种情况下,即使是 1 个变量也可以,(见下文)
建议使用 2 个变量
1. Atuple包含所有可能的状态。
2. 当前状态、价值或指数(参考tuple

这种方法也适用于更多状态,为您提供开发更多状态的空间,而无需太多管理麻烦,

如何?
看下面的代码和2个变量的使用

  1. self.state
  2. self.states

代码:

class Game:

    def __init__(...):
        self.states = ('menu','play')
        self.state = 0

    def events_play(self):
        for event in pygame.event.get():
            # event handling
                self.state = self.states[0]

    def events_menu(self):
        for event in pygame.event.get():
            # event handling
                self.state = self.states[1]

    def game_loop(self):

        while running:
            if self.state == 'menu':
                # I always handle events first :)
                self.events_menu()
                # Do menu things

            elif self.state == 'play':
                # I always handle events first :)
                self.events_play()
                # Play game!
于 2013-01-31T14:02:07.800 回答