📄 gscene.cpp
字号:
//////////////////////////////////////////////////////////////////////
// GScene.cpp: implementation of the CGScene class.
// RPGDemo框架程序 场景类
// written by 萧萧落木(Roc.j.Wood)
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GScene.h"
#include <fstream.h>
#include <algorithm>
#include <string>
#include <functional>
using namespace std;
struct COMPARE_ROLEPOS_LESS : public binary_function<LPCGRole, LPCGRole, bool> {
bool operator()(LPCGRole r1, LPCGRole r2)
{
if(r1==NULL) return false;
if(r2==NULL) return true;
static int x1,x2,y1,y2,lv1,lv2;
lv1=r1->GetLevel();
lv2=r2->GetLevel();
if(lv1==lv2)
{
r1->GetMapPos(x1,y1);
r2->GetMapPos(x2,y2);
return y1<y2;
}
return lv1<lv2;
}
};
HRESULT CGSceneLayer::RenderLayer(CGAFDDrawSurface &gDDSurface, LONG XOff, LONG YOff)
{
assert(RectCount==0||(RectCount>0&&pRectArray));
for(int i=0;i<RectCount;i++)
{
LONG lX=pRectArray[i].left+XOff;
LONG lY=pRectArray[i].top+YOff;
HRESULT hr=gDDSurface.BltFastTo(GAFDDraw.GetBack(),lX,lY,FALSE,pRectArray+i,TRUE);
TESTHR_RET(hr);
}
return S_OK;
}
#pragma pack(push,1)
struct WORDRECT
{
WORD Left;
WORD Top;
WORD Width;
WORD Height;
};
#pragma pack(pop)
HRESULT CGSceneLayer::LoadLayer(::fstream &fs)
{
ClearLayer();
try
{
fs.read((CHAR*)(&RectCount),sizeof(DWORD));
if(RectCount>0)
{
pRectArray = new RECT[RectCount];
if(pRectArray==NULL) throw;
}
for(int i=0;i<RectCount;i++)
{
WORDRECT rt;
fs.read((CHAR*)(&rt),sizeof(WORDRECT));
pRectArray[i].left=rt.Left;
pRectArray[i].top=rt.Top;
pRectArray[i].right=rt.Left+rt.Width;
pRectArray[i].bottom=rt.Top+rt.Height;
}
}
catch(...)
{
ClearLayer();
return E_FAIL;
}
return S_OK;
}
CGScene::CGScene(CRPGGame *pGameApp)
{
assert(pGameApp);
m_pGameApp = pGameApp;
ScreenWidth = GAFDDraw.GetBack()->GetWidth();
ScreenHeight = GAFDDraw.GetBack()->GetHeight();
HCells =
VCells =
Width =
Height =
XPosition =
YPosition =
ObjCount =
ExitCount =
RoleCount = 0;
memset(m_szName,0,16);
memset(m_RoleArray,0,sizeof(LPCGRole)*CG_NUM_MAXROLEINSCENE);
memset(m_ExitArray,0,sizeof(CGSceneExit)*CG_NUM_MAXEXITINSCENE);
m_pMapInfo = NULL;
}
CGScene::~CGScene()
{
FinalClearup();
}
HRESULT CGScene::LoadMAP(LPCTSTR szFileName)
{
assert(szFileName);
string fName;
fName="SCENE\\";
fName.append(szFileName);
::fstream fs;
fs.open(fName.c_str(),ios::in|ios::binary);
if(fs.is_open()==FALSE) return E_FAIL;
try
{
DWORD MAPFLAG;
DWORD MAPVER;
fs.read((CHAR *)&MAPFLAG,4);
fs.read((CHAR *)&MAPVER,4);
if(MAPFLAG!=MAKEFOURCC('G','M','A','P') || MAPVER!=0x0101) return -1;
CHAR GraphFName[32];
fs.read(GraphFName,32);
fName="SCENE\\";
fName.append(GraphFName);
HRESULT hr = m_gGraph.CreateByJPEG(&GAFDDraw,fName.c_str());
TESTHR_RET(hr);
LONG tmpWidth = m_gGraph.GetWidth();
LONG tmpHeight= m_gGraph.GetHeight();
fs.read((CHAR *)&Width,4);
fs.read((CHAR *)&Height,4);
if(tmpWidth!=Width || tmpHeight!=Height) return -2;
MapToCell(tmpWidth,tmpHeight);
SAFE_DELETE_ARRAY(m_pMapInfo);
m_pMapInfo = new WORD[tmpWidth*tmpHeight];
if(m_pMapInfo==NULL) return E_OUTOFMEMORY;
fs.read((CHAR *)m_pMapInfo,tmpHeight*tmpWidth*sizeof(WORD));
for(int Lv=0;Lv<256;Lv++)
{
hr = m_gSceneLayers[Lv].LoadLayer(fs);
TESTHR_TRW(hr);
}
}
catch(...)
{
fs.close();
return E_FAIL;
}
fs.close();
return S_OK;
}
#pragma pack(push,1)
struct SCNOBJECT
{
WORD X,Y; //格子坐标(0..HCells-1,0..VCells-1)
WORD Idx; //道具编号
WORD Enable; //是否空箱子? 1表示有东西,0表示空了
};
struct SCNEXIT
{
WORD X1,Y1,X2,Y2; //出口出发区域(格子坐标)
CHAR SCNName[32]; //对应的场景文件
WORD TX,TY; //切换场景以后在目标场景出现的格子坐标
};
struct SCNROLE
{
WORD X,Y; //站立的格子坐标
WORD Dir; //方向
CHAR ROLName[32]; //对应角色文件(*.ROL)
};
struct SCSNEFILEHEADRER
{
DWORD SCNFLAG;
DWORD Version;
CHAR szName[16]; //场景名称
CHAR szMapName[32]; //场景对应MAP文件名
DWORD Width; //由对应的MAP文件设定
DWORD Height; //由对应的MAP文件设定
DWORD HCells; //Width/16,水平格子数(方格大小16*16)
DWORD VCells; //Height/16,垂直格子数
};
#pragma pack(pop)
inline void LOADINGMSG(const string &Msg, DWORD DelayMS=50)
{
GAFDDraw.GetBack()->Fill(0);
GAFDDraw.GetBack()->TextXY(10,450,0xFFFFFF,(LPCTSTR)Msg.c_str());
GAFDDraw.Present(TRUE,FALSE);
Sleep(DelayMS);
}
HRESULT CGScene::LoadScene(LPCTSTR szFileName)
{
assert(szFileName);
LOADINGMSG("清除残余角色列表...");
ClearupROLEArray(FALSE);
string fName;
fName="SCENE\\";
fName.append(szFileName);
LOADINGMSG(string("打开场景文件")+fName+"...");
::fstream fs;
fs.open(fName.c_str(),ios::in|ios::binary);
if(fs.is_open()==FALSE) return E_FAIL;
//装载场景文件
try
{
SCSNEFILEHEADRER ScnFile;
fs.read((CHAR*)&ScnFile,sizeof(ScnFile));
if(ScnFile.SCNFLAG!=MAKEFOURCC('G','S','C','N') || ScnFile.Version!=0x0106) return -1;
memcpy(m_szName,ScnFile.szName,16);
Width = ScnFile.Width;
Height = ScnFile.Height;
HCells = ScnFile.HCells;
VCells = ScnFile.VCells;
LOADINGMSG(string("装入场景地图文件")+ScnFile.szMapName+"...",0);
HRESULT hr;
hr = LoadMAP(ScnFile.szMapName);
TESTHR_RET(hr);
int i;
//装入道具列表
LOADINGMSG("装入道具列表设定...");
fs.read((CHAR*)&ObjCount,4);
assert(ObjCount==0);
//装入出口列表
LOADINGMSG("装入场景出口列表设定...");
fs.read((CHAR*)&ExitCount,4);
for(i=0;i<ExitCount;i++)
{
SCNEXIT exit;
fs.read((CHAR*)&exit,sizeof(SCNEXIT));
m_ExitArray[i].Enable=TRUE;
m_ExitArray[i].TX=exit.TX;
m_ExitArray[i].TY=exit.TY;
memcpy(m_ExitArray[i].TargetScene,exit.SCNName,32);
SetRect(&(m_ExitArray[i].rt),exit.X1*16,exit.Y1*16,exit.X2*16,exit.Y2*16);
}
//装入角色列表
LOADINGMSG("装入角色列表设定...");
LONG Count;
fs.read((CHAR*)(&Count),4);
for(i=0;i<Count;i++)
{
SCNROLE rol;
fs.read((CHAR*)(&rol),sizeof(SCNROLE));
hr = AddNewRole(rol.ROLName,rol.X,rol.Y,rol.Dir);
TESTHR_MSGTRW(hr,"CGScene场景装入角色出错!");
}
}
catch(...)
{
fs.close();
return E_FAIL;
}
fs.close();
LOADINGMSG("场景装入成功,进入场景模式...",200);
return S_OK;
}
void CGScene::FinalClearup()
{
m_pGameApp = NULL;
memset(m_szName,0,16);
ClearupROLEArray(TRUE);
SAFE_DELETE_ARRAY(m_pMapInfo);
}
void CGScene::SortRoleList()
{
BOOL Flag=TRUE;
while(Flag)
{
static COMPARE_ROLEPOS_LESS _CompareFunc;
Flag=FALSE;
for(int i=CG_NUM_MAXROLEINSCENE-1;i>0;i--)
{
if(_CompareFunc(m_RoleArray[i],m_RoleArray[i-1]))
{
swap(m_RoleArray[i],m_RoleArray[i-1]);
Flag=TRUE;
}
}
}
}
HRESULT CGScene::RenderScene()
{
LONG XOff=-XPosition;
LONG YOff=-YPosition;
GAFDDraw.GetBack()->Fill(0);
//给所有角色按照层次信息和y坐标递增排序
SortRoleList();
int roleidx=0;
for(SHORT Level=0;Level<256;Level+=2) //一次渲染成组的2个层
{
//渲染第Level层道具箱
//未完成
//渲染第Level层景物
m_gSceneLayers[Level].RenderLayer(m_gGraph,XOff,YOff);
//渲染第Level层角色
for(;roleidx<RoleCount;roleidx++)
if(m_RoleArray[roleidx])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -