📄 map.cpp
字号:
//********************************************
// 地图 相关函数
// 创建于2000年3月14日
//********************************************
#include <windows.h>
#include <stdio.h>
#include <fstream>
#include "gamelib\goldpoint.h"
#include "mapedit\mapedit.h"
#include "findpath.h"
#include "main.h"
#include "cursor.h"
#include "role.h"
#include "npc.h"
#include "talk.h"
#include "map.h"
#define GetX(n,w) ((n)%(w))
#define GetY(n,w) ((n)/(w))
int CMap::AniCellNum=0;
stAniCell *CMap::AniCell=NULL;
vectorAniCell CMap::m_vAniCell[4096]; // 动画CELL
int CMap::m_nAniCount[4096]; // 动画的进度
int CMap::m_nAniFrame[4096]; // 动画当前桢
//***************
//填写坐标表
CMap::CMap()
{
Cell = NULL;
strcpy(CurrentMapFileName,"Unknow"); //当前地图文件名
strcpy(CurrentMapFilePath,"Unknow"); //当前地图路径
m_pBackBmp = NULL;
}
CMap::~CMap()
{
ClearNpc();
_DELETE_ARRAY( Cell );
_DELETE_ARRAY(Block);
_DELETE_ARRAY( AniCell );
}
//读入动态元素
void CMap::LoadAniCell(char *file, char *index)
{
ifstream stream;
stream.open(file);
if( stream.is_open() )
{
stream >> AniCellNum; //AniCell的数量
for(int i=0; i<AniCellNum; i++)
{
m_vAniCell[i].clear(); //清除
long num=0;
stream >> num; //动画序列
for(int j=0; j<num; j++)
{
stAniCell st;
stream >> st.page >> st.cell >> st.time; //页,图块,时间
m_vAniCell[i].push_back(st);
}
}
stream.close();
}
memset(m_nAniCount, 0, 4096*4);
memset(m_nAniFrame, 0, 4096*4);
}
//***************
//初始化地图
bool CMap::InitMap(int w, int h)
{
Id=0;
strcpy(Name,"");
Width=w+1;
Height=h+1;
SX=SY=0; //所处场景的左上坐标,明确的说是可见区域的左上坐标
DX=DY=0; //生成场景时的左上坐标
CountDisplayGrid(); //计算显示格子
//声请格子内存
_DELETE_ARRAY(Cell);
_DELETE_ARRAY(Block);
Block = new bool[Width*Height];
Cell = new stCell[Width*Height];
//初始化格子
for(int i=0; i<Width*Height; i++)
{
Cell[i].GroundPic=0;
Cell[i].Ground=6;
Cell[i].ObjPic=0;
Cell[i].Obj=BLOCK_CELL;
Cell[i].Obj2Pic=0;
Cell[i].Obj2=BLOCK_CELL;
Cell[i].Level=0;
Cell[i].Level2=0;
Cell[i].Block=0;
Cell[i].CP=BLOCK_CP;
Cell[i].MouseType=0;
Block[i] = 0;
}
//陷阱数目
Hook_Num=0;
//初始化字体
char *strTemp = GameIni.ReadText("配置文件","字体");
ShowNameFont.LoadFont(strTemp, "地图名称字体");
_FREE(strTemp);
//初始化该地图的寻路节点数组
CFindPath cfp(&map);
cfp.Init(Width, Height);
// 初始化敌人设置
m_nEnemyNum = 0;
m_nEnemyFrequency = 0;
ClearEnemyList();
return true;
}
//***************
//读入地图
bool CMap::LoadMap(char *FileName)
{
FILE *fp;
fp=fopen(FileName, "rb");
if( fp==NULL )
{
ShowMessage("Load map file error!\n找不到文件:%s",FileName);
return false;
}
fseek(fp, 32, SEEK_SET); //挑过文件头
fread(&Id,4,1,fp);
fread(Name,32,1,fp);
fread(&Width,4,1,fp);
fread(&Height,4,1,fp);
//声请格子内存
_DELETE_ARRAY( Cell );
_DELETE_ARRAY(Block);
Cell=new stCell[Width*Height];
Block = new bool[Width*Height];
fread(Cell, sizeof(stCell), Width*Height, fp);
//读入陷阱列表
fread(&Hook_Num,4,1,fp);
fread(Hook, 64, Hook_Num, fp);
for(int i =0;i<Width*Height;i++)
Block[i]=0;
// 读入敌人列表
m_nEnemyNum = 0;
m_nEnemyFrequency = 0;
fread(&m_nEnemyNum, 4, 1, fp);
fread(m_pEnemyList, 4, 16, fp);
fread(&m_nEnemyFrequency, 4, 1, fp);
// 背景图片
m_strBackBmpFilename[0]=0;
_RELEASE(map.m_pBackBmp);
fread(m_strBackBmpFilename, 128, 1, fp);
if( m_strBackBmpFilename[0] )
{
CreateBitmap(map.m_pBackBmp, 0,0, map.m_strBackBmpFilename);
}
fclose(fp);
//清空NPC
ClearNpc();
//获取当前地图文件名和路径名
sprintf(CurrentMapFileName, "%s\\%s", CurrentPath, FileName);
char* str = GetFilePath(CurrentMapFileName);
strcpy(CurrentMapFilePath, str);
_FREE( str );
SX=SY=DX=DY=0;
CountDisplayGrid();
ClearEditData(); //清空编辑数据-避免出错
role[0].bMoving=false;
//读取当前地图的对话文件
char dialogfile[MAX_PATH];
sprintf(dialogfile, "%s%s", CurrentMapFilePath, "talk.txt");
talk.OpenFile( dialogfile );
//显示地图名字数秒种
ShowNameCount=70;
ShowNameAlpha=32;
//初始化该地图的寻路节点数组
CFindPath cfp(&map);
cfp.Init(Width, Height);
//初始话鼠标
CCursor::GetCursor(CCursor::CS_CHANGEMAP).pPic.SetShowCount(0);
return true;
}
//***************
//保存地图
bool CMap::SaveMap(char *FileName)
{
//清除人物的阻挡
//Cell[map.Width*role[0].State.Y+role[0].State.X].Block=0;
//for(int i=0; i<m_vNpc.size(); i++)
//{
// Cell[map.Width*m_vNpc[i]->State.Y+m_vNpc[i]->State.X].Block=0;
// }
//开文件
FILE *fp;
fp=fopen(FileName, "wb");
if( fp==NULL )
{
MessageBox(hWnd,"Save map file error!","",MB_OK);
return false;
}
fwrite(MAP_HEAD, 32, 1, fp); //文件头
fwrite(&Id,4,1,fp);
fwrite(Name,32,1,fp);
fwrite(&Width,4,1,fp);
fwrite(&Height,4,1,fp);
fwrite(Cell, sizeof(stCell), Width*Height, fp);
//保存陷阱列表
fwrite(&Hook_Num,4,1,fp);
fwrite(Hook, 64, Hook_Num, fp);
// 保存敌人列表
fwrite(&m_nEnemyNum, 4, 1, fp);
fwrite(m_pEnemyList, 4, 16, fp);
fwrite(&m_nEnemyFrequency, 4, 1, fp);
fwrite(m_strBackBmpFilename, 128, 1, fp);
fclose(fp);
//恢复人物的阻挡
//Cell[map.Width*role[0].State.Y+role[0].State.X].Block=1;
//for(i=0; i<m_vNpc.size(); i++)
// {
// Cell[map.Width*m_vNpc[i]->State.Y+m_vNpc[i]->State.X].Block=1;
// }
return true;
}
//***************
//读入进度
void CMap::Load(char *FileName)
{
FILE *fp;
fp=fopen(FileName, "rb");
if( fp==NULL )
{
ShowMessage("Load map record file %s error!",FileName);
return;
}
fread(&Id,4,1,fp);
fread(Name,32,1,fp);
fread(&Width,4,1,fp);
fread(&Height,4,1,fp);
//声请格子内存
_DELETE_ARRAY( Cell );
_DELETE_ARRAY( Block );
Cell=new stCell[Width*Height];
Block=new bool[Width*Height];
fread(Cell, sizeof(stCell), Width*Height, fp);
//陷阱列表
fread(&Hook_Num,4,1,fp);
fread(Hook, 64, Hook_Num, fp);
for(int i =0;i<Width*Height;i++)
Block[i]=0;
// 读入敌人列表
m_nEnemyNum = 0;
m_nEnemyFrequency = 0;
fread(&m_nEnemyNum, 4, 1, fp);
fread(m_pEnemyList, 4, 16, fp);
fread(&m_nEnemyFrequency, 4, 1, fp);
fread(&SX,4,1,fp);
fread(&SY,4,1,fp);
fread(&DX,4,1,fp);
fread(&DY,4,1,fp);
fread(&sx,4,1,fp);
fread(&sy,4,1,fp);
//当前地图文件名和路径名
char str[128];
memset(str, 0, 128);
fread(str, 128, 1, fp);
sprintf(CurrentMapFileName, "%s\\%s", CurrentPath, str);
memset(str, 0, 128);
fread(str, 128, 1, fp);
sprintf(CurrentMapFilePath, "%s\\%s", CurrentPath, str);
//读取NPC
long lNpcNum;
fread(&lNpcNum, 4, 1, fp);
ClearNpc();
char temp[MAX_PATH];
for(i=0; i<lNpcNum; i++)
{
sprintf(temp, "%s%d", FileName, i);
CNpc* p = new CNpc;
p->LoadRole(temp);
m_vNpc.push_back(p);
}
for(i=0; i<m_vNpc.size(); i++)
{
Block[map.Width*m_vNpc[i]->State.Y+m_vNpc[i]->State.X]=1;
}
// 背景图片
m_strBackBmpFilename[0]=0;
_RELEASE(map.m_pBackBmp);
fread(m_strBackBmpFilename, 128, 1, fp);
if( m_strBackBmpFilename[0] )
{
CreateBitmap(map.m_pBackBmp, 0,0, map.m_strBackBmpFilename);
}
fclose(fp);
CountDisplayGrid();
//读取当前地图的对话文件
char dialogfile[MAX_PATH];
sprintf(dialogfile, "%s%s", CurrentMapFilePath, "talk.txt");
talk.OpenFile( dialogfile );
//显示地图名字数秒种
ShowNameCount=70;
ShowNameAlpha=32;
//初始化该地图的寻路节点数组
CFindPath cfp(&map);
cfp.Init(Width, Height);
}
//***************
//保存进度
void CMap::Save(char *FileName)
{
//开文件
FILE *fp;
fp=fopen(FileName, "wb");
if( fp==NULL )
{
ShowMessage("Save map record file %s error!",FileName);
return;
}
fwrite(&Id,4,1,fp);
fwrite(Name,32,1,fp);
fwrite(&Width,4,1,fp);
fwrite(&Height,4,1,fp);
fwrite(Cell, sizeof(stCell), Width*Height, fp);
//保存陷阱列表
fwrite(&Hook_Num,4,1,fp);
fwrite(Hook, 64, Hook_Num, fp);
// 保存敌人列表
fwrite(&m_nEnemyNum, 4, 1, fp);
fwrite(m_pEnemyList, 4, 16, fp);
fwrite(&m_nEnemyFrequency, 4, 1, fp);
fwrite(&SX,4,1,fp);
fwrite(&SY,4,1,fp);
fwrite(&DX,4,1,fp);
fwrite(&DY,4,1,fp);
fwrite(&sx,4,1,fp);
fwrite(&sy,4,1,fp);
//当前地图文件名和路径名
char str[128];
memset(str, 0, 128);
strcpy(str, &CurrentMapFileName[strlen(CurrentPath)+1]);
fwrite(str, 128, 1, fp);
memset(str, 0, 128);
strcpy(str, &CurrentMapFilePath[strlen(CurrentPath)+1]);
fwrite(str, 128, 1, fp);
//保存NPC
char temp[MAX_PATH];
long lNpcNum = m_vNpc.size();
fwrite(&lNpcNum, 4, 1, fp);
for(int i=0; i<lNpcNum; i++)
{
sprintf(temp, "%s%d", FileName, i);
m_vNpc[i]->SaveRole(temp);
}
// 背景图片
fwrite(m_strBackBmpFilename, 128, 1, fp);
fclose(fp);
}
// 获取动态图素的当前页和RECT(地面层)
long CMap::GetAniCellPage(const long ground, RECT& rect)
{
long num = Cell[ ground ].Ground; //编号
long page = m_vAniCell[num][ m_nAniFrame[num] ].page; //当前页
long cell = m_vAniCell[num][ m_nAniFrame[num] ].cell; //图块
rect=_GetRectangle(cell, ShowCellW);
return page;
}
// 获取动态图素的当前页和RECT(物体层1)
long CMap::GetAniCellPageObj(const long ground, RECT& rect)
{
long num = Cell[ ground ].Obj;
long page = m_vAniCell[num][ m_nAniFrame[num] ].page;
long cell = m_vAniCell[num][ m_nAniFrame[num] ].cell;
rect=_GetRectangle(cell, ShowCellW);
return page;
}
// 获取动态图素的当前页和RECT(物体层2)
long CMap::GetAniCellPageObj2(const long ground, RECT& rect)
{
long num = Cell[ ground ].Obj2;
long page = m_vAniCell[num][ m_nAniFrame[num] ].page;
long cell = m_vAniCell[num][ m_nAniFrame[num] ].cell;
rect=_GetRectangle(cell, ShowCellW);
return page;
}
// 获取动态图素的当前页和RECT(直接用编号)
long CMap::GetAniPage(const long num, RECT& rect)
{
long page = m_vAniCell[num][ m_nAniFrame[num] ].page;
long cell = m_vAniCell[num][ m_nAniFrame[num] ].cell;
rect=_GetRectangle(cell, ShowCellW);
return page;
}
// 动画过一桢
long CMap::AniLoop()
{
for(int i=0; i<AniCellNum; i++)
{
if( ++m_nAniCount[i] > m_vAniCell[i][m_nAniFrame[i]].time ) //延时
{
m_nAniCount[i] = 0;
if( ++m_nAniFrame[i] >= m_vAniCell[i].size() )
{
m_nAniFrame[i] = 0; //当前桢
}
}
}
return true;
}
//*******************
//显示地图到surf上
void CMap::ShowMap(bool active,LPDIRECTDRAWSURFACE surf)
{
int i,j, cellnum, obj, obj2, level;
RECT rect = {0,0,0,0};
// 显示背景
if( m_pBackBmp )
{
int w, h;
GetSurfaceSize(m_pBackBmp, w, h);
rect.right = w;
rect.bottom = h;
BltFast(surf, 0, 0, m_pBackBmp, rect, false);
}
//更新人物位置
if( active )
{
//主角移动
role[0].Move(role[0].State.X, role[0].State.Y);
CurrentNpc=-1;
for(i=0; i<m_vNpc.size(); i++)
{
//NPC移动
if( m_vNpc[i]->State.bActive && !m_vNpc[i]->bMoving )
{
if( random(100)>98 )
{
m_vNpc[i]->MoveTo(random(Width)*CellWidth, random(Height)*CellHeight);
}
}
m_vNpc[i]->Move(m_vNpc[i]->State.X, m_vNpc[i]->State.Y);
}
}
//计算显示坐标 startx\endx\starty\endy
CountDisplayGrid();
//显示地面
int ground=Width * starty + startx;
for(i=starty; i<endy ; i++)
{
for(j=startx; j<endx ; j++)
{
if( Cell[ ground ].GroundPic < 60 ) //静态元素
{
//位于地图页面的位置矩形
rect=_GetRectangle(Cell[ ground ].Ground, ShowCellW);
//Blt到surf上
BltFast(surf, DX+_point_x(j-SX), DY+_point_y(i-SY),
lpDDSMap[ Cell[ ground ].GroundPic ], rect, true);
ground++;
}
else // 动态图素
{
RECT rect = {0,0,0,0};
long page = GetAniCellPage(ground, rect);
BltFast(surf, DX+_point_x(j-SX), DY+_point_y(i-SY),
lpDDSMap[ page ], rect, true);
ground++;
}
}
//下一行
ground=ground+Width-(endx-startx);
}
//显示物体
for(i=starty; i<endy ; i++)
for(j=endx-1; j>=startx; j--)
{
//TILE坐标
cellnum=Width * i + j;
//画不能遮挡主角的物体 level1
level=Cell[ cellnum ].Level;
if( level==OL_NORMAL ) //人物同级
{
obj=Cell[ cellnum ].Obj; //编号
if( obj != BLOCK_CELL ) //不是空格子
{
if( Cell[ cellnum ].ObjPic < 60 ) //静态元素
{
rect=_GetRectangle(obj, ShowCellW);
Blt(surf, DX+ _point_x(j-SX), DY+ _point_y(i-SY),
lpDDSMap[Cell[ cellnum ].ObjPic], rect, TRUE);
}
else // 动态图素
{
RECT rect = {0,0,0,0};
long page = GetAniCellPageObj(cellnum, rect);
Blt(surf, DX+ _point_x(j-SX), DY+ _point_y(i-SY),
lpDDSMap[page], rect, TRUE);
}
}
}
//画不能遮挡主角的物体 level2
level=Cell[ cellnum ].Level2;
if( level==OL_NORMAL ) //人物同级
{
obj2=Cell[ cellnum ].Obj2; //编号
if( obj2 != BLOCK_CELL ) //不是空的
{
if( Cell[ cellnum ].Obj2Pic < 60 ) //静态元素
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -