#   _*_ coding:utf-8 _*_
from random import randint
import sys
import pygame
from pygame.locals import *
from gameobjects.vector2 import Vector2
import time__author__ = 'admin''''蚂蚁状态机(十二)新问题:蚂蚁还未将蜘蛛击杀就跑去拾取叶子了解决:HuntState中当obj.explore()返回为False时,说明ant还未追击到蜘蛛再将信号置为hunt,继续追击'''
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.capricious_dict = {}self.obj_id = 0self.capricious_list = []def addObj(self, obj):#   在changeState方法中需要传入一个包含所有蚂蚁对象的列表,这个列表中也包含有未被拾取的叶子self.capricious_list.append(obj)#   用于存储程序运行之后生成的所有对象及其对应的idself.objects_dict[self.obj_id] = obj#   道理同objects_dict,只不过该dict会不断的被添加和删除,主要是确定哪些叶子允许被蚂蚁seekself.capricious_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.capricious_dict.values():if obj.name == name:distance = position.get_distance_to(obj.position)if distance <= range:return objreturn Nonedef get_obj_InNest(self, name):for obj in self.capricious_dict.values():if obj.name == name:distance = obj.position.get_distance_to(NEST_POSITION)if distance < NEST_SIZE: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))def explore(self):print("[%s-%d]探索中....." % (self.name, self.id))distance = self.destination - self.position#   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)x = self.position.get_distance_to(self.destination)#   获取单位向量,即每次蚂蚁移动的向量heading = distance.normalise()#   如果蚂蚁再移动单位向量就会越过目标点if x <= heading.get_length():print("[%s-%d]到达目的地了....前往下一个点" % (self.name, self.id))# self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))return Trueelse:self.position += headingclass Spider(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))self.health = 25def draw(self, surface):ObjProduct.draw(self, surface)#   为蜘蛛增加血条,依据health进行血量调整x, y = self.positionw, h = self.image.get_size()blood_x = x - w / 2blood_y = y + h / 2screen.fill((255, 0, 0), (blood_x, blood_y, 25, 4))screen.fill((0, 255, 0), (blood_x, blood_y, self.health, 4))def wait(self):print("[%s-%d]停顿下,思考人生....." % (self.name, self.id))pygame.time.delay(10)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(NEST_POSITION)self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))#   这里让leaf_id为None,单纯就是不想给它一个数字而已,避免这个默认值作为Key使用时报错self.leaf_id = None#   这里让leaf_id为None,单纯就是不想给它一个数字而已,避免这个默认值作为Key使用时报错self.spider_id = Nonedef draw(self, surface):ObjProduct.draw(self, surface)def wait(self):print("[%s-%d]停顿下,思考人生....." % (self.name, self.id))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:if obj.name == 'ant':#   检测此时是否有蜘蛛进入巢穴spider_ = obj.microcosm.get_obj_InNest('spider')#   如果有这样的蜘蛛对象if spider_ is not None:#   为当前蚂蚁对象添加该目标蜘蛛id属性(将该蜘蛛绑定到该蚂蚁上,方便调用)obj.spider_id = spider_.idobj.state = 4else:#   判断当前蚂蚁对象附近范围内是否有叶子存在,并获取这个叶子对象leaf_ = obj.microcosm.get_closeTo_obj('leaf', obj.position)#   如果有这样的叶子对象if leaf_ is not None:#   为当前蚂蚁对象添加该目标叶子id属性(将该叶子绑定到该蚂蚁上,方便调用)obj.leaf_id = leaf_.id#   信号置为seekobj.state = 2else:#   附近没有叶子就执行exploreif obj.explore():obj.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))elif obj.name == 'spider':if obj.explore():obj.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))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:#   当前蚂蚁已经有了叶子目标,capricious_dict中该叶子还未被删除,说明未被其他蚂蚁抢先拾取if obj.leaf_id in obj.microcosm.capricious_dict.keys():print("[%s-%d]发现目标叶子..走过去" % (obj.name, obj.id))#   通过已知的叶子id获取对应的叶子对象leaf_ = obj.microcosm.getObj(obj.leaf_id)#   将叶子的位置当做蚂蚁本次行为的终点obj.destination = leaf_.positionif obj.explore():print("[%s-%d]已达到目标叶子" % (obj.name, obj.id))#   将该叶子移出capricious_dict中,起到不可被seek的作用obj.microcosm.capricious_dict.pop(leaf_.id)obj.microcosm.capricious_list.remove(leaf_)#   将巢穴范围内随机的一个位置当做蚂蚁TransState的终点obj.destination = Vector2(NEST_POSITION) + Vector2(randint(-40, 40), randint(-40, 40))obj.state = 3else:#   当前蚂蚁锁定的叶子被其他蚂蚁抢先拾取print("[%s-%d]的叶子被别的蚂蚁抢先拾取...." % (obj.name, obj.id))#   叶子被别的蚂蚁抢先拾取,则把该蚂蚁绑定的叶子id置为None吧obj.leaf_id = Noneobj.state = 1else:#   当前蚂蚁附近没有叶子了,执行探索obj.state = 1class TransState(State):def exec(self, obj):leaf_ = obj.microcosm.getObj(obj.leaf_id)print("[%s-%d]拾起叶子,走回巢穴..." % (obj.name, obj.id))#   通过蚂蚁当前的位置确定其拾取到的叶子的位置-----》待优化leaf_.position = Vector2(obj.position)#   获取此时蚂蚁起点->终点的向量distance = obj.destination - obj.position#   获取此时蚂蚁距离目标点间的向量长度(即两点间的实际距离)x = obj.position.get_distance_to(obj.destination)#   获取单位向量,即每次蚂蚁移动的向量heading = distance.normalise()#   如果蚂蚁再移动单位向量就会越过目标点if x <= heading.get_length():# print("[Ant-%d]已回到巢穴之中" % obj.id)#   将该蚂蚁绑定的叶子id置为Noneobj.leaf_id = None#   信号置为1,继续探索obj.state = 1else:obj.position += heading#   还未将叶子运回巢穴之内,继续transobj.state = 3class HuntState(State):def exec(self, obj):#   当前蚂蚁已经有了蜘蛛目标,capricious_dict中该蜘蛛还未被删除,说明该蜘蛛还未死亡if obj.spider_id in obj.microcosm.capricious_dict.keys():print("[%s-%d]发现目标蜘蛛..走过去" % (obj.name, obj.id))spider_ = obj.microcosm.getObj(obj.spider_id)obj.destination = spider_.positionif obj.explore():print("[%s-%d]已经追击到蜘蛛" % (obj.name, obj.id))#   这里模拟攻击状态--------》待优化if randint(1, 1) == 1:print("[%s-%d]正在攻击蜘蛛" % (obj.name, obj.id))spider_.health -= 1if spider_.health <= 0:#   将该叶子移出capricious_dict中,起到不可被seek的作用,这里其实也应该将objects_dict中的该蜘蛛删除obj.microcosm.capricious_dict.pop(spider_.id)obj.microcosm.capricious_list.remove(spider_)obj.microcosm.objects_dict.pop(spider_.id)obj.spider_id = None#   蜘蛛已死,进入exploreobj.state = 1else:#   该侵犯巢穴的蜘蛛未死亡,继续huntobj.state = 4else:#   当前蚂蚁锁定的蜘蛛被其他蚂蚁抢先杀死print("[%s-%d]锁定的蜘蛛已被其他蚂蚁杀死...." % (obj.name, obj.id))#   蜘蛛被别的蚂蚁杀死,则把该蚂蚁绑定的蜘蛛id置为None吧obj.spider_id = None#   进入exploreobj.state = 1class StateMachine(object):def __init__(self):#   状态集合self.states_Ant = {0: WaitSate(), 1: ExploreState(), 2: SeekState(), 3: TransState(), 4: HuntState()}self.states_Spider = {0: WaitSate(), 1: ExploreState()}#   改变状态def changeState(self, objs):for obj in objs:#   这里先留着吧,考虑下state是否有为None的必要if obj.state is None:returnelse:if obj.name == 'leaf':#   无状态,不做处理,其实也可以在外层先过滤掉leaf对象passelif obj.name == 'spider':# print("name[%s]--state[%d]" % (obj.name, obj.state))newFsm = self.states_Spider[obj.state]newFsm.exec(obj)else:# print("name[%s]--state[%d]" % (obj.name, obj.state))newFsm = self.states_Ant[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(10):ant = Ant(micr, 'ant', r"E:\PycharmProjects\PGStudy\resource\ant.png")ant.bind(0, sm.states_Ant[0])micr.addObj(ant)while True:checkForOut()#   生出叶子if randint(1, 50) == 1:leaf = Leaf(micr, 'leaf', r"E:\PycharmProjects\PGStudy\resource\leaf.png")micr.addObj(leaf)if randint(1, 1000) == 1:spider = Spider(micr, 'spider', r"E:\PycharmProjects\PGStudy\resource\spider.png")micr.addObj(spider)#   将绘制方法全部封装,每次循环重刷屏幕上所有对象micr.draw(screen)sm.changeState(micr.capricious_list)pygame.display.update()pygame.time.delay(10)

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

  1. python从入门到实践十二章

    python编程从入门到实践12章 今天看了星球里面一位学长的经历,感到很受鼓舞,他参加工作三年了,三月份到四月份自学完了三本书,感到和学长差距很大,我要努力去弥补! 决定首先开始三本书,廖雪峰的py ...

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

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

  3. 【机器学习PAI实践十二】机器学习实现男女声音识别分类(含语音特征提取数据和代码)

    背景 随着人工智能的算法发展,对于非结构化数据的处理能力越来越受到重视,这里面的关键一环就是语音数据的处理.目前,许多关于语音识别的应用案例已经影响着我们的生活,例如一些智能音箱中利用语音发送指令,一 ...

  4. 【机器学习PAI实践十二】机器学习算法基于信用卡消费记录做信用评分

    背景 如果你是做互联网金融的,那么一定听说过评分卡.评分卡是信用风险评估领域常用的建模方法,评分卡并不简单对应于某一种机器学习算法,而是一种通用的建模框架,将原始数据通过分箱后进行特征工程变换,继而应 ...

  5. 记录——python编程从入门到实践十二章练习题

    12-1.12-2.12-3 main.py import sysimport pygamefrom homura import Ho from sets import Settings import ...

  6. ABP学习实践(十二)--模块系统

    模块Module是ABP框架体系很重要的概念,不同的功能组件包括项目之间都是以模块的形式进行关联的.在ABP框架的启动过程中,模块的遍历.初始化.启动也是很重要的一环. 1.模块的定义 1.1定义 在 ...

  7. Spark机器学习实战 (十二) - 推荐系统实战

    0 相关源码 将结合前述知识进行综合实战,以达到所学即所用.在推荐系统项目中,讲解了推荐系统基本原理以及实现推荐系统的架构思路,有其他相关研发经验基础的同学可以结合以往的经验,实现自己的推荐系统. 1 ...

  8. 20189200余超 2018-2019-2 移动平台应用开发实践第十二周作业

    20189200余超 2018-2019-2 移动平台应用开发实践第十二周作业 服务 Service的声明 Service是Android中的四大组件,使用它一定要在AndroidManifest.x ...

  9. 在Jetson Nano上学习ROS的记录(版本Ubuntu18.04,课程来源赵虚左老师的《ROS理论与实践》)第十二章 机器人导航(仿真)

    系列文章目录 第一章 ROS空间创建.helloworld的实现.开启多个节点 第二章 话题通信 第三章 服务通信 第四章 参数服务器 第五章 常用指令 第六章 通信机制实操 第七章 ROS通信机制进 ...

最新文章

  1. GitHub:数据科学最全资料集合
  2. 141. Linked List Cycle 环形链表
  3. 见证开户_见证中的发现
  4. 同为Chromium浏览器,Edge却被“特别关照”
  5. 从零学习perl语言--perl学习笔记(1)--从基础概念到hello world编写(本文约1000字)
  6. 无法生成会话打印机,点打印提示没有选择的打印机
  7. 漫画 | Redis常见面试问题
  8. 20145235李涛《网络对抗》Exp8 Web基础
  9. SpringBoot前后端分离登陆验证码实现以及不显示问题
  10. MFC Windows 程序设计[二十一]之树形控件
  11. wps2019怎么调整字间距_wps2019表格和文字间距太大怎么调整?
  12. 安全管家安卓_iOS 设备为什么百毒不侵?安全软件有用吗?
  13. 解决window10系统电脑插入耳机之后没有声音的问题
  14. k8s haproxy Unable to connect to the server: x509: certificate is valid for 127.0.0.1, 10.0.1.12
  15. 特殊教育学校计算机教学计划,2017年特殊教育学校教学计划
  16. 推荐一位字节大佬的刷题经验!
  17. 服务器CPU和普通CPU的区别
  18. 什么是肿瘤免疫逃逸?
  19. 基于分数傅里叶变换的汽车雷达通信一体化系统干扰抑制
  20. linux下 scp 和 ssh 命令

热门文章

  1. InfoPath,你不需要吗?
  2. 网易云易盾CTO朱浩齐:我们是如何用AI赋能内容安全?
  3. 四福音书关于复活节记载貌似不一致的问题
  4. 2022吉林大学软件学院979回忆版
  5. rosbag录制问题:/use_sim_time set to true and no clock published. Still waiting for valid time...
  6. python mypy类型检查_Python 类型检查指南
  7. 使用telnet登陆smtp服务发邮件
  8. linux load average,Linux 平均负载 Load Average 详解
  9. 中国大学MOOC·Python网络爬虫与信息提取(一)
  10. 牛客小白月赛6 I.公交线路