www.pudn.com > GameEngine_src.rar > CMap.cpp


// CMap.cpp: implementation of the CMap class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "CMap.h" 
#include "normal.h" 
#include "BaseUtil.h" 
#include "CEPKFile.h" 
#include "CEasyAudio.h" 
#include "CHero.h" 
#include "CDInput.h" 
#include "CGameManager.h" 
#include "CNpcDlg.h" 
#include "CMagic.h" 
#include "CSpriteFactory.h" 
#include "CItemFactory.h" 
 
extern PEASYDRAW g_pEasyDraw; 
extern PEASYAUDIO g_pEasyAudio; 
extern CHero	theHero; 
extern CDIMouse	theMouse; 
extern CGameManager	theGameManager; 
extern CSpriteFactory	theSpriteFactory; 
extern CNpcDlgMgr		theNpcDlgMgr; 
extern CItemFactory		theItemFactory; 
 
 
//用于载入建筑物EPG的结构 
struct BUILDING_EPG 
{ 
	BUILDING_EPG( CPictureGroup *p, CPictureGroup *s ) 
	{ pPG = p; pSPG = s; } 
 
	BUILDING_EPG(){} 
 
	CPictureGroup *pPG; 
	CPictureGroup *pSPG; 
}; 
 
//**********************************************CMap类实现******************************************************** 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
CMap::CMap() 
{ 
	m_iWidth	= 0; 
	m_iHeight	= 0; 
	m_TileArray = NULL; 
	m_CellArray = NULL; 
	m_SurfInfo	= NULL; 
	m_IndexHeroPoint = 0; 
} 
 
