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

📄 grole.cpp

📁 一个RPG游戏演示全部源代码。使用Visual C++ 6.0
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////
// GRole.cpp: implementation of the CGRole class.
// RPGDemo框架程序	角色类
// written by 萧萧落木(Roc.j.Wood)
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GRole.h"
#include "GScene.h"

#include <fstream.h>

#include <string>
using namespace std;


#define ROLEWALKONESTEP				1.0f		//精灵移动步长
#define	ROLEWALKONESTEPDSQ2			(ROLEWALKONESTEP*0.707f)

const float MOVESTEPS[16]={0,ROLEWALKONESTEP,
							-ROLEWALKONESTEPDSQ2,ROLEWALKONESTEPDSQ2,
							-ROLEWALKONESTEP,0,
							-ROLEWALKONESTEPDSQ2,-ROLEWALKONESTEPDSQ2,
							0,-ROLEWALKONESTEP,
							ROLEWALKONESTEPDSQ2,-ROLEWALKONESTEPDSQ2,
							ROLEWALKONESTEP,0,
							ROLEWALKONESTEPDSQ2,ROLEWALKONESTEPDSQ2};

#pragma pack(push,1)
struct ROLEFILE
{
	DWORD	FILEFLAG;
	DWORD	Version;
	CHAR	szName[16];
	SHORT	Status;
	SHORT	Flag;
	SHORT	Direction;
	
	CHAR	szScript[32];	//角色脚本文件(如果没有脚本文件则设定为全0,下同)
	CHAR	szGraph[32];	//角色图片文件
	DWORD	GraphWidth;		//图片文件宽度(由图片文件设定)
	DWORD	GraphHeight;	//图片文件高度(由图片文件设定)
	DWORD	CellWidth;		//图片分割单元宽度
	DWORD	CellHeight;		//图片分割单元高度
	POINT	KeyPos;			//角色脚底坐标(用来定位角色)
	RECT	InsideRECT;		//用于检测碰撞的内部矩形框
	
	SHORT    MoveFrames;	//运动帧数(第0帧是站立静止)
	SHORT    MoveDelay;		//运动延时(毫秒)
	SHORT    MoveSwapFrame;	//运动交换帧速率(一般为2或者3)
	SHORT    MoveSpeed;		//运动速度(像素/步)
	SHORT    MoveGrpahLine[8];	//数组纪录对应方向i的运动帧在图像中的行数(行数从0开始计算)
	
	SHORT	 FightFrames;    //战斗帧数
	SHORT    FightGrpahLine; //战斗分解帧在图像中的行数
	
	LONG	HP;				//体力
	LONG	HP_MAX;			//体力上限
	LONG	MP;				//魔法
	LONG	MP_MAX;			//魔法上限
	LONG	AP;				//攻击力
	LONG	DP;				//防御力
	LONG	DEX;			//灵敏
};
#pragma pack(pop)

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGRole::CGRole(CGScene *pScene)
{
	assert(pScene);
	m_pScene = pScene;

	memset(ScriptFile,0,_MAX_PATH);
	
	TempFrame		=
	CurrentFrame	=
	FrameCount		= 0;
	MoveDelay	= 0xffff;
	MoveSwapFrameSpeed = 1;
	MoveSpeed	= 0;
	memset(MoveGrpahLines,0,8*sizeof(SHORT));

	CellWidth	=
	CellHeight	=
	XKPos		=
	YKPos		= 0;
	XMPos		=	pScene->GetWidth()>>1;	//场景坐标中心
	YMPos		=	pScene->GetHeight()>>1;	//场景坐标中心
	Level		=	0;
	Direction	=	1;					//左斜下
	Flag		=	ROLEFLAG_UNKNOWN;	//未知类型
	Status		=	ROLESTAT_NONE;		//空状态

	HP			=
	HP_MAX		=
	MP			=
	MP_MAX		= 0;
	AP			=		//攻击力
	DP			=		//防御力
	EAP			=
	EDP			=
	DEX			= 0;	//灵敏

	ticktimer	= GetTickCount();
}

CGRole::~CGRole()
{
	FinalClearup();
}

void CGRole::FinalClearup()
{
	m_pScene = NULL;
	memset(ScriptFile,0,_MAX_PATH);
}

HRESULT CGRole::LoadGraph(LPCTSTR szFileName)
{
	assert(szFileName);
	
	string fName;
	fName="ROLE\\";
	fName.append(szFileName);

	HRESULT hr=m_gGraph.CreateByBitmap(&GAFDDraw,(LPCTSTR)(fName.c_str()));
	TESTHR_RET(hr);
	
	m_gGraph.SetColorKey();

	return S_OK;
}

void CGRole::SetMapPos(int mx, int my)
{
	if(mx<0) mx=0;
	if(my<0) my=0;
	if(mx>=m_pScene->GetWidth()) mx=m_pScene->GetWidth()-1;
	if(my>=m_pScene->GetHeight()) my=m_pScene->GetHeight()-1;
	XMPos=mx;	YMPos=my;
	if(Flag==ROLEFLAG_LEADER)	m_pScene->FocusSceneCenter(mx,my);

	assert(m_pScene);
	Level=m_pScene->GetLevel(mx,my);
}

HRESULT CGRole::LoadRole(LPCTSTR szFileName)
{
	assert(szFileName);
	
	string fName;
	fName="ROLE\\";
	fName.append(szFileName);
	
	::fstream fs;
	fs.open(fName.c_str(),ios::in|ios::binary);
	if(fs.is_open()==FALSE)	return E_FAIL;
	
	try
	{
		ROLEFILE data;
		fs.read((LPSTR)&data,sizeof(ROLEFILE));
	
		if(data.FILEFLAG!=MAKEFOURCC('G','R','O','L')||data.Version!=0x0103) return -1;
		
		memcpy(szName,data.szName,16);
		Status = (ROLESTATUS)data.Status;
		Flag = (ROLEFLAG)data.Flag;

		memcpy(ScriptFile,data.szScript,32);

		TESTHR_RET(LoadGraph(data.szGraph));
		if(m_gGraph.GetWidth()!=data.GraphWidth
			||m_gGraph.GetHeight()!=data.GraphHeight)
			return -2;
		
		CellWidth = data.CellWidth;
		CellHeight = data.CellHeight;
		XKPos = data.KeyPos.x;
		YKPos = data.KeyPos.y;
		InsideRECT = data.InsideRECT;
		
		FrameCount = data.MoveFrames;
		MoveDelay = data.MoveDelay;
		MoveSpeed = data.MoveSpeed;
		MoveSwapFrameSpeed = data.MoveSwapFrame;
		
		memcpy(MoveGrpahLines,data.MoveGrpahLine,sizeof(SHORT)*8);

		FightFrames = data.FightFrames;
		FightGrpahLine = data.FightGrpahLine;
		
		HP = data.HP;
		HP_MAX = data.HP_MAX;
		MP = data.MP;
		MP_MAX = data.MP_MAX;
		AP = data.AP;
		DP = data.DP;
		DEX = data.DEX;
		EAP=AP;
		EDP=DP;
		
		XMPos = 0;
		YMPos = 0;
		
		SetDirection(data.Direction);	
	}
	catch(...)
	{
		fs.close();
		return E_FAIL;
	}

	ticktimer	= GetTickCount();
	CurrentFrame = TempFrame = 0;
	return S_OK;
}

SHORT CGRole::DecideMoveDirection(int x1, int y1, int x2, int y2) const
{
	float dx=(float)abs(x1-x2);
	float dy=(float)abs(y1-y2);
	if(dx>=2.41f*dy)		//2.41=1/arctan(22.5 Degree)
		return (x1<x2)?6:2;
	if(dy>=2.41f*dx)
		return (y1>y2)?4:0;
	if(x1<x2)
		return (y1>y2)?5:7;
	else
		return (y1>y2)?3:1;

	return Direction;
}

void CGRole::CheckInput()
{
	assert(Flag==ROLEFLAG_LEADER);
	assert(m_pScene);

	Status = ROLESTAT_STAND;
	LONG SX=XMPos,SY=YMPos,lX,lY;
	m_pScene->MapToScreen(SX,SY);	//变换到精灵相对于屏幕的坐标
	
	//按下鼠标右键走动
	if(GAFDInput.GetMouseKeyState(DIK_MOUSERIGHT)==GAFDIKEY_PRESS)
	{
		GAFDInput.GetSysMousePos(&lX,&lY);
		AdjustMousePosition(&lX,&lY);
		SetDirection(DecideMoveDirection(SX,SY,lX,lY));

		LONG dx=SX-lX;
		LONG dy=SY-lY;
		if(dx*dx+dy*dy>16*16) Status = ROLESTAT_WALKING;
	}
}

void CGRole::AIThinking()
{
	if(Flag==ROLEFLAG_LEADER)	CheckInput();	//主角控制

	DWORD timer = GetTickCount();
	switch(Status)
	{
		case ROLESTAT_NONE:
		case ROLESTAT_STAND:
			Status=ROLESTAT_STAND;
			ticktimer=timer;
			TempFrame = 0;
			CurrentFrame = 0;
			break;			
		case ROLESTAT_WALKING:
			if((LONG)(timer-ticktimer)<MoveDelay)	break;
			ticktimer=timer;
			//选择一个合适的方向运动一步
			RoleWalkOneStep();
			break;
		default:
			break;
	}
}

