PyGmae:有限状态机实践(一)

之前在在学习PyGame这一部分的时候,遇到了一个难题就是有限状态机。这个知识点理解起来很容易,谁都可以听得懂,若要你亲自写写代码来实践下就很困难了。我的困惑同时也产生了,困惑源自于一位python学者的博客里面讲解的有限状态机的部分,他实现了一个蚂蚁+叶子+蜘蛛的状态机,其机制及三个对象之间的关系我这里就不赘述了,附上地址供你自行参考。那么困惑是什么呢?我看到那位博主写的代码后有些惊叹,“原来状态机可以这么玩,就仿照他的代码练习下吧”,之后发现不知道从哪里入手。他的代码里有Ant类、Spider类、Leaf类、又有StateMachine类,总而言之很是让人费解,“为什么要有这么多的类,他怎么就知道这样写呢?”。本着有因必有果的想法,我仍认为“写代码肯定是有一个起始状态的,之后发现这个代码可以扩充下,那就扩充下喽”。

所以呢,之后的几篇博客都是我按照自己的想法来梳理并体会了下那位博主写代码的过程(这个过程只是我想像的)

有些地方实在想不通的我也参照了那位博主的代码,也是他的代码给了我答案。

#   _*_ coding:utf-8 _*_
from random import randint
import sys
import pygame
from pygame.locals import *
from gameobjects.vector2 import Vector2
import time

__author__ = 'admin'

'''
    蚂蚁状态机(一)
    实现了蚂蚁全屏探索
    实现了产生叶子
    进阶:蚂蚁自动寻至产生的叶子
'''

SCREEN_SIZE = (640, 480)
NEST_POSITION = (320, 240)
NEST_SIZE = 100.

WHITE = (255, 255, 255)
pygame.init()

screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
clock = pygame.time.Clock()


class Leaf(object):
    def __init__(self):
        self.name = 'leaf'
        self.leaf_path = r"E:\PycharmProjects\PGStudy\resource\leaf.png"
        self.leaf = pygame.image.load(self.leaf_path).convert_alpha()
        self.leaf_location = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))
        self.draw(self.leaf_location)
        self.state = 0
        self.fsm = None

    def draw(self, location):
        screen.blit(self.leaf, location)

    def wait(self):
        self.draw(self.leaf_location)

    def bind(self, state, fsm):
        self.fsm = fsm
        self.state = state

class Ant(object):
    def __init__(self):
        self.name = 'ant'
        self.ant_location = Vector2(100, 100)
        self.ant_path = r"E:\PycharmProjects\PGStudy\resource\ant.png"
        self.ant = pygame.image.load(self.ant_path).convert_alpha()
        self.ant_width, self.ant_height = self.ant.get_size()
        self.ant = pygame.transform.smoothscale(self.ant, (self.ant_width // 1, self.ant_height // 1))
        self.draw(self.ant_location)
        self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))
        self.state = 0
        self.fsm = None

    def draw(self, location):
        screen.blit(self.ant, location)

    def explore(self):
        print("探索中.....")
        distance = self.destination - self.ant_location
        #   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)
        x = self.ant_location.get_distance_to(self.destination)
        #   获取单位向量,即每次蚂蚁移动的向量
        heading = distance.normalise()
        #   如果蚂蚁再移动单位向量就会越过目标点
        if x <= heading.get_length():
            # print("到达目的地了....前往下一个点")
            self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))
        else:
            self.ant_location += heading
            self.draw(self.ant_location)

    def wait(self):
        print("停顿下,思考人生.....")
        self.draw(self.ant_location)

    def bind(self, state, fsm):
        self.fsm = fsm
        self.state = state


class State(object):
    def exec(self, obj):
        pass

    def exit(self, obj):
        pass


class ExploreState(State):
    def exec(self, obj):
        obj.explore()


class WaitSate(State):
    def exec(self, obj):
        obj.wait()


class StateMachine(object):
    def __init__(self):
        self.states = {0: WaitSate(), 1: ExploreState()}

    def changeState(self, newState, objs):
        for obj in objs:
            if obj.name == 'leaf':
                curFsm = self.states[0]
                curFsm.exec(obj)
            elif obj.name == 'ant':
                if newState == obj.state:
                    oldFsm = self.states[obj.state]
                    oldFsm.exec(obj)
                else:
                    newFsm = self.states[newState]
                    newFsm.exec(obj)


def checkForOut():
    for event in pygame.event.get():
        if event.type == 12:
            sys.exit()
        if event.type == 2:
            if event.key == 27:
                exit()

objs = []
sm = StateMachine()
ant = Ant()
ant.bind(0, sm.states[0])
objs.append(ant)

leaf = Leaf()
leaf.bind(0, sm.states[0])
objs.append(leaf)

ant.destination = leaf.leaf_location
while True:
    checkForOut()
    screen.fill(WHITE)
    pygame.draw.circle(screen, (200, 255, 200), NEST_POSITION, int(NEST_SIZE))
    #   用于控制蚂蚁的停顿状态
    if randint(0, 50) == -1:
        state = 0
    else:
        state = 1
    sm.changeState(state, objs)
    pygame.display.update()
    pygame.time.delay(10)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值