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

本文介绍了一个基于Python和Pygame的游戏项目,实现了蚂蚁状态机的等待与探索机制,以及蚂蚁与屏幕中随机生成的叶子进行交互的过程。文章详细描述了如何通过状态机控制蚂蚁的行为,包括探索、等待和寻找叶子,以及叶子的随机生成和蚂蚁将其吃掉的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

__author__ = 'admin'

'''
    蚂蚁状态机(二)
    目标1:实现蚂蚁的状态机,并实现蚂蚁的等待和探索机制
    已完成信号0/1,状态WaitSate/ExploreState
    目标2:实现在屏幕中生成叶子Leaf
    已完成
    目标3:如果蚂蚁活动范围内100像素内存下叶子,则奔向叶子
    之前不成功的原因是因为没有为各个对象绑定micr,以致于micr中objects_dict不能被所有对象共享使用
    已经实现蚂蚁全屏搜索叶子吗,遇到叶子并将叶子吃掉
    目标4:在屏幕上若有一个叶子被吃掉,再生出一个叶子
    可以实现,只要将生成叶子的循环处加一个变量控制即可,即总叶子数-剩余叶子数=要生产的叶子数
    目标5:实现叶子随机产生,不固定数目
    已经实现,比目标4要简单的多
    目标6:实现蚂蚁将叶子搬回蚁巢
    待实现
'''

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 Microcosm(object):
    def __init__(self):
        self.objects_dict = {}
        self.obj_id = 0
        self.objects_list = []

    def addObj(self, obj):
        self.objects_list.append(obj)
        self.objects_dict[self.obj_id] = obj
        #   是在这个位置为对象附上id属性的,下面删除字典元素时要用到这个id
        obj.id = self.obj_id
        self.obj_id += 1

    def getObj(self, obj_id):
        return self.objects[obj_id]

    def get_closeTo_obj(self, name, location, range=50):
        for obj in self.objects_dict.values():
            if obj.name == name:
                distance = location.get_distance_to(obj.location)
                if distance <= range:
                    return obj
        return None


class ObjProduct(object):
    def __init__(self, microcosm, name, path):
        self.microcosm = microcosm
        self.name = name
        self.op_path = path
        self.op = pygame.image.load(self.op_path).convert_alpha()
        self.state = 0
        self.fsm = None
        self.id = 0
        self.speed = 0
        self.location = Vector2(0, 0)
        self.destination = Vector2(0, 0)

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


class Leaf(ObjProduct):
    def __init__(self, microcosm, name, path):
        ObjProduct.__init__(self, microcosm, name, path)
        self.leaf = self.op
        self.location = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))
        self.leaf_position = self.location
        self.draw(self.leaf_position)

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

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

class Ant(ObjProduct):
    def __init__(self, microcosm, name, path):
        ObjProduct.__init__(self, microcosm, name, path)
        self.ant = self.op
        self.location = Vector2(100, 100)
        self.ant_position = self.location
        self.draw(self.ant_position)
        self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))

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

    def explore(self):
        # print("探索中.....")
        distance = self.destination - self.ant_position
        #   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)
        x = self.ant_position.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_position += heading
            self.draw(self.ant_position)

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

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

    def exit(self, obj):
        pass


class ExploreState(State):
    def exec(self, obj):
        leaf_ = obj.microcosm.get_closeTo_obj('leaf', obj.location)
        if leaf_ is not None:
            # print("发现目标叶子")
            obj.destination = leaf_.location
            distance = obj.destination - obj.ant_position
            #   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)
            x = obj.ant_position.get_distance_to(obj.destination)
            #   获取单位向量,即每次蚂蚁移动的向量
            heading = distance.normalise()
            #   如果蚂蚁再移动单位向量就会越过目标点
            if x <= heading.get_length():
                #   让蚂蚁吃掉叶子,即在字典和列表中删除叶子对象,以防止下一次explore时蚂蚁距离该叶子还很近再被拉回
                obj.microcosm.objects_dict.pop(leaf_.id)
                obj.microcosm.objects_list.remove(leaf_)
        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()


micr = Microcosm()
sm = StateMachine()
for i in range(1):
    ant = Ant(micr, 'ant', r"E:\PycharmProjects\PGStudy\resource\ant.png")
    ant.bind(0, sm.states[0])
    micr.addObj(ant)
left_ln = 0
while True:
    checkForOut()
    screen.fill(WHITE)
    pygame.draw.circle(screen, (200, 255, 200), NEST_POSITION, int(NEST_SIZE))
    if randint(1, 100) == 1:
        leaf = Leaf(micr, 'leaf', r"E:\PycharmProjects\PGStudy\resource\leaf.png")
        leaf.bind(0, sm.states[0])
        micr.addObj(leaf)
    #   用于控制蚂蚁的停顿状态
    if randint(0, 50) == -1:
        state = 0
    else:
        state = 1
    sm.changeState(state, micr.objects_list)
    pygame.display.update()
    pygame.time.delay(10)

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值