#   _*_ coding:utf-8 _*_
from random import randint
import sys
import pygame
from pygame.locals import *
from gameobjects.vector2 import Vector2
import time__author__ = 'admin''''蚂蚁状态机(五)问题:蚂蚁找到叶子后,叶子的图屏无法跟随蚂蚁移动回巢原因:叶子的leaf_position属性不会受外界的改变而改变,始终是由其location产生的解决:改变其location属性总结:对象类中不必再定义各类的位置属性,使用ObjProduct的location即可,并重新命名为position
'''SCREEN_SIZE = (640, 480)
NEST_POSITION = (320, 240)
NEST_SIZE = 100.WHITE = (255, 255, 255)clock = pygame.time.Clock()class Microcosm(object):def __init__(self):self.objects_dict = {}self.obj_id = 0self.objects_list = []def addObj(self, obj):self.objects_list.append(obj)self.objects_dict[self.obj_id] = obj#   是在这个位置为对象附上id属性的,下面删除字典元素时要用到这个idobj.id = self.obj_idself.obj_id += 1def getObj(self, obj_id):return self.objects_dict[obj_id]def get_closeTo_obj(self, name, position, range=50):for obj in self.objects_dict.values():if obj.name == name:distance = position.get_distance_to(obj.position)if distance <= range:return objreturn None#   绘制方法存在这里,每个继承的子类都在这里绘制,无需在每个对象类中再绘制了#   每个对象类中只需要实时的变更其位置即可def draw(self, surface):surface.fill(WHITE)pygame.draw.circle(surface, (200, 255, 200), NEST_POSITION, int(NEST_SIZE))for obj in self.objects_dict.values():obj.draw(surface)class ObjProduct(object):def __init__(self, microcosm, name, path):self.microcosm = microcosmself.name = nameself.image_path = pathself.image = pygame.image.load(self.image_path).convert_alpha()self.state = 0self.fsm = Noneself.id = 0self.speed = 0self.position = Vector2(0, 0)self.destination = Vector2(0, 0)def bind(self, state, fsm):self.fsm = fsmself.state = statedef draw(self, surface):x, y = self.positionw, h = self.image.get_size()surface.blit(self.image, (x - w / 2, y - h / 2))class Leaf(ObjProduct):def __init__(self, microcosm, name, path):ObjProduct.__init__(self, microcosm, name, path)self.position = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))def draw(self, surface):ObjProduct.draw(self, surface)class Ant(ObjProduct):def __init__(self, microcosm, name, path):ObjProduct.__init__(self, microcosm, name, path)self.position = Vector2(100, 100)self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))#   这里让leaf_id为None,单纯就是不想给它一个数字而已,避免这个默认值作为Key使用时报错self.leaf_id = Nonedef draw(self, surface):ObjProduct.draw(self, surface)def explore(self):print("探索中.....")distance = self.destination - self.position#   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)x = self.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.position += headingdef wait(self):print("停顿下,思考人生.....")pygame.time.delay(10)class State(object):def exec(self, obj):passdef exit(self, obj):passclass ExploreState(State):def exec(self, obj):#   决定探索过程中触发wait的频率if randint(1, 1000) == 1:#   信号置为0obj.state = 0else:#   判断当前蚂蚁对象附近范围内是否有叶子存在,并获取这个叶子对象leaf_ = obj.microcosm.get_closeTo_obj('leaf', obj.position)#   如果有这样的叶子对象if leaf_ is not None:#   为当前蚂蚁对象添加该目标叶子id属性(将该叶子绑定到该蚂蚁上,方便调用)obj.leaf_id = leaf_.id#   信号置为seekobj.state = 2else:#   附近没有叶子就执行exploreobj.explore()class WaitSate(State):def exec(self, obj):#   执行wait方法obj.wait()#   信号置为1,使得蚂蚁再动起来obj.state = 1class SeekState(State):def exec(self, obj):#   当前蚂蚁对象是否绑定了leaf_id属性(这点可以说明蚂蚁附近是否有叶子)if obj.leaf_id is not None:#   通过已知的叶子id获取对应的叶子对象leaf_ = obj.microcosm.getObj(obj.leaf_id)print("发现目标叶子..走过去")#   将叶子的位置当做蚂蚁本次行为的终点obj.destination = leaf_.position#   获取此时蚂蚁起点->终点的向量distance = obj.destination - obj.position#   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)x = obj.position.get_distance_to(obj.destination)#   获取单位向量,即每次蚂蚁移动的向量heading = distance.normalise()#   如果蚂蚁再移动单位向量就会越过目标点if x <= heading.get_length():print("已达到目标叶子")#   让蚂蚁吃掉叶子,即在字典和列表中删除叶子对象,以防止下一次explore时蚂蚁距离该叶子还很近再被拉回# obj.microcosm.objects_dict.pop(leaf_.id)# obj.microcosm.objects_list.remove(leaf_)#   将该蚂蚁绑定的叶子id置为None# obj.leaf_id = None#   将信号置为3, 将叶子搬回巢穴obj.state = 3#   蚂蚁还未到达叶子,即还需要继续走一个headingelse:obj.position += heading#   继续执行seekingobj.state = 2else:#   当前蚂蚁附近没有叶子了,执行探索obj.state = 1class TransState(State):def exec(self, obj):leaf_ = obj.microcosm.getObj(obj.leaf_id)print("拾起叶子,走回巢穴...")#   通过蚂蚁当前的位置确定其拾取到的叶子的位置-----》待优化leaf_.position = Vector2(obj.position)print(leaf_.position)#   将巢穴的位置当做蚂蚁本次行为的终点obj.destination = Vector2(NEST_POSITION)#   获取此时蚂蚁起点->终点的向量distance = obj.destination - obj.position#   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)x = obj.position.get_distance_to(obj.destination)#   获取单位向量,即每次蚂蚁移动的向量heading = distance.normalise()#   如果蚂蚁再移动单位向量就会越过目标点if x <= heading.get_length():print("已回到巢穴之中")#   让蚂蚁吃掉叶子,即在字典和列表中删除叶子对象,以防止下一次explore时蚂蚁距离该叶子还很近再被拉回obj.microcosm.objects_dict.pop(leaf_.id)obj.microcosm.objects_list.remove(leaf_)#   将该蚂蚁绑定的叶子id置为Noneobj.leaf_id = None#   信号置为1,继续探索obj.state = 1else:obj.position += heading#   还未将叶子运回巢穴之内,继续transobj.state = 3class StateMachine(object):def __init__(self):#   状态集合self.states = {0: WaitSate(), 1: ExploreState(), 2: SeekState(), 3: TransState()}#   改变状态def changeState(self, objs):for obj in objs:#   这里先留着吧,考虑下state是否有为None的必要if obj.state is None:returnelse:if obj.name == 'leaf':#   无状态,不做处理,其实也可以在外层先过滤掉leaf对象passelse:print("name[%s]--state[%d]" % (obj.name, obj.state))newFsm = self.states[obj.state]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()pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)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)while True:checkForOut()#   生出叶子if randint(1, 500) == 1:leaf = Leaf(micr, 'leaf', r"E:\PycharmProjects\PGStudy\resource\leaf.png")leaf.bind(0, sm.states[0])micr.addObj(leaf)#   将绘制方法全部封装,每次循环重刷屏幕上所有对象micr.draw(screen)sm.changeState(micr.objects_list)pygame.display.update()pygame.time.delay(10)

