⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsm_player.cpp.svn-base

📁 自己做的小游戏
💻 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 + -