HRESULT CGRole::RenderRole()
{
	assert(m_pScene);

	LONG GX=XMPos-XKPos;
	LONG GY=YMPos-YKPos;
	m_pScene->MapToScreen(GX,GY);	//从地图坐标转换到屏幕坐标

	//只渲染站立和行走状态
	if(Status==ROLESTAT_STAND||Status==ROLESTAT_WALKING)
	{
		RECT rc;
		rc.top=MoveGrpahLines[Direction]*CellHeight;
		rc.bottom=rc.top+CellHeight;
		rc.left=CurrentFrame*CellWidth;
		rc.right=rc.left+CellWidth;

		if(rc.top>=0)
			m_gGraph.BltFastTo(GAFDDraw.GetBack(),GX,GY,TRUE,&rc,TRUE);
	}

	return S_OK;
}

const SHORT CGROLE_DIRECTION_FIND_ORDER[8]={0,1,7,2,14,3,21,4};

void CGRole::SetDirection(int newdir)
{
	int i,rd;
	for(i=0;i<8;i++)	//由于NPC不一定有8方向,必须寻找一个最接近的方向
	{
		rd=(newdir+CGROLE_DIRECTION_FIND_ORDER[i])%8;
		if(MoveGrpahLines[rd]>=0) break;	//找到了
	}
	if(i<8)
		Direction=rd;	//如果找到才设置方向
}

void CGRole::RoleWalkOneStep()
{
	assert(m_pScene);

	LONG NX,NY;
	int i,rd;

	//由于在我们点鼠标的方向上不一定可以走,
	//所以必须寻找一个可以行走的最接近的方向
	for(i=0;i<=4;i++)	
	{
		rd=(Direction+CGROLE_DIRECTION_FIND_ORDER[i])%8;
		
		NX=XMPos+LONG(MoveSpeed*MOVESTEPS[rd*2]);
		NY=YMPos+LONG(MoveSpeed*MOVESTEPS[rd*2+1]);
	
		if(m_pScene->CanWalk(NX,NY,this))	break;		//找到一个方向了
	}
	
	if(i>4)
	{	
		Status = ROLESTAT_STAND;
		TempFrame = 0;
		CurrentFrame = 0;
	}
	else
	{
		SetMapPos(NX,NY);
		SetDirection(rd);
		
		//改变精灵动画帧
		TempFrame++;
		if(TempFrame>=MoveSwapFrameSpeed)
		{	
			TempFrame=0;
			CurrentFrame=(CurrentFrame+1)%FrameCount;
			if(CurrentFrame==0)	CurrentFrame++;
		}
	}
}

BOOL CGRole::CheckMouseHit(LONG lX,LONG lY) const
{
	assert(m_pScene);
	m_pScene->ScreenToMap(lX,lY);

	POINT pt;
	pt.x=lX-XMPos+XKPos;
	pt.y=lY-YMPos+YKPos;

	return PtInRect(&InsideRECT,pt);
}

HRESULT CGRole::RenderCombatRole(LONG lX, LONG lY, POINT MousePos, BOOL Anim /* = FALSE */)
{
	static SHORT CombatFrame=0;
	static DWORD CombatTimer=GetTickCount();
	DWORD Timer=GetTickCount();
	
	RECT rc;
	if (Anim)
	{
		if(Timer-CombatTimer>=150)
		{
			CombatTimer=Timer;
			CombatFrame=(CombatFrame+1)%FightFrames;
		}
		rc.top=FightGrpahLine*CellHeight;
		rc.bottom=rc.top+CellHeight;
		rc.left=CombatFrame*CellWidth;
		rc.right=rc.left+CellWidth;
	}
	else 
	{
		rc.top=FightGrpahLine*CellHeight;
		rc.bottom=rc.top+CellHeight;
		rc.left=0;
		rc.right=rc.left+CellWidth;
	}
	
		
	HRESULT hr;
	if(rc.top>=0)
	{
		hr = m_gGraph.BltFastTo(GAFDDraw.GetBack(),lX,lY,TRUE,&rc,TRUE);
		if (FAILED(hr))
			return hr;
		
		RECT rect;
		SetRect(&rect, lX, lY, lX+rc.right-rc.left, lY+rc.bottom-rc.top);

		if (PtInRect(&rect, MousePos))
		{
			HDC hdc = GAFDDraw.GetBack()->GetDC();
			HPEN hPen = CreatePen(PS_SOLID, 1, RGB(0,255,0));
			hPen = SelectPen(hdc, hPen);

			MoveToEx(hdc, rect.left, rect.top, NULL);
			LineTo(hdc, rect.right, rect.top);
			LineTo(hdc, rect.right, rect.bottom);
			LineTo(hdc, rect.left, rect.bottom);
			LineTo(hdc, rect.left, rect.top);
			
			hPen = SelectPen(hdc, hPen);
			DeleteObject(hPen);
			GAFDDraw.GetBack()->ReleaseDC();
		}

	}
	
	return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -