📄 cbmini.cpp
字号:
/////////////////
// CBMini.cpp : 《赤壁》缩略图
// v0010 : Jan.31.1997
// v0011 : May.5.1997, add blinking on the map, add size of each unit
// written by : Liu Gang
// Compiler : Visual C++ 4.2 & DirectX
// Library : DDraw.lib
// Copyright : WayAhead Software Co.Ltd. 1996-1997
/////////////////
// 此文件包含所有对缩略图的操作
#include "stdafx.h"
#include "Assert.h"
#include "DDCompo.h"
#include "CBMini.h"
#include "CBMap.h"
#include "CBShadow.h"
/////////////////
// globals
// 地形图素数据数组
//extern WORD MAP_wGroundData[MAP_DATA_THICK][MAP_DATA_WIDTH][MAP_DATA_HEIGHT];
// 区域数据数组
//extern WORD MAP_wRegionData[MAP_DATA_WIDTH][MAP_DATA_HEIGHT];
// 战场窗口
extern RECT DRAW_rcScreen; // defined in CBDraw.cpp
// Location Number
extern int MAP_nLocationNum[4]; // defined in CBMap.cpp
/////////////////
/////////////////
// internal variables
struct MAP_MINI_LIB_STRUCT MINI_Lib; // 缩略图结构
// 缩略图的显示面
class CDDSurface MINI_sMap; // surface to display minimap
// 保存背景地图的缓冲区
BYTE *MINI_pBuffer; // buffer for storing ground map
// 显示面的大小
int MINI_nWidth;
int MINI_nHeight;
int MINI_nBuffSize;
// 闪烁用数组
#define MINI_BLINK_MAX 10
POINT MINI_ptBlink[MINI_BLINK_MAX];
void MINI_DrawBlink( int nCol, int nRow, int nColor ); // 显示闪烁效果,在MINI_Update()
/////////////////
/////////////////
// create mini map surface and buffer
// must read med file first
// 必须在打开战场图后使用,GAME_ReadMedfile()
// return : TRUE if succeeded
BOOL MINI_Load()
{
// test if has loaded before
// test if has loaded before
if( MINI_Lib.nType != -1 )
{
ErrorMessage( hwndGame, MINI_ERROR_ID+0, "Mini map has been created!" );
OutputDebugString( "MINI_Load Error(0): Mini map has been created!\n" );
return FALSE;
}
// set mini map type
switch( MAP_Lib.szNum.cx )
{
case 90:
MINI_Lib.nType = 0;
break;
case 105:
MINI_Lib.nType = 1;
break;
case 120:
MINI_Lib.nType = 2;
break;
}
// if do not read mini map data file yet
if( MINI_Lib.nType == -1 )
{
ErrorMessage( hwndGame, MINI_ERROR_ID+1, "Load Minimap before load battle field!" );
OutputDebugString( "MINI_Load Error(1): Load Minimap before load battle field!\n" );
return FALSE;
}
// create minimap surface
// no color key, in system memory
MINI_nWidth = MINI_Lib.rcMap[MINI_Lib.nType].right -
MINI_Lib.rcMap[MINI_Lib.nType].left;
MINI_nHeight = MINI_Lib.rcMap[MINI_Lib.nType].bottom -
MINI_Lib.rcMap[MINI_Lib.nType].top;
if( !MINI_sMap.Create( MINI_nWidth, MINI_nHeight, FALSE, FALSE ) )
{
ErrorMessage( hwndGame, MINI_ERROR_ID+2, "Cannot create minimap surface!" );
OutputDebugString( "MINI_Load Error(2): Cannot create minimap surface!\n" );
return FALSE;
}
MINI_sMap.Erase( 0 );
// create buffer
MINI_nBuffSize = MINI_nWidth*MINI_nHeight;
MINI_pBuffer = (BYTE*)malloc( MINI_nBuffSize );
if( !MINI_pBuffer )
{
ErrorMessage( hwndGame, MINI_ERROR_ID+3, "Cannot create minimap buffer!" );
OutputDebugString( "MINI_Load Error(3): Cannot create minimap buffer!\n" );
return FALSE;
}
memset( MINI_pBuffer, 0, MINI_nBuffSize );
// initialize blink point array
memset( MINI_ptBlink, 0, sizeof( POINT )*MINI_BLINK_MAX );
return TRUE;
}
// release minimap surface and buffer
void MINI_Release()
{
if( MINI_Lib.nType == -1 )
{
ErrorMessage( hwndGame, MINI_ERROR_ID+10, "Try to release minimap surface before load it!" );
OutputDebugString( "MINI_Load Error(10): Try to release minimap surface before load it!\n" );
return ;
}
MINI_sMap.Release();
//GlobalFree( MINI_pBuffer );
free( MINI_pBuffer );
MINI_pBuffer = NULL;
DD_EraseBackScreen( 1, &MINI_Lib.rcMap[2] );
DDC_UpdateScreen( &MINI_Lib.rcMap[2] );
MINI_Lib.nType = -1;
}
POINT ptLocation[16]={
{0,0},{1,0},{0,-1},{1,-1},
{-1,0},{-1,-1},{-1,-2},{0,-2},
{1,-2},{-2,0},{-2,-1},{-2,-2},
{-2,-3},{-1,-3},{0,-3},{1,-3}};
// set unit data to buffer
void MINI_SetUnitData( int nCol, int nRow, int nType, int nLocationSize )
{
int nBase = 15;
int nX, nY;
int nOffset;
BYTE *pBuffer=NULL;
if( SHADOW_IfBlanked( nCol, nRow ) != 0 )
return; // 被任何阴影遮挡则不画
for( int x=0; x<MAP_nLocationNum[nLocationSize]; x++ )
{
nX = nCol+ptLocation[x].x, nY = nRow+ptLocation[x].y;
nOffset = MINI_nWidth*(nY>>2)+nX;
if( nOffset < 0 || nOffset > MINI_nBuffSize )
continue; // 出界
pBuffer = MINI_pBuffer+nOffset;
*pBuffer=(BYTE)MINI_Lib.nColorTable[nBase+nType];
}
}
// set ground data to buffer
void MINI_SetGroundData( int nCol, int nRow, int nLocationSize )
{
int nX, nY;
int nOffset;
BYTE *pBuffer=NULL;
if( SHADOW_IfBlanked( nCol, nRow ) == MAP_SHADOW_NONE )
return; // 被实心阴影遮挡则不画
for( int x=0; x<MAP_nLocationNum[nLocationSize]; x++ )
{
nX = nCol+ptLocation[x].x, nY = nRow+ptLocation[x].y;
for( int i=MAP_DATA_THICK-1; i>=0; i-- )
{
WORD codeG = MAP_GetGroundData( i, nX, nY );
if( codeG != MAP_DATA_NONE )
{
nOffset = MINI_nWidth*(nY>>2)+nX;
if( nOffset < 0 || nOffset > MINI_nBuffSize )
continue; // 出界
pBuffer = MINI_pBuffer+nOffset;
struct MAP_GROUND_CODE_STRUCT stctG;
MAP_GroundDeCode( codeG, &stctG );
if( stctG.nAttr == 0 || stctG.nAttr == 1 )
{
*pBuffer=(BYTE)MINI_Lib.nColorTable[13+stctG.nAttr];
}
else if( stctG.nFile == 3 && stctG.nCol == 13 )
{
*pBuffer=(BYTE)MINI_Lib.nColorTable[0]; // special condition, in water range but it is land
}
else
{
*pBuffer=(BYTE)MINI_Lib.nColorTable[stctG.nFile];
}
break;
}
}
}
}
// draw all the items on the battlefield to buffer
// bDraw : TRUE if Draw data from ground data to buffer
// else erase buffer with black
void MINI_DrawAll( BOOL bDraw /*= TRUE */)
{
// 必须在给MINI_pBuffer申请内存后使用
#ifdef _DEBUG
if( !MINI_pBuffer )
{
ErrorMessage( hwndGame, MINI_ERROR_ID+10, "Try to read map data before create buffer surface!" );
return;
}
#endif // _DEBUG
int i,j,k;
if( bDraw )
{ // draw
memset( MINI_pBuffer, 0, MINI_nBuffSize );
// draw ground
int nHeight = MINI_nHeight<<2;
BYTE *pBuffer = (BYTE*)MINI_pBuffer;
for( j=0; j<nHeight; j+=4 )
for( k=0; k<MINI_nWidth; k++ )
{
int ret = SHADOW_IfBlanked( k, j );
if( ret != MAP_SHADOW_NONE )//|| (ret==1 && (k&1)==0 && (j&7)==0) )
{
for( i=MAP_DATA_THICK-1; i>=0; i-- )
{
WORD codeG = MAP_GetGroundData( i, k, j );
if( codeG != MAP_DATA_NONE )
{ // 没有被实心阴影所遮挡
struct MAP_GROUND_CODE_STRUCT stctG;
MAP_GroundDeCode( codeG, &stctG );
if( stctG.nAttr == 0 || stctG.nAttr == 1 )
{
*pBuffer=(BYTE)MINI_Lib.nColorTable[13+stctG.nAttr];
}
else if( stctG.nFile == 3 && stctG.nCol == 13 )
{
*pBuffer=(BYTE)MINI_Lib.nColorTable[0]; // special condition, in water range but it is land
}
else
{
*pBuffer=(BYTE)MINI_Lib.nColorTable[stctG.nFile];
}
break;
}
}
}
pBuffer++;
}
// draw unit
for( i=0; i<GAME_PLAYER_MAX; i++ )
{
int nCounter = 0;
for( j=0; j<PLAYER_UNIT_MAX; j++ )
{
struct UNIT_STRUCT *pUnit = &GAME.Players[i].Unit[j];
if( pUnit->nType != MAP_UNIT_TYPE_NONE )
{
MINI_SetUnitData( pUnit->Draw.nX, pUnit->Draw.nY,
pUnit->Draw.nPlayer, pUnit->Draw.nLocationSize );
}
}
}
}
else // erase
{
int nHeight = MINI_nHeight<<2;
BYTE *pBuffer = (BYTE*)MINI_pBuffer;
for( int j=0; j<nHeight; j+=4 )
for( int k=0; k<MINI_nWidth; k++ )
{
WORD codeR = MAP_GetRegionData( k, j );
struct MAP_REGION_CODE_STRUCT stctR;
MAP_RegionDeCode( codeR, &stctR );
if( stctR.nShadow == MAP_SHADOW_NONE )
*pBuffer=0;
pBuffer++;
}
}
} // end of MINI_DrawAll()
// July 23, 1997
// draw from mini surface to back buffer , and to front buffer
// bFront : 1 for draw to front buffer,
// 2 for only update to front buffer
// 0 for do not draw to front buffer
// bClearBlink : TRUE if should erase blink point array right after drawing blink
void MINI_Update( BOOL bFront/* = TRUE*/, BOOL bClearBlink/* = TRUE*/ )
{
// draw to front
// July 23, 1997
if( bFront == 2 )
{
RECT rcScreen;
SetRect( &rcScreen,
DRAW_rcScreen.left, DRAW_rcScreen.top>>2,
DRAW_rcScreen.right, DRAW_rcScreen.bottom>>2 );
OffsetRect( &rcScreen,
MINI_Lib.rcMap[MINI_Lib.nType].left,
MINI_Lib.rcMap[MINI_Lib.nType].top );
DDC_FrameRect( &rcScreen, RGB(240,240,240) );
DDC_UpdateScreen( &MINI_Lib.rcMap[MINI_Lib.nType] );
return;
}
// copy buffer
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof( ddsd );
if( MINI_sMap.GetSurface()->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ) == DD_OK )
{
memcpy( ddsd.lpSurface, MINI_pBuffer, ddsd.dwWidth*ddsd.dwHeight );
MINI_sMap.GetSurface()->Unlock( NULL );
}
// draw screen rectangle
if( bFront == 1 )
{
RECT rcScreen;
SetRect( &rcScreen,
DRAW_rcScreen.left, DRAW_rcScreen.top>>2,
DRAW_rcScreen.right, DRAW_rcScreen.bottom>>2 );
DDC_FrameRect( MINI_sMap.GetSurface(), &rcScreen, RGB(240,240,240) );
}
// draw blinking crosses
static int nC=0;
int arColor[2]={83, 95};
nC = (nC+1)%2;
for( int i=0; i<MINI_BLINK_MAX; i++ )
{
if( MINI_ptBlink[i].x != 0 && MINI_ptBlink[i].y != 0 )
{
MINI_DrawBlink( MINI_ptBlink[i].x, MINI_ptBlink[i].y, arColor[nC] );
}
}
if( bClearBlink )
{
// initialize blink point array
memset( MINI_ptBlink, 0, sizeof( POINT )*MINI_BLINK_MAX );
}
// draw to back
POINT ptDest;
RECT rcSrc;
ptDest.x = MINI_Lib.rcMap[MINI_Lib.nType].left;
ptDest.y = MINI_Lib.rcMap[MINI_Lib.nType].top;
rcSrc.left = rcSrc.top = 0;
rcSrc.right = MINI_Lib.rcMap[MINI_Lib.nType].right -
MINI_Lib.rcMap[MINI_Lib.nType].left;
rcSrc.bottom = MINI_Lib.rcMap[MINI_Lib.nType].bottom -
MINI_Lib.rcMap[MINI_Lib.nType].top;
MINI_sMap.BltToBack( ptDest, &rcSrc );
// draw to front
if( bFront == 1 )
DDC_UpdateScreen( &MINI_Lib.rcMap[MINI_Lib.nType] );
}
// if there is a war draw blinking cross on the map
void MINI_SetBlink( int nCol, int nRow )
{
nRow = nRow>>2;
RECT rect;
int nRange=4;
rect.left = nCol-nRange;
rect.top = nRow-nRange;
rect.right = nCol+nRange;
rect.bottom = nRow+nRange;
for( int i=0; i<MINI_BLINK_MAX; i++ )
{
// if( MINI_ptBlink[i].x != nCol
// || MINI_ptBlink[i].y != nRow )
// if( PtInRect( MINI_ptBlink[i], &rect ) )
if( MINI_ptBlink[i].x >rect.right
|| MINI_ptBlink[i].x<=rect.left
|| MINI_ptBlink[i].y>rect.top
|| MINI_ptBlink[i].y<=rect.bottom )
{
MINI_ptBlink[i].x = nCol;
MINI_ptBlink[i].y = nRow;
break;
}
}
}
void MINI_DrawBlink( int nCol, int nRow, int nColor )
{
//int nColor = 88;
// draw to surface directly
DDSURFACEDESC ddsd;
BYTE *pBuffer = NULL;
int nOff;
POINT ptCross[9]={{-2,-2,},{2,-2},{-1,-1},{1,-1},{0,0},{-1,1},{1,1},{-2,2},{2,2}};
ddsd.dwSize = sizeof( ddsd );
if( MINI_sMap.GetSurface()->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ) == DD_OK )
{
for( int i=0; i<9; i++ )
{
pBuffer = (BYTE*)ddsd.lpSurface;
nOff = ddsd.lPitch*(nRow+ptCross[i].y)+nCol+ptCross[i].x;
if( nOff<0 || nOff>=int(ddsd.lPitch*ddsd.dwHeight) )
continue;
pBuffer += nOff;
*pBuffer = nColor;
}
MINI_sMap.GetSurface()->Unlock( NULL );
}
}
/////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -