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

📄 map.cpp

📁 凌星科技_2004-5-17_《圣剑英雄传II》的源代码scr2
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//********************************************
//	地图 相关函数
//  创建于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 + -