📄 fsm_player.cpp.svn-base
字号:
#include "fsm_player.h"
#include "fsm.h"
#include "custom_time.h"
#include "fsmmacros.h"
#include "msgroute.h"
#include "game_object.h"
#include "Game.h"
#include "player.h"
#include "util.h"
#include "../gamedata/gamedata.h"
#include "../gamedata/FireBall.h"
#include "../gamedata/mdlmodel.h"
#include "../UI/UI.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
void ProcessPlayerInput();
void CalcNewPlayerPos(GameObject* go);
bool PlayerProcessStateMachine( GameObject* go, unsigned int state, MsgObject* msg )
{
//This is the state machine language.
//To see the keywords, look in the file "fsmmacros.h".
//You can get MS Visual Studio to highlight these words by listing them in
//a text file called "usertype.dat" put in the same directory where Msdev.exe
//is stored (like C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin).
//You'll find the "usertype.dat file in the same directory this file is in.
//Just copy it to the correct directory.
BeginStateMachine
OnEnter
SetState( STATE_Stand ); //This sets the initial state that it starts up in
OnMsg(MSG_Damage)
//这个消息由global状态处理,因为各种状态都应该响应这个消息
go->health -= msg->ex.damage;
if (go->health <= 0) {
SetState(STATE_Dead);
}
OnMsg( MSG_CalcNewPos )
//计算新位置
go->checked = false;
go->collide = false;
CalcNewPlayerPos(go);
if (go->newPos.x != go->oldPos.x || go->newPos.z != go->oldPos.z)
go->NeedChecked = true;
else
go->NeedChecked = false;
//----------------------------------------------------------------
State( STATE_Run )
OnEnter
go->model->SetSeq(RUN); //设置动画序列
OnUpdate
//这部分有点儿乱,您看怎么改改把它改得清晰一点
if (go->NeedChecked) {
if (go->checked) {
if (!go->collide) {
go->pos = go->newPos;
}
} else {
assert( !"You must calculate new position before update!" );
}
}else {
SetState(STATE_Stand);
}
if (key[MOUSE_0]) {
SetState(STATE_Attack);
key[MOUSE_0] = false;
}
OnMsg(MSG_Attack)
SetState(STATE_Attack);
//----------------------------------------------------------------
State(STATE_Stand)
OnEnter
go->model->SetSeq(IDLE);
//model[0].SetSequence(0);
OnUpdate
if (go->NeedChecked) {
if (go->checked) {
if (!go->collide) { //位置有改变且没有碰撞
go->pos = go->newPos;
SetState(STATE_Run);
}
} else {
assert( !"You must calculate new position before update!" );
}
}
if (key[MOUSE_0]) {
SetState(STATE_Attack);
key[MOUSE_0] = false;
}
OnMsg(MSG_Attack)
SetState(STATE_Attack);
//----------------------------------------------------------------
State( STATE_Attack )
OnEnter
go->model->SetSeq(ATTACK);
//设置这个状态持续的时间,在这个状态进行的过程中,人物不相应外界事件,直到攻击行为结束。
//当然你也可以不这么设计,比如让人边攻击边移动
//其中GetSeqTime后面减500是因为该函数返回的数值不是很精确,稍微有点儿大
SendDelayedMsgToCurrentState( MSG_Timeout, go->model->GetSeqTime()-500, go->unique_id, go->unique_id, go );
go->NeedChecked = false;
go->collide = false;
go->checked = false;
//获得鼠标位置,即,火球的目的地
go->rotY = GetRotY(go->pos, selection);
//计算火球的初始位置,即,人物的包围盒往外一点的位置,人身高的一半
Vertex fbPos;
fbPos.x = go->pos.x + (go->radius+0.3 + 0.1) * sinf(go->rotY*0.0174533f);
fbPos.z = go->pos.z + (go->radius+0.3 + 0.1) * cosf(go->rotY*0.0174533f);
fbPos.y = go->pos.y + go->lenY * 0.5;
//搞一个火球放到链表里
FireBall fb(fbPos, selection, go->unique_id, go->aggressivity);
fireBalls.push_back(fb);
OnUpdate
//什么也不做
OnMsg( MSG_CalcNewPos )
//什么也不做,重载该消息处理函数
OnMsg( MSG_Timeout )
if (msg->state == STATE_Attack) {
if (key[MOUSE_0]) {
SetState(STATE_Attack);
key[MOUSE_0] = false;
} else {
SetState(STATE_Stand);
}
}
//----------------------------------------------------------------
State( STATE_Dead )
go->model->SetSeq(DIE);
SendMsg(MSG_GamePlayerDie, go->unique_id, gameGO.unique_id);
//----------------------------------------------------------------
EndStateMachine
}
void ProcessPlayerInput()
{
runVector.x = runVector.z = 0;
//转动
if (key[KEY_LEFTROT]) {
player.rotY += incT * rotSpeed;
}
if (key[KEY_RIGHTROT]) {
player.rotY -= incT * rotSpeed;
}
if (player.rotY >= 360) player.rotY -= 360;
if (player.rotY < 0) player.rotY += 360;
//平移
if (key[KEY_FORWARD]) {
runVector.z += incT * playerSpeed;
}
if (key[KEY_BACKWARD]) {
runVector.z -= incT * playerSpeed;
}
if (key[KEY_LEFT]) {
runVector.x += incT * playerSpeed;
}
if (key[KEY_RIGHT]) {
runVector.x -= incT * playerSpeed;
}
}
void CalcNewPlayerPos(GameObject *go)
{
ProcessPlayerInput(); //处理玩家的输入
go->rotY = player.rotY; //更新角度
go->newPos = go->oldPos = go->pos;
//根据player在局部坐标系中的位置和局部坐标系和世界坐标系的偏转角计算player在世界坐标系中的位置
if (runVector.x != 0 || runVector.z != 0) // 更新位置
{
go->newPos.x += runVector.z*sinf(player.rotY*0.0174533f) + runVector.x*cosf(player.rotY*0.0174533f);
go->newPos.z += runVector.z*cosf(player.rotY*0.0174533f) - runVector.x*sinf(player.rotY*0.0174533f);
go->newPos.y = map.getHeight(go->newPos.x,go->newPos.z);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -