Pygame:有限状态机实例(二)

本文深入探讨如何在Pygame游戏中应用有限状态机(FSM)概念,通过实例详细解释了状态转换和事件处理,以提升游戏逻辑的组织和管理。
#   _*_ coding:utf-8 _*_
from random import randint
from time import sleep
import pygame

__author__ = 'admin'

pygame.init()
SCREEN_SIZE = (640, 320)
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)

WHITE = (255, 255, 255)
RED = (255, 0, 0)
DARK_RED = (128, 0, 0)
GREEN = (0, 255, 0)
DARK_GREEN = (0, 128, 0)
GREY = (192, 192, 192)


class Light(object):
    def __init__(self, name, color, pos):
        self.name = name
        #   在屏幕中画出生成的对象light
        self.size = (40, 40)
        self.width, self.height = self.size
        self.color = color
        self.pos = pos
        self.rect_light = pygame.Rect(self.pos, self.size)
        self.draw(self.color)
        #   初始化light的状态和对应的状态机
        self.state = 0
        self.fsm = None

    #   绘制light的方法
    def draw(self, light_color):
        pygame.draw.rect(screen, light_color, self.rect_light)

    #   开灯方法
    def lightOn(self, on_color):
        print("[%s]灯亮着" % self.name)
        self.draw(on_color)

    #   关灯方法
    def lightOff(self, off_color):
        print("[%s]灯灭着" % self.name)
        self.draw(off_color)

    #   坏灯方法
    def lightBroken(self, broken_color):
        print("[%s]灯被玩坏了" % self.name)
        self.draw(broken_color)

    #   修灯方法
    def lightRepair(self, off_color):
        print("[%s]灯被修中...修复完成" % self.name)
        self.draw(off_color)

    #   为light对象绑定状态机
    def bind(self, state, fsm):
        self.fsm = fsm
        self.state = state

#   定义状态类
class State(object):
    def exec(self, obj, color):
        pass

    def exit(self, obj, color):
        pass

#   开灯状态类
class OnState(State):
    def exec(self, obj, on_color):
        obj.lightOn(on_color)

#   关灯状态类
class OffState(State):
    def exec(self, obj, off_color):
        obj.lightOff(off_color)

#   坏灯状态类
class BrokenState(State):
    def exec(self, obj, broken_color):
        obj.lightBroken(broken_color)

#   修灯状态类
class RepairState(State):
    def exec(self, obj, repair_color):
        obj.lightRepair(repair_color)

class StateMachine(object):
    def __init__(self):
        #   name与颜色对应,两种状态分贝为另外的两种颜色
        self.light_color = {'red': {0: RED, 1: GREY, 2: DARK_RED, 3: GREY}, 'green': {0: GREEN, 1: GREY, 2: DARK_GREEN, 3: GREY}}
        #   light的几种状态机和对应的信号
        self.states = {0: OnState(), 1: OffState(), 2: BrokenState(), 3: RepairState()}

    #   依据给定的信号获取对应的状态机
    def get_fsm(self, state):
        return self.states[state]

    #   获取信号
    def createSignal(self):
        return randint(0, 3)

    #   这里是最主要的,变更对象的状态
    # def changeState(self, newState, objs):
    def changeState(self, objs):
        for obj in objs:
            newState = self.createSignal()
            #   新信号与原来的信号一致,light的状态不发生变化
            if newState == obj.state:
                newColor = self.light_color[obj.name][obj.state]
                newFsm = self.get_fsm(obj.state)
                newFsm.exec(obj, newColor)
            else:
                #   灯处于坏着的状态时无法被点亮或者关闭的,所以对此类信号屏蔽
                if obj.state == 2 and newState in [0, 1]:
                    print("Current signal[%d]:[%s]灯坏了,无法点亮/关闭!" % (newState, obj.name))
                    newState = obj.state
                #   灯处于正常工作的状态时无需再进行修复,所以对此类信号屏蔽
                if obj.state in [0, 1] and newState == 3:
                    print("Current signal[%d]:[%s]灯正常工作,无需修复!" % (newState, obj.name))
                    newState = obj.state
                obj.state = newState
                obj.fsm = self.get_fsm(newState)
                obj.fsm.exec(obj, self.light_color[obj.name][newState])

# 退出检测函数
def checkForOut():
    for event in pygame.event.get():
        #   点击×
        if event.type == 12:
            exit()
        if event.type == 2:
            #   按键为Esc
            if event.key == 27:
                exit()

def run():
    #   实例化状态机管理器
    sm = StateMachine()
    #   生产2个light对象
    l = []
    l1 = Light('red', RED, (140, 140))
    l1.bind(1, sm.get_fsm(1))
    l.append(l1)
    l2 = Light('green', RED, (460, 140))
    l2.bind(1, sm.get_fsm(1))
    l.append(l2)
    #   判定循环
    while True:
        #   检测退出
        checkForOut()
        #   刷新屏幕
        screen.fill(WHITE)
        #   执行状态切换
        sm.changeState(l)
        pygame.display.update()
        #   延迟
        sleep(2)
run()

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值