闲话
在本文中,我将向您介绍CryEngine中的事件处理,并简要概述您可以在项目中使用的众多监听器。
进入CE的代码,你将会看到许多设计模式,其中关键的一种就是观察者模式。在在此模式中,一个
对象维护一个依赖对象列表,并负责通知它们状态的变化。在CryEngine中,它们通常表示为名称和
结构,其名称以 [Listener]结尾,例如IGameRulesKillListener。
在编写任何代码之前,应该熟悉(至少一般)每个可用的侦听器。现在,让我们来看看如何实现一个
监听器。
类比说明
可能你遇到的第一个监听器是IGameFrameworkListener。IGameFrameworkListener是一个监听框架
事件的对象。什么是框架事件可以具体看看该类,例如保存加载游戏,升级等事件。监听器的目的就是
接受事件然后根据不同事件写不同的代码。当然,事件不可能凭空产生,事件肯定是某个“老板”通知的。
所以,所有的监听器最后都需要被注册才有用,比如监听器是一个公司职员,并已经在老板下面挂名了
(注册了),然后老板有事就会给你发通知(通告),然后你(监听器)就会去响应这个通告(具体代
码逻辑)。这大概就是这么搞的。
伪代码说明
//中央集权
struct IBoss
{
//Boss可以随时取经理来用...(有点邪恶)
virtual IStaffManager* GetStaffManager() = 0;
//Boss可以布置任务,就是通知你们该干嘛
virtual void Notify(EBossNotifyEvent event) = 0;
//有新来的员工,Boss肯定是要知道的
virtual void RegisterNotifyListener(IStaffNotifyListener* listener) = 0;
//员工辞职了,Boss肯定要知道的
virtual void UnregisterNotifyListener(IStaffNotifyListener* listener) = 0;
};
//监听器(可以理解为Boss为了好给你发消息,给你带上的仪器)
struct IStaffNotifyListener
{
virtual void OnStaffNotifyEvent(EEditorNotifyEvent event) = 0;
}
//员工小明
class XiaoMing:public IStaffNotifyListener
{
XiaoMing()
{
//新员工小明报道
Get公司()->GetBoss()->RegisterNotifyListener(this);
}
~XiaoMing()
{
//新员工小明辞职
Get公司()->GetBoss()->UnregisterNotifyListener(this);
}
virtual void OnStaffNotifyEvent(EEditorNotifyEvent event) override
{
//执行老板的下达的任务
swicth(event)
{
case 搬砖:
....
case 放假:
....
....
}
}
}
//调用
IBoss->Notify(搬砖);
一起来看看CryEngine里面大概都有什么监听器
有兴趣的玩家可以在GameSDK模块运行下Doxygen以了解都有什么监听器,大约有四十个类被声明为监听者。将在下面简要介绍一下:
IBasicEventListener
提供对基本事件的访问,比如进入和离开菜单,鼠标单击或键盘字符输入。
struct IBasicEventListener
{
enum EAction
{
eA_Default,
eA_None,
eA_ActivateAndEat
};
virtual ~IBasicEventListener();
virtual EAction OnClose(HWND hWnd) = 0;
virtual EAction OnMouseActivate(HWND hWnd) = 0;
virtual EAction OnEnterSizeMove(HWND hWnd) = 0;
virtual EAction OnExitSizeMove(HWND hWnd) = 0;
virtual EAction OnEnterMenuLoop(HWND hWnd) = 0;
virtual EAction OnExitMenuLoop(HWND hWnd) = 0;
virtual EAction OnHotKey(HWND hWnd) = 0;
virtual EAction OnSycChar(HWND hWnd) = 0;
virtual EAction OnChar(HWND hWnd, WPARAM wParam) = 0;
virtual EAction OnIMEChar(HWND hWnd) = 0;
virtual EAction OnSysKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam) = 0;
virtual EAction OnSetCursor(HWND hWnd) = 0;
virtual EAction OnMouseMove(HWND hWnd, LPARAM lParam) = 0;
virtual EAction OnLeftButtonDown(HWND hWnd, LPARAM lParam) = 0;
virtual EAction OnLeftButtonUp(HWND hWnd, LPARAM lParam) = 0;
virtual EAction OnLeftButtonDoubleClick(HWND hWnd, LPARAM lParam) = 0;
virtual EAction OnMouseWheel(HWND hWnd, LPARAM lParam, short WheelDelta) = 0;
virtual EAction OnMove(HWND hWnd, LPARAM lParam) = 0;
virtual EAction OnSize(HWND hWnd, LPARAM lParam) = 0;
virtual EAction OnActivate(HWND hWnd, WPARAM wParam) = 0;
virtual EAction OnSetFocus(HWND hWnd) = 0;
virtual EAction OnKillFocus(HWND hWnd) = 0;
virtual EAction OnWindowPositionChanged(HWND hWnd) = 0;
virtual EAction OnWindowStyleChanged(HWND hWnd) = 0;
virtual EAction OnInputLanguageChanged(HWND hWnd, WPARAM wParam, LPARAM lParam) = 0;
virtual EAction OnSysCommand(HWND hWnd, WPARAM wParam) = 0;
};
IDataListener
这可以通过修补和下载对象来使用。它提供了一个简单的界面,可在下载完成或失败时通知您。
struct IDataListener
{
virtual void DataDownloaded(CDownloadableResourcePtr inResource)= 0;
virtual void DataFailedToDownload(CDownloadableResourcePtr inResource)= 0;
virtual~IDataListener();
};
IDataPatcherListener
由CDataPatchDownloader类使用。
struct IDataPatcherListener
{
virtual void DataPatchAvailable()= 0;
virtual void DataPatchNotAvailable()= 0;
virtual~IDataPatcherListener(){}
};
*IEnvironmentalWeaponEventListener
(这个是什么功能我也不知道,希望知道的大牛回复下我好补充说明)
struct IEnvironmentalWeaponEventListener
{
// Called when Rip anim is started
virtual void OnRipStart () = 0;
// Called at the point within the rip action that the actual 'detach/Unroot' occurs
virtual void OnRipDetach () = 0;
// Called at the end of the rip anim
virtual void OnRipEnd () = 0;
virtual ~IEnvironmentalWeaponEventListener () {};
};
IFireModeListener
仅在CFireMode类中使用,开火模式。
struct IFireModeListener
{
virtual~IFireModeListener(){}
virtual void OnFireModeDeleted()= 0;
virtual void OnFireModeActivated(bool activated)= 0;
};
IGameLobbyEventListener
在反作弊码中使用。
class IGameLobbyEventListener
{
public:
virtual~IGameLobbyEventListener(){}
virtual void InsertedUser(CryUserID userId,const char * userName)= 0;
virtual void SessionChanged(const CrySessionHandle inOldSession,const CrySessionHandle inNewSession)= 0;
};
IGameRulesActorActionListener
由游戏规则例程使用。
class IGameRulesActorActionListener
{
public:
virtual~IGameRulesActorActionListener(){}
virtual void OnAction(const ActionId&actionId,int activationMode,float value)= 0;
};
IGameRulesClientConnectionListener
客户端连接时事件。
class IGameRulesClientConnectionListener
{
public:
virtual~IGameRulesClientConnectionListener(){}
virtual void OnClientConnect(int channelId,bool isReset,EntityId playerId)= 0;
virtual void OnClientDisconnect(int channelId,EntityId playerId)= 0;
virtual void OnClientEnteredGame(int channelId,bool isReset,EntityId playerId)= 0;
virtual void OnOwnClientEnteredGame()= 0;
};
IGameRulesClientScoreListener
客户评分时的通知事件。
class IGameRulesClientScoreListener
{
public:
virtual~ IGameRulesClientScoreListener(){}
virtual void ClientScoreEvent(EGameRulesScoreType type,int points,EXPReason inReason,int currentTeamScore)= 0;
};
IGameRulesKillListener
实体被杀时的通知。
class IGameRulesKillListener
{
public:
virtual~IGameRulesKillListener(){}
virtual void OnEntityKilledEarly(const HitInfo&hitInfo)= 0;
virtual void OnEntityKilled(const HitInfo&hitInfo)= 0;
};
IGameRulesModuleRMIListener
(这个是什么功能我也不知道,希望知道的大牛回复下我好补充说明)
class IGameRulesModuleRMIListener
{
public:
virtual~IGameRulesModuleRMIListener(){}
virtual void OnSingleEntityRMI(CGameRules :: SModuleRMIEntityParams params)= 0;
virtual void OnDoubleEntityRMI(CGameRules :: SModuleRMITwoEntityParams params)= 0;
virtual void OnEntityWithTimeRMI(CGameRules :: SModuleRMIEntityTimeParams params)= 0;
virtual void OnSvClientActionRMI(CGameRules :: SModuleRMISvClientActionParams params,EntityId fromEid)= 0;
};
IGameRulesPickupListener
拾取和丢弃物品的实体通知。
class IGameRulesPickupListener
{
public:
virtual~IGameRulesPickupListener(){}
virtual void OnItemPickedUp(EntityId itemId,EntityId actorId)= 0;
virtual void OnItemDropped(EntityId itemId,EntityId actorId)= 0;
virtual void OnPickupEntityAttached(EntityId entityId,EntityId actorId)= 0;
virtual void OnPickupEntityDetached(EntityId entityId,EntityId actorId,bool isOnRemove)= 0;
};
IGameRulesPlayerStatsListener
(这个是什么功能我也不知道,希望知道的大牛回复下我好补充说明)
class IGameRulesPlayerStatsListener
{
public:
virtual~IGameRulesPlayerStatsListener(){}
virtual void ClPlayerStatsNetSerializeReadDeath(const SGameRulesPlayerStat * s,uint16 prevDeathsThisRound,uint8 prevFlags)= 0;
};
IGameRulesRevivedListener
它可能貌似大概是一个实体何时复活的通知。
class IGameRulesRevivedListener
{
public:
virtual~IGameRulesRevivedListener(){}
virtual void EntityRevived(EntityId entityId)= 0;
};
IGameRulesRoundsListener
由游戏规则代码使用。
class IGameRulesRoundsListener
{
public:
virtual~IGameRulesRoundsListener(){}
virtual void OnRoundStart()= 0;
virtual void OnRoundEnd()= 0;
virtual void OnSuddenDeath()= 0;
virtual void ClRoundsNetSerializeReadState(int newState,int curState)= 0;
virtual void OnRoundAboutToStart()= 0;
};
IGameRulesStateListener
由游戏规则代码使用。
class IGameRulesStateListener
{
public:
virtual~IGameRulesStateListener(){}
virtual void OnIntroStart()= 0;
virtual void OnGameStart()= 0;
virtual void OnGameEnd()= 0;
virtual void OnStateEntered(IGameRulesStateModule :: EGR_GameState newGameState)= 0;
};
IGameRulesSurvivorCountListener
由游戏规则代码使用。
class IGameRulesSurvivorCountListener
{
public:
virtual ~IGameRulesSurvivorCountListener () {}
virtual void SvSurvivorCountRefresh (int count, const EntityId survivors[], int numKills) = 0;
};
IGameRulesTeamChangedListener
由游戏规则代码使用。
class IGameRulesTeamChangedListener
{
public:
virtual~ IGameRulesTeamChangedListener(){}
virtual void OnChangedTeam(EntityId entityId,int oldTeamId,int newTeamId)= 0;
};
IHUDEventListener
这会处理来自HUD的事件通知。
struct IHUDEventListener
{
virtual~IHUDEventListener(){}
virtual void OnHUDEvent(const SHUDEvent&event)= 0;
};
IMeleeCollisionHelperListener
这可以在类CPickAndThrowWeapon中看到,它响应有助于计算投掷武器的命中。
struct IMeleeCollisionHelperListener
{
virtual~IMeleeCollisionHelperListener(){}
virtual void OnSuccesfulHit(const ray_hit&hitResult)= 0;
virtual void OnFailedHit()= 0;
};
IMPPathFollowingListener
路径查找管理器用于通知路径何时完成。
struct IMPPathFollowingListener
{
virtual void OnPathCompleted(EntityId attachedEntityId)= 0;
virtual~IMPPathFollowingListener(){};
};
IPatchPakManagerListener
只有已知的用途是由专用服务器知道权限已更改并且是时候退出。
class IPatchPakManagerListener
{
public:
virtual~IPatchPakManagerListener(){}
virtual void UpdatedPermissionsNowAvailable()= 0;
};
IPlayerEventListener
玩家采取的行动通知。这包括支持进出车辆,在第一人和第三人称相机之间切换,拾取,丢弃和使用物品,死亡和姿态变化等。它还为玩家处理特殊动作。目前只定义了跳转和冲刺。
struct IPlayerEventListener
{
enum ESpecialMove
{
eSM_Jump = 0,
eSM_SpeedSprint,
};
virtual~IPlayerEventListener(){}
virtual void OnEnterVehicle(IActor * pActor,const char * strVehicleClassName,const char * strSeatName,bool bThirdPerson){};
virtual void OnExitVehicle(IActor * pActor){};
virtual void OnToggleThirdPerson(IActor * pActor,bool bThirdPerson){};
virtual void OnItemDropped(IActor * pActor,EntityId itemId){};
virtual void OnItemPickedUp(IActor * pActor,EntityId itemId){};
virtual void OnItemUsed(IActor * pActor,EntityId itemId){};
virtual void OnStanceChanged(IActor * pActor,EStance stance){};
virtual void OnSpecialMove(IActor * pActor,ESpecialMove move){};
virtual void OnDeath(IActor * pActor,bool bIsGod){};
virtual void OnObjectGrabbed(IActor * pActor,bool bIsGrab,EntityId objectId,bool bIsNPC,bool bIsTwoHanded){};
virtual void OnHealthChanged(IActor * pActor,float newHealth){};
virtual void OnRevive(IActor * pActor,bool bIsGod){};
virtual void OnSpectatorModeChanged(IActor * pActor,uint8 mode){};
virtual void OnPickedUpPickableAmmo(IActor * pActor,IEntityClass * pAmmoType,int count){}
};
IPlayerProgressionEventListener
OnEvent函数侦听重要的游戏事件,例如EMP爆炸,首次血杀和隐形杀戮。它仅由CPersistantStats类用于记录这些事件。
struct IPlayerProgressionEventListener
{
virtual~IPlayerProgressionEventListener(){}
virtual void OnEvent(EPPType type,bool skillKill,void * data)= 0;
};
IPlayerUpdateListener
播放器更新的监听器界面。
struct IPlayerUpdateListener
{
virtual~IPlayerUpdateListener(){}
virtual void Update(float fFrameTime)= 0;
};
IPrivateGameListener
大堂经理用于设置私人游戏。
struct IPrivateGameListener
{
virtual~IPrivateGameListener(){}
virtual void SetPrivateGame(const bool privateGame)= 0;
};
IProjectileListener
无论何时发射射弹,都会调用OnLaunch功能。OnProjectilePhysicsPostStep有关于线程安全的警告,看起来不适合外部使用。
struct IProjectileListener
{
// NB: Must be physics-thread safe IF its called from the physics OnPostStep
virtual void OnProjectilePhysicsPostStep (CProjectile* pProjectile, EventPhysPostStep* pEvent, int bPhysicsThread) {}
// Called from Main thread
virtual void OnLaunch (CProjectile* pProjectile, const Vec3& pos, const Vec3& velocity) {}
protected:
// Should never be called
virtual ~IProjectileListener () {}
};
RecordingSystemListener
(还是求大神告知,不知道)
class IRecordingSystemListener
{
public:
virtual~IRecordingSystemListener(){}
virtual void OnPlaybackRequested(const SPlaybackRequest&info){}
virtual void OnPlaybackStarted(const SPlaybackInfo&info){}
virtual void OnPlaybackEnd(const SPlaybackInfo&info){}
};
ISquadEventListener
小队管理通知。
class ISquadEventListener
{
public:
// Local squad events
enum ESquadEventType
{
eSET_CreatedSquad,
eSET_MigratedSquad,
eSET_JoinedSquad,
eSET_LeftSquad,
};
public:
virtual~ISquadEventListener(){}
virtual void AddedSquaddie(CryUserID userId)= 0;
virtual void RemovedSquaddie(CryUserID userId)= 0;
virtual void UpdatedSquaddie(CryUserID userId)= 0;
virtual void SquadLeaderChanged(CryUserID userId)= 0;
virtual void SquadEvent(ISquadEventListener :: ESquadEventType eventType)= 0;
};
IUIControlSchemeListener
这似乎是用户何时更改游戏控件的通知。
struct IUIControlSchemeListener
{
virtual~IUIControlSchemeListener(){};
virtual bool OnControlSchemeChanged(const EControlScheme controlScheme)= 0;
};
SGameRulesListener
重要游戏规则事件的通知。
struct SGameRulesListener
{
virtual~SwameRulesListener(){}
virtual void GameOver(EGameOverType localWinner,bool isClientSpectator){}
virtual void EnteredGame(){}
virtual void EndGameNear(EntityId id){}
virtual void ClientEnteredGame(EntityId clientId){}
virtual void ClientDisconnect (EntityId clientId){}
virtual void OnActorDeath(CActor * pActor){}
virtual void SvOnTimeLimitExpired(){}
virtual void ClTeamScoreFeedback(int teamId,int prevScore,int newScore){}
void GetMemoryUsage(ICrySizer * pSizer)const {}
};
最后跟大家说
写到这里,手麻了,眼花了,脚离抽经不远了。还是要跟大伙儿说一下,搞项目源码要耐心+细心+专心+恒心,星星之火最后就是太阳了。