# _*_ 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()