PyGmae:有限状态机实践(五)相关推荐

  1. nodejs 实践:express 最佳实践(五) connect解析

    nodejs 实践:express 最佳实践(五) connect解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固,需 ...

  2. PyGmae:有限状态机实践(十四)

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

  3. PyGmae:有限状态机实践(十三)

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

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

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

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

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

  6. 单片机c语言 oxfe,AVR单片机入门及C语言高效设计实践(五)

    ATMEAGl6L的中断系统什么是"中断"?顾名思义中断就是中断某一工作过程去处理一些与本工作过程无关或间接相关或临时发生的事件,处理完后,则继续原工作过程.比如:你在看书,电话响 ...

  7. 推荐系统实践(五)----基于图的推荐算法

      基于图的模型(graph−basedmodelgraph-based modelgraph−basedmodel)是推荐系统中的重要内容.在研究基于图的模型之前,首先需要将用户行为数据表示成图的形 ...

  8. linux内核增加emc拨号功能,[转载]EMC存储最佳实践(五)

    二.为可用性和冗余做考虑 一个可靠的和冗余的存储网络以SAN的设计开始,这已经超越了这个白皮书的范围.但是,一些存储系统设计方面的问题----例如硬盘和RAID组的选择---是存储系统理所当然的课题. ...

  9. websocket心跳链接代码_WebSocket原理与实践(五)--心跳及重连机制

    在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件.这样会有:服务器会继续向客户端发送多余的链接,并且这些数据还会丢失.所以就需要 ...

最新文章

  1. (zz)编译Ubuntu Linux内核
  2. 软件项目组织管理(七)项目成本管理
  3. power bi连接mysql_一起学微软Power BI系列-使用技巧(6) 连接Sqlite数据库
  4. 获取参数(可以是中文)
  5. Sublime Text 3中SublimeLinter的使用
  6. 知识管理系统Data Solution研发日记之七 源代码与解决方案
  7. linux vi替换字符串
  8. 10位Swift和iOS开发大师
  9. 毕向东_Java基础
  10. java gis 矢量数据结构_2.4. 矢量数据结构
  11. 如何做好应用架构分层和模块化?
  12. 【安全狐】CVE-2015-5254_ActiveMQ反序列化漏洞复现
  13. 为什么要了解和使用拉姆达——走进Java Lambda(〇)
  14. 通过U盘安装Windows11时遇此设备不支持升级时的解决办法
  15. 还想野蛮生长?互联网金融有《意见》了
  16. 淘宝SEO优化提高流量的绝密办法
  17. Java程序性能优化——设计优化
  18. 写技术指标的一般方法
  19. 机器学习线性回归实践,广告投放收益预测,手写梯度下降
  20. 南京2级计算机成绩查询,南京审计大学教务管理系统登录入口、成绩查询网上选课查分...

热门文章

  1. asp.net mvc Html.BeginForm()用法
  2. 针对《评人工智能如何走向新阶段》一文,继续发布国内外的跟贴留言503-531条如下:
  3. 一位职场老前辈呕心沥血总结的心得
  4. 图像采集数据集整理和扩充方案(含代码)
  5. html5+css3满天星星音乐背景动画特效(超炫酷)
  6. 渣渣的Leetcode之旅(Python3)_打卡(12,15,917,7,8)
  7. macOS怎样备份?备份Mac文件的最佳方法
  8. 并发编程常见面试题Synchronized 相 关 问 题
  9. c语言打印a-Z字母的方法
  10. kafka中Topic、Partition、Groups、Brokers概念辨析