CMap::~CMap() 
{ 
 
} 
 
 
////////////////////////////////////////////////////////////////////// 
//width,height是地图宽高,单位是TILE 
////////////////////////////////////////////////////////////////////// 
bool CMap::Init() 
{	 
	//init render queue 
	bool b = m_RenderQueue.Init( 64 ); 
	if ( !b ) return false; 
 
	b = m_BuildingArray.Init( 64 ); 
	if ( !b ) return false; 
 
	b = m_BuildingPGArray.Init( 64 ); 
	if ( !b ) return false; 
 
	b = m_MovingSpritePool.Init( 16 ); 
	if ( !b ) return false; 
 
	b = m_SelectQueue.Init( 16 ); 
	if ( !b ) return false; 
 
	b = m_MagicSpritePool.Init( 64 ); 
	if ( !b ) return false; 
 
	m_SurfInfo = g_pEasyDraw->CreateSurfaceEx( NULL, g_pEasyDraw->GetCharWidth()*16,  
										g_pEasyDraw->GetCharHeight(), 0, true, 0 ); 
	if ( m_SurfInfo == NULL )	return false; 
 
	m_Viewer.left = 0; 
	m_Viewer.top = 0; 
	m_Viewer.right = g_pEasyDraw->GetDeviceWidth(); 
	m_Viewer.bottom = g_pEasyDraw->GetDeviceHeight(); 
 
	return b; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::Free() 
{ 
	SafeDeleteArray( m_CellArray ); 
	SafeDeleteArray( m_TileArray ); 
 
	for ( int i = 0; i < m_TileSurfaceArray.GetLength(); ++i ) 
		g_pEasyDraw->DeleteSurface( m_TileSurfaceArray[i] ); 
 
	m_TileSurfaceArray.Free(); 
	m_RenderQueue.Free(); 
	m_BuildingPGArray.Free(); 
	m_BuildingArray.Free(); 
	m_MovingSpritePool.Free(); 
 
	m_iHeight = 0; 
	m_iWidth = 0; 
	m_CellPitch = 0; 
} 
 
////////////////////////////////////////////////////////////////////// 
//width,height是地图宽高,单位是TILE 
////////////////////////////////////////////////////////////////////// 
bool CMap::CreateMap( int width, int height ) 
{ 
	//alloc cell array 
	m_CellNum	= width * height * 16; 
	m_CellArray = new BYTE[ m_CellNum ]; 
	if ( m_CellArray == NULL ) return false; 
 
	memset( m_CellArray, 0, m_CellNum ); 
	m_CellPitch = width * 4; 
 
 
	//alloc tile array 
	int NumTile = width * height; 
	m_TileArray = new TILE[NumTile]; 
	if ( m_TileArray == NULL ) return false; 
 
	//init tile array 
	for ( int i = 0; i < height; ++i ) 
	{ 
		for ( int j = 0; j < width; ++j ) 
		{ 
			int left	= j * TILE_WIDTH; 
			int top		= i * TILE_HEIGHT;  
			TILE &tile  = m_TileArray[i * width + j]; 
			tile.m_Rect.left = left; 
			tile.m_Rect.top  = top; 
			tile.m_Rect.right= left + TILE_WIDTH - 1;			//注意要-1 
			tile.m_Rect.bottom=top + TILE_HEIGHT - 1; 
			tile.m_Surf = NULL; 
 
			if ( tile.Init() == false ) 
				assert(false); 
		} 
	} 
 
	//set information 
	m_iWidth	= width; 
	m_iHeight	= height; 
 
	m_Viewer.left	= 0; 
	m_Viewer.top	= 0; 
	m_Viewer.right  = g_pEasyDraw->GetDeviceWidth(); 
	m_Viewer.bottom = g_pEasyDraw->GetDeviceHeight(); 
 
	m_MapRect.left	= 0; 
	m_MapRect.top	= 0; 
	m_MapRect.right = width * TILE_WIDTH - 1;					//注意要-1 
	m_MapRect.bottom= height * TILE_HEIGHT - 1; 
 
	m_CurMapName = m_NextMapName; 
	return true; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::FreeMap() 
{ 
	SafeDeleteArray( m_CellArray ); 
	SafeDeleteArray( m_TileArray ); 
 
	for ( int i = 0; i < m_TileSurfaceArray.GetLength(); ++i ) 
		g_pEasyDraw->DeleteSurface( m_TileSurfaceArray[i] ); 
 
	m_TileSurfaceArray.Clear(); 
	m_RenderQueue.Clear(); 
	m_BuildingPGArray.Clear(); 
	m_BuildingArray.Clear(); 
	m_MovingSpritePool.Clear(); 
	m_MagicSpritePool.Clear(); 
 
	m_iHeight = 0; 
	m_iWidth = 0; 
	m_CellPitch = 0; 
	m_CellNum = 0; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::Draw() 
{ 
	//1.处理魔法精灵 
	for ( m_MagicSpritePool.Begin(); m_MagicSpritePool.IsNotNull(); m_MagicSpritePool.MoveNext() ) 
	{ 
		CMagicSprite *sprite = *(m_MagicSpritePool.GetCur()); 
		if ( sprite->UpdateSprite() ) 
		{ 
			if ( sprite->IsVisible( m_Viewer ) ) 
				m_RenderQueue.Add( sprite ); 
		} 
		else 
			m_MagicSpritePool.FreeCur(); 
	} 
 
	//2.获取m_Viewer与m_MapRect的相交区域 
	RECT rc; 
	rc.left		= ( m_ViewerEx.left > m_MapRect.left ? m_ViewerEx.left : m_MapRect.left );  
	rc.right	= ( m_ViewerEx.right < m_MapRect.right ? m_ViewerEx.right : m_MapRect.right ); 
	rc.top		= ( m_ViewerEx.top > m_MapRect.top ? m_ViewerEx.top : m_MapRect.top ); 
	rc.bottom	= ( m_ViewerEx.bottom < m_MapRect.bottom ? m_ViewerEx.bottom : m_MapRect.bottom ); 
 
	int col_begin = rc.left / TILE_WIDTH; 
	int	row_begin = rc.top / TILE_HEIGHT; 
	int col_end	 = rc.right / TILE_WIDTH; 
	int row_end	 = rc.bottom / TILE_HEIGHT;	 
 
	POINT p_map = {theMouse.GetX(), theMouse.GetY()}; 
	ClientToMap( p_map ); 
 
	for ( int i = row_begin; i <= row_end; ++i ) 
	{ 
		for ( int j = col_begin; j <= col_end; ++j ) 
		{ 
			TILE &tile = m_TileArray[i * m_iWidth + j]; 
 
			POINT p; 
			p.x = tile.m_Rect.left; 
			p.y = tile.m_Rect.top; 
 
			MapToClient( p ); 
			tile.m_Surf->DrawAutoClip( p.x, p.y ); 
 
			//不可选取的精灵 
			for ( tile.m_SPool.Begin(); tile.m_SPool.IsNotNull(); tile.m_SPool.MoveNext() ) 
			{ 
				CBaseSprite *sprite = *(tile.m_SPool.GetCur()); 
 
				if ( sprite->UpdateSprite() ) 
				{ 
					if ( sprite->IsVisible( m_Viewer ) ) 
					{ 
						m_RenderQueue.Add( sprite ); 
					} 
				} 
				else 
					tile.m_SPool.FreeCur(); 
			} 
 
			//可选取的精灵 
			for ( tile.m_APool.Begin(); tile.m_APool.IsNotNull(); tile.m_APool.MoveNext() ) 
			{ 
				CBaseSprite *sprite = *(tile.m_APool.GetCur()); 
 
				if ( sprite->UpdateSprite() ) 
				{ 
					if ( sprite->IsVisible( m_Viewer ) ) 
					{ 
						m_RenderQueue.Add( sprite ); 
						if ( sprite->IsSelected( p_map.x, p_map.y ) ) 
						{ 
							m_SelectQueue.Add( sprite ); 
						} 
					} 
				} 
				else 
					tile.m_APool.FreeCur(); 
			} 
 
		 
		} 
	} 
	 
	if ( m_SelectQueue.IsEmpty() == false ) 
	{ 
		SortSprite(m_SelectQueue); 
		CBaseSprite *sprite = m_SelectQueue[m_SelectQueue.GetLength()-1]; 
		theGameManager.SetCurSelSprite( sprite ); 
	} 
	else 
	{ 
		theGameManager.SetCurSelSprite( NULL ); 
	} 
 
	//处理正在移动的精灵 
	for ( m_MovingSpritePool.Begin(); m_MovingSpritePool.IsNotNull(); m_MovingSpritePool.MoveNext() ) 
	{ 
		CBaseSprite *sprite = *(m_MovingSpritePool.GetCur()); 
		AddAliveSprite( sprite ); 
 
		if ( sprite->IsVisible( m_Viewer ) ) 
			m_RenderQueue.Add( sprite ); 
 
		m_MovingSpritePool.FreeCur(); 
	} 
 
	theHero.UpdateSprite(); 
	m_RenderQueue.Add( (CBaseSprite *)&theHero ); 
	m_NumRenderObj = m_RenderQueue.GetLength(); 
	SortSprite( m_RenderQueue ); 
 
#ifndef ALPHA_SHADOW 
	for ( i = 0; i < m_RenderQueue.GetLength(); ++i ) 
		m_RenderQueue[i]->DrawShadow(); 
#endif 
 
	for ( i = 0; i < m_RenderQueue.GetLength(); ++i ) 
		m_RenderQueue[i]->DrawSprite(); 
 
	m_RenderQueue.Clear(); 
	m_SelectQueue.Clear(); 
 
	int nx = g_pEasyDraw->GetDeviceWidth() - m_SurfInfo->GetWidth(); 
	m_SurfInfo->DrawSurface( nx, 0, 0 ); 
} 
 
 
////////////////////////////////////////////////////////////////////// 
//插入排序 
////////////////////////////////////////////////////////////////////// 
inline void CMap::SortSprite( CDynamicArray &array ) 
{ 
	CBaseSprite *bs; 
 
	for ( int i = 1; i < array.GetLength(); ++i ) 
	{ 
		bs = array[i]; 
 
		for ( int j = i - 1; j >= 0; --j ) 
		{ 
			if ( array[j]->GetPriority() > bs->GetPriority() ) 
			{ 
				Swap( array[j+1], array[j] ); 
			} 
			else 
				break; 
		} 
	} 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::SetViewer( int left, int top, int right, int bottom ) 
{ 
	m_Viewer.left	= left; 
	m_Viewer.top	= top; 
	m_Viewer.right	= right; 
	m_Viewer.bottom	= bottom; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
//此处有些BUG 
////////////////////////////////////////////////////////////////////// 
void CMap::MoveMap( int add_x, int add_y ) 
{ 
	if ( m_Viewer.left + add_x >= 0 && m_Viewer.right + add_x <= m_MapRect.right ) 
	{ 
		m_Viewer.left	+= add_x; 
		m_Viewer.right	+= add_x; 
		m_ViewerEx.left += add_x; 
		m_ViewerEx.right+= add_x; 
	} 
 
	if ( m_Viewer.top + add_y >= 0 && m_Viewer.bottom + add_y <= m_MapRect.bottom ) 
	{ 
		m_Viewer.top	+= add_y; 
		m_Viewer.bottom += add_y; 
		m_ViewerEx.top	+= add_y; 
		m_ViewerEx.bottom+=add_y; 
	} 
} 
 
////////////////////////////////////////////////////////////////////// 
//x,y是鼠标在窗口客户区的坐标 
////////////////////////////////////////////////////////////////////// 
/*void CMap::SelectSprite( int x_mouse, int y_mouse ) 
{ 
	POINT p_map = {x_mouse, y_mouse}; 
	ClientToMap( p_map ); 
 
	int row = p_map.y / TILE_HEIGHT; 
	int col = p_map.x / TILE_WIDTH; 
 
	int begin_row = ( row > 0 ? row-1 : 0 ); 
	int end_row = ( row < m_iHeight-1 ? row+1 : m_iHeight-1 ); 
	int begin_col = ( col > 0 ? col-1 : 0 ); 
	int end_col = ( col < m_iWidth-1 ? col+1 : m_iWidth-1 ); 
 
	m_RenderQueue.SetLength( 0 ); 
 
	for ( int i = begin_row; i <= end_row; ++i ) 
	{ 
		for ( int j = begin_col; j <= end_col; ++j ) 
		{ 
			TILE &tile = m_TileArray[i * m_iWidth + j]; 
 
			for ( tile.m_APool.Begin(); tile.m_APool.IsNotNull(); tile.m_APool.MoveNext() ) 
			{ 
				CBaseSprite *sprite = *(tile.m_APool.GetCur()); 
				if ( sprite->IsSelected( p_map.x, p_map.y ) ) 
					m_RenderQueue.Add( sprite ); 
			} 
		} 
	} 
 
	if ( m_RenderQueue.IsEmpty() == false ) 
	{ 
		SortSprite(m_RenderQueue); 
		CBaseSprite *sprite = m_RenderQueue[m_RenderQueue.GetLength()-1]; 
		//sprite->EnableSelected(); 
		theGameManager.SetCurSelSprite( sprite ); 
	} 
	else 
	{ 
		theGameManager.SetCurSelSprite( NULL ); 
	} 
}*/ 
 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::SetCell( int row, int col, BYTE data ) 
{ 
	if ( row >= 0 && row < m_iHeight * 4 ) 
	{ 
		if ( col >= 0 && col < m_CellPitch ) 
		{ 
			m_CellArray[row * m_CellPitch + col ] = data; 
			return true; 
		} 
	} 
 
	return false; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::HoldCell( int row, int col ) 
{ 
	int index = row * m_CellPitch + col; 
	debug_assert( index >= 0 && index < m_iHeight * m_iWidth * 16 ); 
 
	m_CellArray[index] |= MONSTER_MASK; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::HoldCell( int row, int col, BYTE mask ) 
{ 
	int index = row * m_CellPitch + col; 
	debug_assert( index >= 0 && index < m_iHeight * m_iWidth * 16 ); 
 
	m_CellArray[index] |= mask; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::NoHoldCell( int row, int col ) 
{ 
	int index = row * m_CellPitch + col; 
	debug_assert( index >= 0 && index < m_iHeight * m_iWidth * 16 ); 
 
	m_CellArray[index] &= ~MONSTER_MASK; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::NoHoldCell( int row, int col, BYTE mask ) 
{ 
	int index = row * m_CellPitch + col; 
	assert( index >= 0 && index < m_iHeight * m_iWidth * 16 ); 
 
	m_CellArray[index] &= ~mask; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::IsCellHold( int row, int col ) 
{ 
	if ( row >= 0 && row < m_iHeight * 4 ) 
	{ 
		if ( col >= 0 && col < m_CellPitch ) 
		{ 
			if (m_CellArray[row * m_CellPitch + col ] & HOLD_MASK ) 
				return true; 
			else 
				return false; 
		} 
	} 
 
	return true; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::IsCellHold( int row, int col, BYTE mask ) 
{ 
	if ( row >= 0 && row < m_iHeight * 4 ) 
	{ 
		if ( col >= 0 && col < m_CellPitch ) 
		{ 
			if (m_CellArray[row * m_CellPitch + col ] & mask) return true; 
			else return false; 
		} 
	} 
 
	return true; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::IsCellNull( int row, int col ) 
{ 
	if ( row >= 0 && row < m_iHeight * 4 ) 
	{ 
		if ( col >= 0 && col < m_CellPitch ) 
		{ 
			return false; 
		} 
	} 
 
	return true; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
//row,col单位为TILE 
////////////////////////////////////////////////////////////////////// 
void CMap::SetTileSurface( int row, int col, PSURFACE surf ) 
{ 
	if ( col >= 0 && col < m_iWidth ) 
	{ 
		if ( row >= 0 && row < m_iHeight ) 
			m_TileArray[row * m_iWidth + col].m_Surf = surf; 
	} 
} 
 
 
////////////////////////////////////////////////////////////////////// 
//x,y是地图坐标系的坐标,单位像素 
////////////////////////////////////////////////////////////////////// 
PTILE CMap::GetTile( int x, int y ) 
{ 
	if ( x >= 0 && x < m_iWidth * TILE_WIDTH ) 
	{ 
		if ( y >= 0 && y < m_iHeight * TILE_HEIGHT ) 
			return &m_TileArray[(y/TILE_HEIGHT) * m_iWidth + (x/TILE_WIDTH)]; 
	} 
 
	return NULL; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
//地图文件格式:文件头+TILE页面文件名+建筑EPG文件名数组+TILE索引数组 
//+建筑物数据+CELL数组+NPC信息+怪物信息+DLG信息+物品信息 
////////////////////////////////////////////////////////////////////// 
bool CMap::LoadMap( const char *filename ) 
{ 
	//free map, then init later 
	FreeMap(); 
	 
	//open file 
	if ( filename == NULL ) 
		filename = m_NextMapName.c_str(); 
 
	FILE *fp = fopen( filename, "rb" );				//load from file, no epk 
	if ( fp == NULL ) 
		assert(false); 
 
	//read header 
	MAPFILEHEADER mfh; 
	fread( &mfh, sizeof(mfh), 1, fp ); 
	if ( mfh.mapFileType != MAPFILE ) 
	{ 
		fclose(fp); 
		return false; 
	} 
 
	m_MapName = mfh.mapName; 
	m_SurfInfo->ClearSurface( 0, 0 ); 
	m_SurfInfo->WriteTextCenter( mfh.mapName, 0xffffff ); 
 
	//create map 
	bool b = CreateMap( mfh.mapWidth, mfh.mapHeight ); 
	debug_assert(b); 
 
 
	//open tile epk; 
	CEPKFile epk; 
	if ( epk.Open( "..\\data\\tile.epk", EPK_IN ) == false ) 
	{ 
		fclose(fp); 
		return false; 
	} 
	//load tile surface 
	for ( int i = 0; i < mfh.mapNumTileSurface; ++i ) 
	{ 
		char sz[32]; 
		fread( sz, 32, 1, fp );			//read tile name 
 
		BYTE *buf = epk.Read( sz ); 
 
		if ( buf == NULL ) 
		{ 
			epk.Close(); 
			fclose(fp); 
			Free(); 
			return false; 
		} 
 
		PSURFACE surf = g_pEasyDraw->NewSurface(); 
		debug_assert( surf != NULL ); 
 
		if ( surf->CreateBmpSurfaceFromMemory( buf, false ) == false ) 
		{ 
			epk.Close(); 
			fclose(fp); 
			Free(); 
			return false; 
		} 
		 
		m_TileSurfaceArray.Add( surf ); 
	} 
 
	epk.Close(); 
 
 
	//load building epg 
	if ( epk.Open( "..\\data\\building.epk", EPK_IN ) == false ) 
	{ 
		fclose(fp); 
		assert(false); 
		return false; 
	} 
 
	CDynamicArray	epg_array; 
	for ( i = 0; i < mfh.mapNumBuildingEPG; ++i ) 
	{ 
		char sz[32]; 
		fread( sz, 32, 1, fp );			//read file name 
		BYTE *buf = epk.Read( sz );		//read epg 
 
		if ( buf == NULL ) 
		{ 
			epk.Close(); 
			fclose(fp); 
			Free(); 
			return false; 
		} 
 
		CPictureGroup *pPG = m_BuildingPGArray.CreateOneElement(); 
		CPictureGroup *pSPG= m_BuildingPGArray.CreateOneElement(); 
 
		bool b = pPG->LoadEPG( (char *)buf, false, pSPG, 0, 0 ); 
		debug_assert(b); 
 
		if ( pSPG->IsEmpty() ) 
		{ 
			m_BuildingPGArray.DeleteLastElement();			//if has no shadow, delete it 
			pSPG = NULL; 
		} 
 
		epg_array.Add( BUILDING_EPG( pPG, pSPG ) ); 
	} 
	epk.Close(); 
 
	//load tile index data 
	for ( i = 0; i < mfh.mapHeight; ++i ) 
	{ 
		for ( int j = 0; j < mfh.mapWidth; ++j ) 
		{ 
			int index; 
			fread( &index, 4, 1, fp ); 
 
			m_TileArray[i * mfh.mapWidth + j].m_Surf = m_TileSurfaceArray[index]; 
		} 
	} 
 
	//load building data 
	m_BuildingArray.SetSize( mfh.mapNumBuilding ); 
	for ( i = 0; i < mfh.mapNumBuilding; ++i ) 
	{ 
		BUILDING_DATA building_data; 
		fread( &building_data, sizeof(building_data), 1, fp ); 
 
		BUILDING_EPG &be = epg_array[building_data.IndexOfBuildingEpg]; 
		CPictureGroup *pPG = be.pPG; 
		CPictureGroup *pSPG = be.pSPG; 
 
		CBuilding *building = &m_BuildingArray[i]; 
 
		bool b = building->Init( pPG, pSPG, building_data.BasePoint ); 
		debug_assert(b); 
 
		AddStaticSprite( building ); 
	} 
 
	//load cell data 
	fread( m_CellArray, mfh.mapHeight * mfh.mapWidth * 16, 1, fp ); 
 
	//load npc and monster info 
	theSpriteFactory.OnLoadMap( fp, mfh.mapNumNpcSI, mfh.mapNumMonsterSI ); 
 
	//load dlg data 
	for ( i = 0; i < mfh.NumNpcDlg; ++i ) 
	{ 
		char sz[32]; 
		fread( sz, 32, 1, fp ); 
		theNpcDlgMgr.OnLoadMap( sz ); 
	} 
 
	//load item data 
	theItemFactory.OnLoadMap( fp ); 
 
	fclose(fp); 
 
	//set hero position 
	POINT p = {mfh.HeroPoint[m_IndexHeroPoint].x, mfh.HeroPoint[m_IndexHeroPoint].y}; 
	theHero.SetBasePoint( p.x, p.y ); 
	theHero.CalcPriority(); 
	HoldCell( p.y / CELL_HEIGHT, p.x / CELL_WIDTH ); 
	CalcViewerRect( p.x, p.y ); 
 
	//play mp3: 
	if ( strlen( mfh.mapMusic ) > 0 ) 
		g_pEasyAudio->PlayMP3( mfh.mapMusic ); 
	return true; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::AddStaticSprite( CBaseSprite *sprite ) 
{ 
	const POINT base = sprite->GetBasePoint(); 
	PTILE tile = GetTile( base.x, base.y ); 
	if ( tile == NULL ) 
	{ 
		debug_assert(false); 
		return false; 
	} 
 
	if ( tile->m_SPool.Add( sprite ) == NULL ) 
	{ 
		debug_assert(false); 
		return false; 
	} 
 
	return true; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::AddMovingSprite( CBaseSprite *sprite ) 
{ 
	if ( m_MovingSpritePool.Add( sprite ) == NULL ) 
	{ 
		debug_assert(false); 
		return false; 
	} 
	else  
		return true; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::AddAliveSprite( CBaseSprite *sprite ) 
{ 
	const POINT base = sprite->GetBasePoint(); 
	PTILE tile = GetTile( base.x, base.y ); 
	if ( tile == NULL ) 
	{ 
		debug_assert(false); 
		return false; 
	} 
 
	if ( tile->m_APool.Add( sprite ) == NULL ) 
	{ 
		debug_assert(false); 
		return false; 
	} 
 
	HoldCell( base.y / CELL_HEIGHT, base.x / CELL_WIDTH ); 
	return true; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
bool CMap::AddItem( CBaseSprite *sprite ) 
{ 
	const POINT base = sprite->GetBasePoint(); 
	PTILE tile = GetTile( base.x, base.y ); 
	if ( tile == NULL ) 
		return false; 
 
	if ( tile->m_APool.Add( sprite ) == NULL ) 
		return false; 
 
	return true; 
} 
 
////////////////////////////////////////////////////////////////////// 
//根据英雄起初位置计算可视RECT 
////////////////////////////////////////////////////////////////////// 
void CMap::CalcViewerRect( int x, int y ) 
{ 
	x += CELL_WIDTH / 2; 
	y += CELL_HEIGHT/ 2; 
 
	int w = g_pEasyDraw->GetDeviceWidth() / 2; 
	int h = g_pEasyDraw->GetDeviceHeight() / 2; 
 
	m_Viewer.left = x - w; 
	m_Viewer.top = y - h; 
	m_Viewer.right = x + w; 
	m_Viewer.bottom= y + h; 
 
	int add_x = 0; 
	int add_y = 0; 
 
	if ( m_Viewer.left < 0 ) 
		add_x = 0 - m_Viewer.left; 
	else if ( m_Viewer.right > m_iWidth * TILE_WIDTH ) 
		add_x = m_iWidth * TILE_WIDTH - m_Viewer.right; 
 
	if ( m_Viewer.top < 0 ) 
		add_y = 0 - m_Viewer.top; 
	else if ( m_Viewer.bottom > m_iHeight * TILE_HEIGHT ) 
		add_y = m_iHeight * TILE_HEIGHT - m_Viewer.bottom; 
 
	m_Viewer.left += add_x; 
	m_Viewer.right+= add_x; 
	m_Viewer.top  += add_y; 
	m_Viewer.bottom+=add_y; 
 
	m_ViewerEx.left = m_Viewer.left - TILE_WIDTH; 
	m_ViewerEx.right= m_Viewer.right+ TILE_WIDTH; 
	m_ViewerEx.top	= m_Viewer.top - TILE_HEIGHT; 
	m_ViewerEx.bottom = m_Viewer.bottom + TILE_HEIGHT * 2; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
//根据viewer的矩形, 计算所覆盖的TILE 
////////////////////////////////////////////////////////////////////// 
void CMap::GetVisibleTile( const RECT &viewer, RECT &rcOut ) 
{ 
	rcOut.left	= ( viewer.left > m_MapRect.left ? viewer.left : m_MapRect.left );  
	rcOut.right	= ( viewer.right < m_MapRect.right ? viewer.right : m_MapRect.right ); 
	rcOut.top	= ( viewer.top > m_MapRect.top ? viewer.top : m_MapRect.top ); 
	rcOut.bottom= ( viewer.bottom < m_MapRect.bottom ? viewer.bottom : m_MapRect.bottom ); 
 
	rcOut.left /= TILE_WIDTH; 
	rcOut.top /= TILE_HEIGHT; 
	rcOut.right /= TILE_WIDTH; 
	rcOut.bottom /= TILE_HEIGHT;	 
} 
 
////////////////////////////////////////////////////////////////////// 
// 
////////////////////////////////////////////////////////////////////// 
void CMap::SetNextMap( char *name ) 
{ 
	m_NextMapName = name; 
}