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;
}