📄 cbdraw.cpp
字号:
/////////////
// CBDraw.cpp : v0032
// Written by : Liu Gang
// Compiler : Microsoft Visual C++ 4.0 & DirectX
// Library : DDraw.Lib
// Copyright (C) : 1996 WayAhead Corporation
// v0010 : Sep.26.1996
// v0011 : Nov.16.1996
// v0020 : Dec.12.1996, changed the display method to MMX
// v0021 : Jan.22.1997, changed drawing border method
// v0030 : Mar.7.1997, Great changes since optimze display core functions
// Optimize display functions again, this time, compressed the file
// to one third, and the speed is faster 2-3 frames/second.
// Optimzed the border drawing functions too.
// v0031 : Mar.12.1997, add new MMX features in code
// v0032 : Mar.29.1997, change drawing method of special items
/////////////
// implementation file
// display core codes
#include "stdafx.h" // compatible with MFC
#include "Assert.h"
#include "DDCompo.h" // Direct Draw objects and components
#include <stdio.h>
#include "CBDraw.h"
#include "CBMap.h" // game map data
#include "CBGame.h" // game data
#include "puthz.h" // draw chinese charactor
#include "CBMouse.h" // mouse hit test
#include "CBEyes.h" // EYE_ifOutOfRange()
/////////////////////
/////////////////////
// subs
#include "CBShadow.h"
#include "CBMini.h"
#include "CBBuild.h"
#include "CBOther.h"
/////////////////////
//---------------LHJ
#include "interfac.h"
//---------------
//---------------LWC
#ifdef _MAP_COMPRESS_
#include "L_image.h"
#include "L_Allbmp.h"
// image compression library
class CPicture_image DRAW_ImageLib;
#endif
//---------------LWC
//---------------TY
//君主AI初始化函数。
//#include "Temperor.h"
//---------------TY
/////////////////////
// assembler
extern "C"{
// for debug only, get cycles of CPU spent
// defined in file cycount.asm
void reset_time_event_info(int);
void start_time_event(int,int);
void end_time_event(int);
int get_time_event_info(int);
}
/////////////////////
/////////////////////
// globals, defines, macros
/////////////////////
extern char strCopyright[65];
class CDDText tCopyright;
class CDDText tGold, tFood, tWood, tIron;
void UpdateGFWI(); // 显示钱粮木铁,测试用
BOOL GFWI_bUpdate= TRUE; // 是否显示钱粮木铁;
void DrawHZ( class CDDSurface * pSurface );
/////////////////////
// user defined surfaces
BOOL DRAW_bLoadMaps = FALSE;
/////////////////////
/////////////////////
extern CDDCursor MAIN_Cursors[4]; // defined in CBMain.cpp
/////////////////////
/////////////////////
// ground maps
class CDDSurface DRAW_sGroundMap[MAP_GROUND_LIB_NUM];
/////////////////////
/////////////////////
// other maps
class CDDSurface DRAW_sOtherMap[MAP_OTHER_NUM];
/////////////////////
/////////////////////
// declared in CBMap.cpp
extern int MAP_nLocationNum[5];
extern POINT MAP_ptLocation[2][MAP_LOCATION_MAX];
POINT ptCovering[2][11]={
{{-2,0},{-1,0},{0,0},{1,0},{2,0},
{-3,1},{-2,1},{-1,1},{0,1},{1,1},{2,1},},
{{-2,0},{-1,0},{0,0},{1,0},{2,0},
{-2,1},{-1,1},{0,1},{1,1},{2,1},{3,1},},
};
/////////////////////
/////////////////////
// to move screen
BOOL DRAW_bMoveScreenEx = FALSE;
// client size in grid
// how much girds the client can fit
//RECT DRAW_rcScreen={0,0,11,50};
// 战场显示区域大小和在整个战场的相对位置(格子)
RECT DRAW_rcScreen={0,0,14,51};
// 战场显示区域左上角在整个战场的相对坐标(点)
POINT DRAW_ptScreenOffset;
// client size in pixel
RECT DRAW_rcClient={24,48,483,456};
// 部队运动的范围(行列)
RECT DRAW_rcMove={0,0,0,0};
// moving directions
int DD[8][2]={{-1,-2},{0,-2},{1,-2},{1,0},
{1,2},{0,2},{-1,2},{-1,0}};
// 将计算好位置的屏幕重新画一遍
// draw moving screen, it should be much faster than DRAW_UpdateScreen()
// ptOff : 新位置与旧位置的偏移量
void DRAW_DrawMoveScreen( POINT ptOff );
/////////////////////
/////////////////////
// bkground surface
// 用来长久保存地形图素的面,与战场区域一样大
class CDDSurface DRAW_sBkGround;
// 拷贝游戏背景面到地形背景面
// prcCut : 剪裁的范围,如果为NULL,则拷贝整个战场的区域
void DRAW_DrawBack2BkGround( CONST RECT *prcCut = NULL );
// 拷贝地形背景面到游戏背景面
// prcCut : 剪裁的范围,如果为NULL,则拷贝整个战场的区域
void DRAW_DrawBkGround2Back( CONST RECT *prcCut = NULL );
/////////////////////
/////////////////////
// MMX temp surface
// 暂时存放单元贴图的面,必须大于等于最大的单元的大小
#define DRAW_MMX_WIDTH 144
#define DRAW_MMX_HEIGHT 120
class CDDSurface DRAW_sMMX;
extern BOOL MAIN_bMMX; // 使用MMX技术的开关
/////////////////////
/////////////////////
// cover method
// 从数据文件中读取单元遮挡的数据存到这里
struct DRAW_COVER_STRUCT DRAW_CoverLib;
/////////////////////
// for hit test only
//7 8
// 5 6
// 3 4
// 1 2
// 0
// 能够覆盖某点的所有点的相对坐标
// 第一维是奇偶性
POINT DRAW_ptCovering[2][9]=
{ {{0,2},{-1,1},{0,1},
{-1,0},{1,0},{-2,-1},
{1,-1},{-2,-2},{2,-2}},
{{0,2},{0,1},{1,1},
{-1,0},{1,0},{-1,-1},
{2,-1},{-2,-2},{2,-2}}
};
/////////////////////
/////////////////////
// 被选中为目的地的单元,要闪烁显示它的边界
#define DRAW_BLINK_DELAY1 10
#define DRAW_BLINK_DELAY2 20
#define DRAW_BLINK_COUNT 3
int DRAW_BLINK_nCounter = 0;
int DRAW_BLINK_nDelay = 0;
int DRAW_BLINK_bDraw = TRUE;
WORD DRAW_BLINK_nID = MAP_DATA_NONE;
int DRAW_BLINK_nSave = 0;
/////////////////////
/////////////////////
// local functions
// 显示模块
/////////////////////
// draw one ground item
// 显示地形一个图素
// prcCut : 只更新此矩形区内的图像
// k,i,j : 图素的层号,行号,列号
// bFront : 是否直接更新到显示屏幕
void DRAW_DrawSingleG( CONST RECT *prcCut, int k, int i, int j, BOOL bFront );
// 显示被某单元遮挡的所有地形,实际上是重新画该矩形区域内的地形
// 从背景面上拷贝出一块区域贴图
// darw other things
// prcCut : 只更新此矩形区内的图像
// pstctCF : 单元图素显示帧结构
inline void DRAW_DrawUnitCovered( CONST RECT *prcCut, const struct CTRL_FRAME_STRUCT *pstctCF );
// 显示遮挡某单元的所有单元
// prcCut : 只更新此矩形区内的图像
// pstctCF : 单元图素显示帧结构
inline void DRAW_DrawUnitCovering( CONST RECT *prcCut, const struct CTRL_FRAME_STRUCT *pstctCF );
// 显示某单元
// prcCut : 只更新此矩形区内的图像
// pstctCF : 单元图素显示帧结构
// BOOL : TRUE for has drown
BOOL DRAW_DrawUnitSingle( CONST RECT *prcCut, const struct CTRL_FRAME_STRUCT *pstctCF );
// 显示一个单元,包含了更新其周围的单元的操作
// draw one unit item
// prcCut : 只更新此矩形区内的图像
// i,j : 图素的行号,列号
// bFront : 是否直接更新到显示屏幕
void DRAW_DrawSingleU( CONST RECT *prcCut, int i, int j, BOOL bFront );
// 显示一个特殊图素,树木,麦田,陷阱等
// draw one special item
// prcCut : 只更新此矩形区内的图像
// i,j : 图素的行号,列号
// bFront : 是否直接更新到显示屏幕
// Attr : 特殊图素的属性,非0时有效
// k : 特殊图素的层号,nAttr非0时有效
inline void DRAW_DrawSingleS( CONST RECT *prcCut, int i, int j, BOOL bFront, int nAttr, int k );
// 显示战场区域内的所有地形图素
// draw ground items
// rcCut : 只更新此矩形区内的图像
// k : 地形图素的层号
// bFront : 是否直接更新到显示屏幕
void DRAW_DrawGround( RECT rcCut, int k, BOOL bFront );
// 显示战场区域内的所有单元图素
// draw unit itmes
// rcCut : 只更新此矩形区内的图像
// bFront : 是否直接更新到显示屏幕
void DRAW_DrawUnit( RECT rcCut, BOOL bFront );
/////////////////////
/////////////////////
// 当某单元被选中时,显示一个菱形的框
// border
int DRAW_nBdrColors[3] = {188,84,59};
// 显示菱形框的上半部分,应该被该单元遮挡
// pptDest : 目的地坐标,左上角
// dwWidthDest : 目的地缓冲区的宽度
// pDest : 目的地数据指针
// prcCutGOld : 该单元的矩形大小和位置
// nSize : 该单元所占位置的大小(格子)
// nColorIndex : 应该贴成什么样的颜色
void DRAW_drawBorderTop( CONST POINT *pptDest, DWORD dwWidthDest, BYTE *pDest,
CONST RECT *prcCutGOld, int nSize, int nColorIndex );
// 显示菱形框的下半部分,应该遮挡该单元
// pptDest : 目的地坐标,左上角
// dwWidthDest : 目的地缓冲区的宽度
// pDest : 目的地数据指针
// prcCutGOld : 该单元的矩形大小和位置
// nSize : 该单元所占位置的大小(格子)
// nColorIndex : 应该贴成什么样的颜色
void DRAW_drawBorderBottom( CONST POINT *pptDest, DWORD dwWidthDest, BYTE *pDest,
CONST RECT *prcCutGOld, int nSize, int nColorIndex );
// 显示弓箭,火,滚木,擂石,投石,血迹,爆炸,雨,雪等
// nType : before or after the units have been drawn
// defined in CBDrawOt.cpp
int DRAW_OTHER_nMouseID=-1; // declared in CBDraw.cpp
void DRAW_DrawOthersCOM( int nType );
void DRAW_DrawOthersBMP( int nType );
void DRAW_DrawOthersMouse();
// 显示计谋提示图标(血点)
// pUnit : 被显示的单元
// pRect : 该单元的矩形大小
// prcCut : 剪切的范围
void DRAW_Draw8x8( struct UNIT_STRUCT *pUnit, CONST RECT *pRect, CONST RECT *prcCut );
/////////////////////
/////////////////////
// 装入所有战场上需要的位图和缓冲区
// load user defined surfaces
// TRUE if succeeded
// return : TRUE if successful
extern CDDPalette palMain;
BOOL DRAW_LoadMaps()
{
int i;
// test if created
if( DRAW_bLoadMaps )
{
ErrorMessage( hwndGame, DRAW_ERROR_ID+0, "Maps have been loaded!" );
return FALSE;
}
#ifdef _DEBUG
DWORD timeBegin, timeEnd;
timeBegin = timeGetTime();
OutputDebugString( "LoadMaps:" );
#endif
// clear screen
// DD_EraseFrontScreen();
// change palette
// palMain.SetPalette();
// initialize displaying and moving range
DRAW_ptScreenOffset.x = (DRAW_rcScreen.left+2)*MAP_Lib.szItem.cx;
DRAW_ptScreenOffset.y = DRAW_rcScreen.top*(MAP_Lib.szItem.cy>>1);
DRAW_rcMove.left = 2;
DRAW_rcMove.top = 2;
DRAW_rcMove.right = MAP_Lib.szNum.cx - 2;
DRAW_rcMove.bottom = MAP_Lib.szNum.cy - 2;
// load bkground surface
// same size as client area
// no color key , in system memory
OutputDebugString( "BackGround Load:\n" );
if( !DRAW_sBkGround.Create( DRAW_rcClient.right-DRAW_rcClient.left,
DRAW_rcClient.bottom-DRAW_rcClient.top, FALSE, TRUE ) )
{
OutputDebugString( "DRAW_LoadMaps: Cannot create back ground surface in video memory!\n" );
if( !DRAW_sBkGround.Create( DRAW_rcClient.right-DRAW_rcClient.left,
DRAW_rcClient.bottom-DRAW_rcClient.top, FALSE, FALSE ) )
{
ErrorMessage( hwndGame, DRAW_ERROR_ID+4, "Cannot create bkground surface!" );
return FALSE;
}
}
// WriteLogFile( "Dead.log","CCC\n" );
#ifdef _DEBUG
timeEnd = timeGetTime();
OutputString( timeEnd-timeBegin, "\n" );
timeBegin = timeEnd;
#endif
#define _ALLBMP_
#ifdef _ALLBMP_
CPicture_imageall CPImage;
char fname[_MAX_FNAME];
// WriteLogFile( "Dead.log", GAME.strPathBMP );
strcpy( fname, GAME.strPathBMP );
strcat( fname, "Other" );
strcat( fname, ".lwc" );
CPImage.image_open_compress( fname );
strcpy( fname, GAME.strPathBMP );
strcat( fname, "Other" );
strcat( fname, ".idx" );
CPImage.image_open_index( fname );
// Load other surfaces, must before read med file, read shadow file, read build file
// 读取其它图素文件
for( i=0; i< MAP_Lib.nOtherNum; i++ )
{
// has color key , in system memory
if( !CPImage.LoadBitmap( &DRAW_sOtherMap[i], i, TRUE ) )
{
ErrorMessage( hwndGame, DRAW_ERROR_ID+5, "Cannot open ground map file:", MAP_Lib.Other[i].strFile );
return FALSE;
}
}
CPImage.image_close_compress();
CPImage.image_close_index();
#else
// Load other surfaces, must before read med file, read shadow file, read build file
// 读取其它图素文件
for( i=0; i< MAP_Lib.nOtherNum; i++ )
{
// has color key , in system memory
if( !DRAW_sOtherMap[i].LoadBitmap( MAP_Lib.Other[i].strFile, TRUE, FALSE ) )
{
ErrorMessage( hwndGame, DRAW_ERROR_ID+5, "Cannot open ground map file:", MAP_Lib.Other[i].strFile );
return FALSE;
}
}
#endif
// WriteLogFile( "Dead.log","AAAAA\n" );
#ifdef _ALLBMP_
//CPicture_imageall CPImage;
//char fname[_MAX_FNAME];
strcpy( fname, GAME.strPathBMP );
strcat( fname, "Lib" );
strcat( fname, ".lwc" );
CPImage.image_open_compress( fname );
strcpy( fname, GAME.strPathBMP );
strcat( fname, "Lib" );
strcat( fname, ".idx" );
CPImage.image_open_index( fname );
// Load other surfaces, must before read med file, read shadow file, read build file
// 读取其它图素文件
for( i=0; i< MAP_Lib.nGLibNum; i++ )
{
// has color key , in system memory
if( !CPImage.LoadBitmap( &DRAW_sGroundMap[i], i, TRUE ) )
{
ErrorMessage( hwndGame, DRAW_ERROR_ID+5, "Cannot open ground map file:", MAP_Lib.Other[i].strFile );
return FALSE;
}
}
CPImage.image_close_compress();
CPImage.image_close_index();
#else
// load ground bitmaps
for( i=0; i < MAP_Lib.nGLibNum; i++ )
{
// has color key , in system memory
if( !DRAW_sGroundMap[i].LoadBitmap( MAP_Lib.Ground[i].strFile, TRUE, FALSE ) )
{
ErrorMessage( hwndGame, DRAW_ERROR_ID+8, "Cannot open ground map file:", MAP_Lib.Ground[i].strFile );
return FALSE;
}
}
#endif
// WriteLogFile( "Dead.log","DDD" );
#ifdef _DEBUG
timeEnd = timeGetTime();
OutputString( timeEnd-timeBegin, "\n" );
timeBegin = timeEnd;
#endif
// load image compress library
#ifdef _MAP_COMPRESS_
char str[_MAX_FNAME];
strcpy( str, GAME.strPathBMP );
strcat( str, "Unit" );
strcat( str, ".LWC" );
DRAW_ImageLib.image_open_compress( str );
strcpy( str, GAME.strPathBMP );
strcat( str, "Unit" );
strcat( str, ".IDX" );
DRAW_ImageLib.image_open_index( str );
#endif // _MAP_COMPRESS_
#ifdef _DEBUG
timeEnd = timeGetTime();
OutputString( timeEnd-timeBegin, "\n" );
timeBegin = timeEnd;
#endif
// Load Shadow surfaces, must before read med file
// 因为读取MED文件时要设置阴影
OutputDebugString( "SHADOW_Load: \n" );
if( !SHADOW_Load() )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -