博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
游戏人工智能 状态驱动智能体设计——消息功能
阅读量:4088 次
发布时间:2019-05-25

本文共 9062 字,大约阅读时间需要 30 分钟。

状态驱动智能体设计——消息功能

1. 如何设计游戏的消息功能?

设计精度的游戏趋向于事件驱动。即当一个事件发生了(武器发射了子弹等),事件被广播给游戏中的相关的对象。这样它们可以恰当地做出反应。而这个消息可以是立即执行,也可以设定多久后才执行。

于是,我们可以设计一个消息处理器类,包含处理消息的方法、加入消息的方法,还有用于储存延迟消息的队列以及游戏循环时刻调用的用于检测延迟消息队列是否有消息到达时间点然后处理它。
在处理消息的方法中,可以让接收者调用自身处理消息的方法,在这个方法中又去调用FSM有限状态机的处理消息的方法,让当前的状态响应该消息。
消息可以用一个“电报”类来包装,包含了发送者、接受者、消息内容、执行时间等。

2. 主要代码展示

#ifndef MESSAGE_DISPATCHER_H#define MESSAGE_DISPATCHER_H//------------------------------------------------------------------------////  Name:   MessageDispatcher.h////  Desc:   A message dispatcher. Manages messages of the type Telegram.//          Instantiated as a singleton.////  Author: Mat Buckland 2002 (fup@ai-junkie.com)////------------------------------------------------------------------------#pragma warning (disable:4786)#include 
#include "misc/ConsoleUtils.h"#include "messaging/Telegram.h"class BaseGameEntity;//to make code easier to readconst double SEND_MSG_IMMEDIATELY = 0.0f;const int NO_ADDITIONAL_INFO = 0;//to make life easier...#define Dispatch MessageDispatcher::Instance()class MessageDispatcher{private: //a std::set is used as the container for the delayed messages //because of the benefit of automatic sorting and avoidance //of duplicates. Messages are sorted by their dispatch time. std::set
PriorityQ; //this method is utilized by DispatchMessage or DispatchDelayedMessages. //This method calls the message handling member function of the receiving //entity, pReceiver, with the newly created telegram void Discharge(BaseGameEntity* pReceiver, const Telegram& msg); MessageDispatcher(){} //copy ctor and assignment should be private MessageDispatcher(const MessageDispatcher&); MessageDispatcher& operator=(const MessageDispatcher&);public: //this class is a singleton static MessageDispatcher* Instance(); //send a message to another agent. Receiving agent is referenced by ID. void DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo); //send out any delayed messages. This method is called each time through //the main game loop. void DispatchDelayedMessages();};#endif
#ifndef TELEGRAM_H#define TELEGRAM_H//------------------------------------------------------------------------////  Name:   Telegram.h////  Desc:   This defines a telegram. A telegram is a data structure that//          records information required to dispatch messages. Messages //          are used by game agents to communicate with each other.////  Author: Mat Buckland (fup@ai-junkie.com)////------------------------------------------------------------------------#include 
#include
struct Telegram{ //the entity that sent this telegram int Sender; //the entity that is to receive this telegram int Receiver; //the message itself. These are all enumerated in the file //"MessageTypes.h" int Msg; //messages can be dispatched immediately or delayed for a specified amount //of time. If a delay is necessary this field is stamped with the time //the message should be dispatched. double DispatchTime; //any additional information that may accompany the message void* ExtraInfo; Telegram():DispatchTime(-1), Sender(-1), Receiver(-1), Msg(-1) {} Telegram(double time, int sender, int receiver, int msg, void* info = NULL): DispatchTime(time), Sender(sender), Receiver(receiver), Msg(msg), ExtraInfo(info) {}};//these telegrams will be stored in a priority queue. Therefore the >//operator needs to be overloaded so that the PQ can sort the telegrams//by time priority. Note how the times must be smaller than//SmallestDelay apart before two Telegrams are considered unique.const double SmallestDelay = 0.25;inline bool operator==(const Telegram& t1, const Telegram& t2){ return ( fabs(t1.DispatchTime-t2.DispatchTime) < SmallestDelay) && (t1.Sender == t2.Sender) && (t1.Receiver == t2.Receiver) && (t1.Msg == t2.Msg);}inline bool operator<(const Telegram& t1, const Telegram& t2){ if (t1 == t2) { return false; } else { return (t1.DispatchTime < t2.DispatchTime); }}inline std::ostream& operator<<(std::ostream& os, const Telegram& t){ os << "time: " << t.DispatchTime << " Sender: " << t.Sender << " Receiver: " << t.Receiver << " Msg: " << t.Msg; return os;}//handy helper function for dereferencing the ExtraInfo field of the Telegram //to the required type.template
inline T DereferenceToType(void* p){ return *(T*)(p);}#endif
#include "MessageDispatcher.h"#include "BaseGameEntity.h"#include "Time/CrudeTimer.h"#include "EntityManager.h"#include "Locations.h"#include "MessageTypes.h"#include "EntityNames.h"#include 
using std::cout;using std::set;#ifdef TEXTOUTPUT#include
extern std::ofstream os;#define cout os#endif//------------------------------ Instance -------------------------------------MessageDispatcher* MessageDispatcher::Instance(){ static MessageDispatcher instance; return &instance;}//----------------------------- Dispatch ---------------------------------// // see description in header//------------------------------------------------------------------------void MessageDispatcher::Discharge(BaseGameEntity* pReceiver, const Telegram& telegram){ if (!pReceiver->HandleMessage(telegram)) { //telegram could not be handled cout << "Message not handled"; }}//---------------------------- DispatchMessage ---------------------------//// given a message, a receiver, a sender and any time delay , this function// routes the message to the correct agent (if no delay) or stores// in the message queue to be dispatched at the correct time//------------------------------------------------------------------------void MessageDispatcher::DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo){ SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); //get pointers to the sender and receiver BaseGameEntity* pSender = EntityMgr->GetEntityFromID(sender); BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID(receiver); //make sure the receiver is valid if (pReceiver == NULL) { cout << "\nWarning! No Receiver with ID of " << receiver << " found"; return; } //create the telegram Telegram telegram(0, sender, receiver, msg, ExtraInfo); //if there is no delay, route telegram immediately if (delay <= 0.0f) { cout << "\nInstant telegram dispatched at time: " << Clock->GetCurrentTime() << " by " << GetNameOfEntity(pSender->ID()) << " for " << GetNameOfEntity(pReceiver->ID()) << ". Msg is "<< MsgToStr(msg); //send the telegram to the recipient Discharge(pReceiver, telegram); } //else calculate the time when the telegram should be dispatched else { double CurrentTime = Clock->GetCurrentTime(); telegram.DispatchTime = CurrentTime + delay; //and put it in the queue PriorityQ.insert(telegram); cout << "\nDelayed telegram from " << GetNameOfEntity(pSender->ID()) << " recorded at time " << Clock->GetCurrentTime() << " for " << GetNameOfEntity(pReceiver->ID()) << ". Msg is "<< MsgToStr(msg); }}//---------------------- DispatchDelayedMessages -------------------------//// This function dispatches any telegrams with a timestamp that has// expired. Any dispatched telegrams are removed from the queue//------------------------------------------------------------------------void MessageDispatcher::DispatchDelayedMessages(){ SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); //get current time double CurrentTime = Clock->GetCurrentTime(); //now peek at the queue to see if any telegrams need dispatching. //remove all telegrams from the front of the queue that have gone //past their sell by date while( !PriorityQ.empty() && (PriorityQ.begin()->DispatchTime < CurrentTime) && (PriorityQ.begin()->DispatchTime > 0) ) { //read the telegram from the front of the queue const Telegram& telegram = *PriorityQ.begin(); //find the recipient BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID(telegram.Receiver); cout << "\nQueued telegram ready for dispatch: Sent to " << GetNameOfEntity(pReceiver->ID()) << ". Msg is " << MsgToStr(telegram.Msg); //send the telegram to the recipient Discharge(pReceiver, telegram); //remove it from the queue PriorityQ.erase(PriorityQ.begin()); }}

3. 完整项目源代码下载

转载地址:http://nnyii.baihongyu.com/

你可能感兴趣的文章
FTP 常见问题
查看>>
Python学习笔记之数据类型
查看>>
shell 快捷键
查看>>
VIM滚屏操作
查看>>
将file文件内容转成字符串
查看>>
MODULE_DEVICE_TABLE的理解
查看>>
.net强制退出主窗口的方法——Application.Exit()方法和Environment.Exit(0)方法
查看>>
c# 如何调用win8自带的屏幕键盘(非osk.exe)
查看>>
build/envsetup.sh 简介
查看>>
编译Android4.0源码时常见错误及解决办法
查看>>
Android 源码编译make的错误处理
查看>>
启用SELinux时遇到的问题
查看>>
virbr0 虚拟网卡卸载方法
查看>>
No devices detected. Fatal server error: no screens found
查看>>
新版本的linux如何生成xorg.conf
查看>>
Linux基础教程:CentOS卸载KDE桌面
查看>>
read humor_campus
查看>>
my read work
查看>>
db db2 base / instance database tablespace container
查看>>
db db2_monitorTool IBM Rational Performace Tester
查看>>