微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

pygame如何处理状态

如何解决pygame如何处理状态

我最近用pygame用python完成了一个四连体类型的游戏。任一玩家获胜后,它会显示一个菜单,询问您是否要再次玩还是退出,每个选项都有一个按钮。程序根据Game类中的变量(包含游戏的状态)来确定是运行游戏还是显示菜单。问题是我然后必须在程序中的几个点上有一个if-elif子句才能看到要做什么。例如,在Game.draw方法中,它绘制游戏板和棋子或菜单Game.on_click方法将事件发送到游戏板或菜单中的按钮,等等。我的问题是,有没有一种方法可以跟踪游戏状态,而无需在整个程序中分散if-elif子句?

game.py:

import pygame

from board import Board
from player import Player
from button import Button
from constants import (
    BLACK,RED,YELLOW,GREEN,WHITE,SQUARE_SIZE,ROWS,WIDTH,HEIGHT
)


class Game:
    PLAYING = 0
    HAS_WON = 1

    def __init__(self,win):
        self.win = win
        # self.running = True
        self.state = self.PLAYING
        self.running = True
        self.board = Board()

        self.players = [Player(RED,self.board),Player(YELLOW,self.board)]
        self.player_turn_counter = 0

        pygame.font.init()
        self.font = pygame.font.SysFont("Arial",36)
        self.text = ""

        play_again_xpos = WIDTH // 5
        play_again_ypos = (HEIGHT // 5) * 4
        play_again_button = Button("Play Again",self.play_again,xpos=play_again_xpos,ypos=play_again_ypos,show_border=True,border_color=(255,255,255))

        quit_xpos = (WIDTH // 5) * 4
        quit_ypos = (HEIGHT // 5) * 4
        quit_button = Button("Quit",self.quit,xpos=quit_xpos,ypos=quit_ypos,255))

        self.buttons = [play_again_button,quit_button]

    def play_again(self):
        self.__init__(self.win)
        self.run()

    def quit(self):
        self.running = False

    def draw(self):
        self.win.fill(BLACK)
        self.board.draw(self.win)
        if self.state == self.HAS_WON:
            # self.win.fill(WHITE)
            text = self.font.render(self.text,True,WHITE)

            text_rect = text.get_rect()
            text_rect.centerx = WIDTH // 2
            text_rect.centery = ((SQUARE_SIZE * ROWS) // 3) - SQUARE_SIZE // 2

            self.win.blit(text,text_rect)

            for button in self.buttons:
                button.draw(self.win)
            # self.play_again_button.draw(self.win)
            # self.quit_button.draw(self.win)

        pygame.display.update()

    def is_full(self,column):
        board = self.board.get_board()
        # pieces = []

        # for row in board:
        #     pieces.append(row[column])

        # return all(pieces)
        return all([row[column] for row in board])

    def on_win(self,color):
        self.state = self.HAS_WON
        colors = {(255,0): "Yellow",(255,0): "Red"}
        self.text = f"{colors[color]} has won!"
        # print(f"{colors[color]} has won!")

    def on_click(self):
        if self.state == self.PLAYING:
            column = self.board.get_column()
            if not self.is_full(column):
                self.player_turn_counter += 1
                self.player_turn_counter = self.player_turn_counter % 2
            self.players[self.player_turn_counter].on_click()
            has_won,color = self.board.check_for_win()
            if has_won:
                self.on_win(color)
        elif self.state == self.HAS_WON:
            for button in self.buttons:
                button.on_click()

    def run(self):
        clock = pygame.time.Clock()

        while self.running:
            clock.tick(60)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False

                if event.type == pygame.MOUSEBUTTONDOWN:
                    self.on_click()

            self.draw()

这里是整个程序的github仓库: https://github.com/pianocomposer321/ConnectFour.git

解决方法

创建两个具有相同接口的类,每个状态一个。这些类包含与游戏状态相关的实现:

class Playing:
    def __init__(self,game)
        self.game = game

    def draw(self):
        # [...]

    def on_click(self):
        # [...]
class HasWon:
    def __init__(self,game):
        self.game = game

    def draw(self):
        # [...]

    def on_click(self):
        # [...]

Game 类使用实现游戏状态的类。附加属性 (self.current) 指的是当前的 state 类。附加方法 (set_state) 切换状态变量并根据状态设置 self.current。这是程序中唯一需要if - elif 子句的点。在其他方法中,您可以委托给游戏状态实现的实现方法(例如self.current.draw()self.current.on_click()):

class Game:
    PLAYING = 0
    HAS_WON = 1

    def __init__(self,win):
        # [...]

        self.playing = Playing(self)
        self.haswon = HasWon(self)
        self.set_state(self.PLAYING)
        
    def set_state(new_state):
        self.state = self.PLAYING
        if self.state == self.PLAYING:
            self.current = self.playing
        elif self.state == self.HAS_WON:
            self.current = self.haswon

    def draw(self):
        self.win.fill(BLACK)
        self.board.draw(self.win)
        
        self.current.draw()

        pygame.display.update()

    def on_win(self,color):
        self.set_state(self.HAS_WON)
        # [...]
        

    def on_click(self):
        self.current.on_click()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。