📄 cgame.cpp
字号:
//--------------------------------------------------------------------------------------------------------
// 游戏主引擎模块
//CGame.cpp
//游戏引擎中的主引擎部分
//作者:吴振华(kylinx)(中国科大01级11系)
//E-mail:game-diy@163.com
//创建于:2003/6/19 by Kylinx
//最后修改于2003/7/28 by Kylinx
//--------------------------------------------------------------------------------------------------------
#include<time.h>
#include<stdio.h>
#include"CGame.h"
#include"CError.h"
#include"CGoods.h"
#include"CBattle.h"
#include"CGameData.h"
#include"CGraph.h"
#include"CMagic.h"
#include"CMessage.h"
#include"CMap.h"
#include"CButton.h"
#include"CTalk.h"
#include"CScript.h"
#include"CMenu.h"
#include"CMessageBox.h"
#include"CIniFile.h"
#include"CFont.h"
#include"CRenderPicture.h"
#include"CMacro.h"
#include"CBuyAndSell.h"
#include"CCursor.h"
#include"LoaMapEditor\\resource.h"
char CGame::s_szCurrentDir[1024];
////////////////////////////////////////////////////////////////////////////////////////////
//构造
////////////////////////////////////////////////////////////////////////////////////////////
CGame::CGame()
{
memset(this,0,sizeof(CGame));
m_bIsNight=false;
m_pdbMagic=NULL;
m_pdbGoods=NULL;
m_pGameData=NULL;
m_pDisplay=NULL;
m_pPlayer=NULL;
m_bShowFPS=false;
m_bRandomBattle=false;
m_bDitherScreen=false;
m_bScriptControlling=true;
m_nBattleFrequency=5;
memset(s_szCurrentDir,0,1024);
::GetCurrentDirectory(1024,s_szCurrentDir);
m_pLog=new CLog("GameLog.txt");
srand(time(0));
}
////////////////////////////////////////////////////////////////////////////////////////////
//析构
////////////////////////////////////////////////////////////////////////////////////////////
CGame::~CGame()
{
}
////////////////////////////////////////////////////////////////////////////////////////////
//调节Gamma,类似夜晚效果
////////////////////////////////////////////////////////////////////////////////////////////
void CGame::SetNight()
{
m_bIsNight=true;
DDGAMMARAMP ddGammaRamp;
DDGAMMARAMP ddGammaStart=m_pDisplay->GetGamma();
for(int i=0;i<256;i++)
{
ddGammaRamp.blue[i]=ddGammaStart.blue[i];
ddGammaRamp.red[i]=ddGammaStart.red[i]>>1;
ddGammaRamp.green[i]=ddGammaStart.green[i]>>1;
}
m_pDisplay->SetGamma(ddGammaRamp);
}
////////////////////////////////////////////////////////////////////////////////////////////
//得到绝对路径
////////////////////////////////////////////////////////////////////////////////////////////
char*CGame::GetAbsolutePath(char*szRelativePath)
{
LOA_ASSERT(szRelativePath!=NULL);
return strcat(s_szCurrentDir,szRelativePath);
}
////////////////////////////////////////////////////////////////////////////////////////////
//初始化数据库
////////////////////////////////////////////////////////////////////////////////////////////
BOOL CGame::InitGameDataBase()
{
m_pMapSurface=new CMapSurface();
if(!m_pMapSurface)
{
m_pLog->WriteMessage("New CMapSurface() Failed!\n");
return false;
}
m_pRoleBlock=KGDStack<POINT>::ForeCreate();
m_pNpcList=KGDList<STRenderRole*>::ForeCreate();
if(!m_pNpcList)
{
m_pLog->WriteMessage("New Npc List Failed!\n");
return false;
}
m_pRoleQueue=CLagQueue<STRenderRole*>::ForeCreate();
if(!m_pRoleQueue)
{
m_pLog->WriteMessage("New RenderRole Queue Failed!\n");
return false;
}
m_pMap=new CMap(m_pLog);
if(!m_pMap)
{
m_pLog->WriteMessage("New CMap Failed!\n");
return false;
}
m_pRender=new CRender();
if(!m_pRender)
{
m_pLog->WriteMessage("New CRender Failed!Out of memory!\n");
return false;
}
m_pMsg=new CMessage();
if(!m_pMsg)
{
m_pLog->WriteMessage("New CMessage Failed!Out of memory!\n");
return false;
}
if(!m_pMsg->InitMessageQueue(m_pLog))
{
m_pLog->WriteMessage("Init Message Queue Failed!\n");
return false;
}
m_pdbChangeMap=IDataBase<STChangeMapData>::ForeCreate();
if(!m_pdbChangeMap )
{
m_pLog->WriteMessage("Create Change Map Database Failed!\n");
return false;
}
m_pdbLoadScript=IDataBase<STLoadScriptData>::ForeCreate();
if(!m_pdbLoadScript )
{
m_pLog->WriteMessage("Create Load Script Database Failed!\n");
return false;
}
//查找所有的地图文件,创建地图文件数据库
WIN32_FIND_DATA wfd;
ZeroMemory(&wfd,sizeof(wfd));
STChangeMapData*pCmd=NULL;
STLoadScriptData*pScrdata=NULL;
HANDLE hff=::FindFirstFile("map\\*.lmp",&wfd);
char tmp[256];
if(hff!=INVALID_HANDLE_VALUE)
{
memset(tmp,0,256);
CMap map(NULL);
STMapHead maphead;
wsprintf(tmp,"map\\%s",wfd.cFileName);
map.GetMapHead(tmp,&maphead);
pCmd=new STChangeMapData;
pCmd->ID=maphead.ID;
strncpy(pCmd->szName,tmp,128);
if(pCmd->ID!=0)
m_pdbChangeMap->AddData(pCmd->ID,pCmd);
while(::FindNextFile(hff,&wfd))
{
memset(tmp,0,256);
wsprintf(tmp,"map\\%s",wfd.cFileName);
map.GetMapHead(tmp,&maphead);
pCmd=new STChangeMapData;
pCmd->ID=maphead.ID;
strncpy(pCmd->szName,tmp,128);
if(pCmd->ID!=0)
m_pdbChangeMap->AddData(pCmd->ID,pCmd);
}
::FindClose(hff);
}
//查找所有脚本文件,创建脚本文件数据库
hff=::FindFirstFile("script\\*.lsr",&wfd);
if(hff!=INVALID_HANDLE_VALUE)
{
memset(tmp,0,256);
CIniFile inifile;
wsprintf(tmp,"script\\%s",wfd.cFileName);
pScrdata=new STLoadScriptData;
pScrdata->ID=::GetPrivateProfileInt("Info","ID",0,tmp);
strncpy(pScrdata->szName,tmp,128);
if(pScrdata->ID!=0)
m_pdbLoadScript->AddData(pScrdata->ID,pScrdata);
while(::FindNextFile(hff,&wfd))
{
memset(tmp,0,256);
wsprintf(tmp,"script\\%s",wfd.cFileName);
pScrdata=new STLoadScriptData;
pScrdata->ID=::GetPrivateProfileInt("Info","ID",0,tmp);
strncpy(pScrdata->szName,tmp,128);
if(pScrdata->ID!=0)
m_pdbLoadScript->AddData(pScrdata->ID,pScrdata);
}
::FindClose(hff);
}
m_pLog->WriteMessage("Create Change Map Database...OK!\n");
m_pdbGoods=IDataBase<STGood>::ForeCreate();
if(!m_pdbGoods)
{
m_pLog->WriteMessage("New GoodsDataBase Failed! Out of Memory!\n");
return false;
}
m_pdbMagic=IDataBase<STMagic>::ForeCreate();
if(!m_pdbMagic)
{
m_pLog->WriteMessage("New MagicDataBase Failed! Out of Memory!\n");
return false;
}
m_pdbEffect=IDataBase<STEffect>::ForeCreate();
if(!m_pdbEffect)
{
m_pLog->WriteMessage("New EffectDataBase Failed! Out of Memory!\n");
return false;
}
m_pGameData=new CGameData(m_pLog);
if(!m_pGameData)
{
m_pLog->WriteMessage("New Game Data Class Failed! Out of Memory!\n");
return false;
}
char szGoodsDataFile[]="data\\goods.dat";
m_pLog->WriteMessage("正在从物品数据文件%s获得物品数据...\n",szGoodsDataFile);
if(!m_pGameData->CreateGoodsDataBase(szGoodsDataFile,&m_pdbGoods))
{
m_pLog->WriteMessage("初始化物品数据库...Failed!\n");
return false;
}
m_pLog->WriteMessage("初始化物品数据库...OK!\n");
m_pRenderMap=new CRenderMap();
m_pRenderMap->CreateTask(true,true,0xffff); //高优先级
m_pRender->AddTask(m_pRenderMap);
m_pRoleGraph=new CRoleGraph(m_pLog);
if(!m_pRoleGraph)
{
m_pLog->WriteMessage("New CRole Graph Failed!\n");
return false;
}
m_pLog->WriteMessage("New CRoleGraph OK!\n");
m_pScriptData=new CScriptData;
m_pScriptData->InitScriptVariable(m_pLog,4096);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////
//设置显示模式
////////////////////////////////////////////////////////////////////////////////////////////
BOOL CGame::CreateDisplayMode(BOOL bWindowed)
{
if(bWindowed)
{
if(FAILED(m_pDisplay->CreateWindowedDisplay(m_hWnd,640,480,WS_OVERLAPPED | WS_CAPTION| WS_MINIMIZEBOX)))
return false;
else
return true;
}
else
{
if(FAILED(m_pDisplay->CreateFullScreenDisplay(m_hWnd,640,480,16)))
return false;
else
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////////////
//截图
////////////////////////////////////////////////////////////////////////////////////////////
BOOL CGame::ScreenShot()
{
//查找已经截下来的bmp文件,得到正确的一个索引,防止覆盖以前的文件
WIN32_FIND_DATA wfd;
ZeroMemory(&wfd,sizeof(wfd));
HANDLE hff=::FindFirstFile("screenshot\\LOABMP*.bmp",&wfd);
int index=0;
if(hff!=INVALID_HANDLE_VALUE)
{
sscanf(wfd.cFileName,"LOABMP%d.bmp",&index);
while(::FindNextFile(hff,&wfd))
{
sscanf(wfd.cFileName,"LOABMP%d.bmp",&index);
}
::FindClose(hff);
}
index++;
char szBmpFile[256];
wsprintf(szBmpFile,"screenshot\\LOABMP%d.bmp",index);
FILE*fp=fopen(szBmpFile,"wb");
if(!fp)
return false;
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
m_pDisplay->GetBackBuffer()->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
WORD*pBuf=(WORD*)ddsd.lpSurface;
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
bfh.bfType=0x4d42;
bfh.bfReserved1=0;
bfh.bfReserved2=0;
bfh.bfOffBits=sizeof(bfh)+sizeof(bih);
bfh.bfSize=ddsd.dwWidth*ddsd.dwHeight*3+bfh.bfOffBits; //保存为24位色的bmp,所以大小要*3
bih.biBitCount=24;
bih.biClrImportant=0;
bih.biClrUsed=0;
bih.biCompression=BI_RGB;
bih.biHeight=ddsd.dwHeight;
bih.biWidth=ddsd.dwWidth;
bih.biPlanes=1;
bih.biSize=sizeof(bih);
bih.biSizeImage=ddsd.dwWidth*ddsd.dwHeight*3;
bih.biXPelsPerMeter=0;
bih.biYPelsPerMeter=0;
fwrite(&bfh,sizeof(bfh),1,fp);
fwrite(&bih,sizeof(bih),1,fp);
pBuf=pBuf+ddsd.dwWidth*(ddsd.dwHeight-1);
//倒着存放,从下到上
if(m_pDisplay->Is565()) //如果表面是565格式
{
for(DWORD i=0;i<ddsd.dwHeight;i++)
{
for(DWORD j=0;j<ddsd.dwWidth;j++)
{
fputc((*pBuf & 0x1f)<<3,fp); //b
fputc((*pBuf >>3)&0xff,fp); //g
fputc((*pBuf >>8)&0xff,fp); //r
pBuf++;
}
pBuf-=ddsd.lPitch;//(ddsd.lPitch>>1)<<1;
}
}
else
{
for(DWORD i=0;i<ddsd.dwHeight;i++)
{
for(DWORD j=0;j<ddsd.dwWidth;j++)
{
fputc((*pBuf & 0x1f)<<3,fp); //b
fputc((*pBuf >>2)&0xff,fp); //g
fputc((*pBuf >>7)&0xff,fp); //r
pBuf++;
}
pBuf-=ddsd.lPitch;//(ddsd.lPitch>>1)<<1;
}
}
m_pDisplay->GetBackBuffer()->Unlock(NULL);
fclose(fp);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////
//窗口过程
////////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK CGame::WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static CGame*pGame=NULL;
switch(message)
{
case UM_SETGAME:
pGame=(CGame*)wParam;
break;
case UM_GRAPHNOTIFY: //DirectShow消息
if(pGame)
{
pGame->m_pDShow->HandleGraphEvent();
if(!pGame->m_pDShow->IsPlaying())
{
::SetActiveWindow(pGame->m_hWnd);
}
}
break;
case WM_SETCURSOR:
ShowCursor(false);
break;
case WM_ACTIVATEAPP:
if(pGame)
pGame->m_bActive=wParam;
break;
case WM_MOVE:
case WM_SIZE:
{
if(!pGame)
break;
pGame->m_pDisplay->UpdateBounds();
}
break;
case WM_CLOSE:
{
if(pGame)
{
CMessageBox msgbox;
if(LOA_MSG_BOX_IDYES==msgbox.ShowMessageBox(pGame,LOA_MSG_BOX_YESNO,"确实要退出么?"))
DestroyWindow(hWnd);
}
else
{
DestroyWindow(hWnd);
}
}
break;
case WM_DESTROY:
{
if(pGame)
pGame->m_bPlayGame=false;
PostQuitMessage(0);
}
break;
case WM_KEYDOWN:
{
switch(LOWORD(wParam))
{
case VK_F9:
{
if(pGame)
pGame->ScreenShot();
}
break;
case VK_F8:
{
if(pGame)
pGame->m_bShowFPS=!pGame->m_bShowFPS;
}
break;
case VK_F5:
{
if(pGame)
{
if(pGame->m_bRandomBattle)
pGame->m_bRandomBattle=false;
else
pGame->m_bRandomBattle=true;
}
}
break;
default:
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -