📄 msgroute.cpp.svn-base
字号:
/* Copyright (C) Steve Rabin, 2000. * All rights reserved worldwide.** This software is provided "as is" without express or implied* warranties. You may freely copy and compile this source into* applications you distribute provided that the copyright text* below is included in the resulting source code, for example:* "Portions Copyright (C) Steve Rabin, 2000"*/////////////////////////////////////////////////////////////////// Filename: msgroute.cpp//// Author: Steve Rabin// E-mail: stevera@noa.nintendo.com// From the book "Game Programming Gems"// From the article "Designing a General Robust AI Engine"//// Brief Disclaimer:// This code is free to use for commercial use and is in the// public domain. You may distribute, copy, modify, or use as// is as long as this information is present. This code makes// no guarantees written or implied and is provided solely as// an example. Have a nice day!//// Purpose:// This file contains all of the critical messaging and routing// code that enables game objects to talk to each other. Delayed// messages (functionally timers) are also handled, stored, and// fired from this file.////////////////////////////////////////////////////////////////#include "msgroute.h"#include "custom_time.h"#include "malloc.h"#include "msg.h"#include "fsm_unit.h"#include "fsm_player.h"#include "fsm_game.h"#include "fsm_script.h"#include "fsm_camera.h"#include "unit.h"#include <list>#include <windows.h>//---------------------------------------------//这个文件的内容比较关键//---------------------------------------------typedef struct DelayedMessage_Str{ MsgObject msg; bool bSent; //struct DelayedMessage_Str* next;} DelayedMessage;list<DelayedMessage*> DelayedMsgList;bool RouteMessageHelper( GameObject* go, unsigned int state, MsgObject* msg );void StoreDelayedMessage( MsgObject* msg );void PushBackDelayedMessage( DelayedMessage* msg );void SendMsg( MsgName name, unsigned int sender, unsigned int receiver ){ MsgObject msg; msg.name = name; //The name of the message msg.sender_id = sender; //The sender msg.receiver_id = receiver; //The receiver msg.delivery_time = GetCurTime(); //Send the message NOW RouteMessage( &msg );}void SendDelayedMsg( MsgName name, unsigned int delay, unsigned int sender, unsigned int receiver ){ MsgObject msg; msg.name = name; //The name of the message msg.sender_id = sender; //The sender msg.receiver_id = receiver; //The receiver msg.delivery_time = GetCurTime() + delay; //Send the message at a future time RouteMessage( &msg );}void SendMsg( MsgName name, unsigned int sender, unsigned int receiver, extra_data ex ){ MsgObject msg; msg.name = name; //The name of the message msg.sender_id = sender; //The sender msg.receiver_id = receiver; //The receiver msg.delivery_time = GetCurTime(); //Send the message NOW msg.ex = ex; RouteMessage( &msg );}void SendDelayedMsg( MsgName name, unsigned int delay, unsigned int sender, unsigned int receiver, extra_data ex){ MsgObject msg; msg.name = name; //The name of the message msg.sender_id = sender; //The sender msg.receiver_id = receiver; //The receiver msg.delivery_time = GetCurTime() + delay; //Send the message at a future time msg.ex = ex; RouteMessage( &msg );}void SendDelayedMsgToCurrentState( MsgName name, unsigned int delay, unsigned int sender, unsigned int receiver, GameObject *go ){ MsgObject msg; msg.name = name; //The name of the message msg.sender_id = sender; //The sender msg.receiver_id = receiver; //The receiver msg.delivery_time = GetCurTime() + delay; //Send the message at a future time msg.state = go->state; RouteMessage( &msg );}//传递消息的主要函数void RouteMessage( MsgObject* msg ){ GameObject* go; // 如果是发给player的消息,则单独处理,因为player没放到链表里 if (msg->receiver_id == player.unique_id) go = &player; else go = GODBGetGO( msg->receiver_id ); if( !go ) { //Receiver doesn't exist anymore - discard the message return; } if( msg->delivery_time > GetCurTime() ) { //This message needs to be stored until its time to send it StoreDelayedMessage( msg ); return; } if( RouteMessageHelper( go, go->state, msg ) == false ) { //Current state didn't handle msg, try Global state (0) RouteMessageHelper( go, 0, msg ); } // Check for a state change //在发送完消息之后紧接着就更改状态 while( go->force_state_change ) { //Note: circular logic (state changes causing state changes) //could cause an infinite loop here - protect against this //Create a general msg for initializing and cleaning up the state change MsgObject tempmsg; tempmsg.receiver_id = go->unique_id; tempmsg.sender_id = go->unique_id; tempmsg.delivery_time = GetCurTime(); go->force_state_change = false; //Let the last state clean-up tempmsg.name = MSG_RESERVED_Exit; RouteMessageHelper( go, go->state, &tempmsg ); //Set the new state go->state = go->next_state; //Let the new state initialize tempmsg.name = MSG_RESERVED_Enter; RouteMessageHelper( go, go->state, &tempmsg ); }}bool RouteMessageHelper( GameObject* go, unsigned int state, MsgObject* msg ){ //Look up correct state machine for this Game Object //and send message to that particular one switch( go->state_machine_id ) { case FSM_Unit: return( UnitProcessStateMachine( go, state, msg ) ); break; case FSM_Player: return ( PlayerProcessStateMachine( go, state, msg ) ); break; case FSM_Game: return ( GameProcessStateMachine( go, state, msg ) ); break; case FSM_Script: return ( ScriptProcessStateMachine( go, state, msg ) ); break; case FSM_Camera: return ( CameraProcessStateMachine( go, state, msg ) ); break; default: return( false ); break; }}void StoreDelayedMessage( MsgObject* msg ){ //Store this message (in some data structure) for later routing //A priority queue would be the ideal data structure (but not required) //to store the delayed messages - Check out Mark Nelson's article //"Priority Queues and the STL" in the January 1996 Dr. Dobb's Journal //http://www.dogma.net/markn/articles/pq_stl/priority.htm //Note: In main game loop call SendDelayedMessages() every game // tick to check if its time to send the stored messages DelayedMessage* newDelayedMessage = (DelayedMessage*) malloc( sizeof( DelayedMessage ) ); newDelayedMessage->msg.name = msg->name; newDelayedMessage->msg.receiver_id = msg->receiver_id; newDelayedMessage->msg.sender_id = msg->sender_id; newDelayedMessage->msg.state = msg->state; newDelayedMessage->msg.ex = msg->ex; newDelayedMessage->msg.delivery_time = msg->delivery_time; //newDelayedMessage->next = 0; newDelayedMessage->bSent = false; PushBackDelayedMessage( newDelayedMessage );}void SendDelayedMessages( void ){ //This function is called every game tick list<DelayedMessage*>::iterator i = DelayedMsgList.begin(); list<DelayedMessage*>::iterator temp; DelayedMessage *tmpMsg; while (i != DelayedMsgList.end()) { if ((*i)->msg.delivery_time <= GetCurTime()) { (*i)->bSent = true; RouteMessage(&((*i)->msg)); free(*i); i = DelayedMsgList.erase(i); } else ++i; } //while (i != DelayedMsgList.end()) { // if (i->msg.delivery_time <= GetCurTime()) { // i->bSent = true; // RouteMessage(&i->msg); // temp = i; // i++; // tmpMsg = &(*temp); // DelayedMsgList.erase(temp); // free(tmpMsg); // } else if (i != DelayedMsgList.end()) // i++; //} //DelayedMessage* cur_msg = masterDelayedMessage.head; //DelayedMessage* last = 0; //unsigned int curTime = GetCurTime(); //while( cur_msg != 0 ) //{ // if( cur_msg->msg.delivery_time <= GetCurTime() ) // { // cur_msg->bSent = true; // RouteMessage( &cur_msg->msg ); // if( last != 0 ) { // last->next = cur_msg->next; // free( cur_msg ); // cur_msg = last->next; // } // else { // masterDelayedMessage.head = cur_msg->next; // free( cur_msg ); // cur_msg = masterDelayedMessage.head; // } // } // else if( cur_msg != 0 ) { // last = cur_msg; // cur_msg = cur_msg->next; // } //}}void PushBackDelayedMessage( DelayedMessage* msg ){ DelayedMsgList.push_back(msg); //DelayedMessage* curDelayedMessage = masterDelayedMessage.head; //if( curDelayedMessage != 0 ) //{ // while( curDelayedMessage->next != 0 ) // { // if( curDelayedMessage->bSent == false && // curDelayedMessage->msg.name == msg->msg.name && // curDelayedMessage->msg.receiver_id == msg->msg.receiver_id && // curDelayedMessage->msg.sender_id == msg->msg.sender_id && // curDelayedMessage->msg.delivery_time == msg->msg.delivery_time) // { // //Already on queue - don't add // return; // } // curDelayedMessage = curDelayedMessage->next; // } // curDelayedMessage->next = msg; //} //else { // masterDelayedMessage.head = msg; //}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -