📄 grole.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 + -