📄 game.cpp
字号:
/*********************************
[学VC编游戏]
编著、程序设计:唐明理 2004.7
E-mail: cqtml@163.com
**********************************/
#include "stdafx.h"
#include "game.h"
JCDZ zjdz[6]={0,5,40,10,120,10,200,10,280,10,360,5};//人动作结构400幅
//0站,1走, 2刺, 3劈, 4倒 5尸
JCDZ zjdw[6]={0,5,40,10,120,10,200,10,280,10,360,5};//兽动作结构400幅
//0站,1走, 2跑, 3斗, 4倒, 5尸
unsigned short dw[7][6]={0,1,1,3,4,5, //0豹,无跑
0,1,2,3,4,5, //1狼,
0,1,1,3,4,5, //2猪,无跑
0,1,2,3,4,5, //3鹿,
0,2,2,2,4,5, //4马,无走、斗
0,1,1,1,4,5, //5羊,无跑、斗
0,1,1,3,4,5 //6雀,无跑
};
////////////////////////////////////////////////////////////////////////////
game:: game(){} //构造函数
game::~game(){} //析构函数
//****************************************************************
// init() 初始化,建立图形处理环境
// BkDC0-装载背景地面
// BkDC1-在此生成即时场景,在1个时钟周期后翻转到当前显示屏。
// MemDC-调入的对象图片。
//****************************************************************
BOOL game::init()//初始化
{ hScrDC=CreateDC("DISPLAY", NULL, NULL, NULL); //创建屏幕设备句柄
BkDC0 =CreateCompatibleDC(hScrDC); //创建地图设备句柄
BkDC1 =CreateCompatibleDC(hScrDC); //创建暂存设备句柄
bit0 =CreateCompatibleBitmap(hScrDC,WIDTH,HEIGHT);//创建暂存位图内存0
bit1 =CreateCompatibleBitmap(hScrDC,WIDTH,HEIGHT);//创建暂存位图内存1
SelectObject(BkDC1,bit1); //暂存位图内存1与暂存设备句柄关联
OldMak=(HBITMAP)SelectObject(BkDC0,bit0); //暂存位图内存0与地图设备句柄关联
MemDC =CreateCompatibleDC(hScrDC); //创建对象设备句柄
//==================================================
BK =CreateCompatibleDC(hScrDC);//创建暂存设备句柄
bi =CreateCompatibleBitmap(hScrDC,WIDTH,HEIGHT);
SelectObject(BK,bi);
bitya=CreateCompatibleBitmap(hScrDC,220,200);
DeleteDC(hScrDC); //删除屏幕设备句柄
rBlend.BlendOp = AC_SRC_OVER; //
rBlend.BlendFlags = 0; //
rBlend.AlphaFormat = 0; //
rBlend.SourceConstantAlpha=140;
//==================================================
GetCurrentDirectory(256,appdir);//取当前目录
dir=appdir;
if(dir.Right(8)=="运行程序")
dir="图片/";
else
dir="../运行程序/图片/"; //图片路径
//==================================================
sys=getsys(); //取当前系统
scrx=0;scry=0;
rs=0; //对象数置0
find_p=0; //无搜索0有搜索1
stmp=NULL;rtmp=NULL;jtmp=NULL;
return TRUE;
}
//**************************************************
// exit() 退出, 删除图形处理环境
//**************************************************
void game::exit()//退出
{ DeleteDC(BK);
DeleteObject(bi);
DeleteObject(bitya);
DeleteObject(bit0); //删除暂存位图内存
DeleteObject(bit1); //删除暂存位图内存
DeleteDC(BkDC0); //删除地图设备句柄
DeleteDC(BkDC1); //删除暂存设备句柄
DeleteDC(MemDC); //删除对象设备句柄
DeleteDC(hScrDC); //删除屏幕设备句柄
}
//****************************************************
// getsys()//识别操作系统
// 使用TransparentBlt()透明显示的需要;
// 是WIN2000,直接调用TransparentBlt();否则调用自编的。
//****************************************************
int game::getsys()//识别操作系统
{ OSVERSIONINFO stOSVI ;
ZeroMemory(&stOSVI , sizeof ( OSVERSIONINFO )) ;
stOSVI.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO ) ;
GetVersionEx ( &stOSVI);
int a=0;
if (stOSVI.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS &&
(stOSVI.dwMajorVersion>4||(stOSVI.dwMajorVersion==4
&& stOSVI.dwMinorVersion>0)))
a=1;// rec="Windows98";
if (VER_PLATFORM_WIN32_NT==stOSVI.dwPlatformId&&stOSVI.dwMajorVersion>=5)
a=2;// rec="Windows2000";
if (VER_PLATFORM_WIN32_NT==stOSVI.dwPlatformId&&stOSVI.dwMajorVersion==4)
a=3;// rec="WindowsNT4.0";
if (VER_PLATFORM_WIN32_NT==stOSVI.dwPlatformId)
a=4;// rec="WindowsNT";
return a;
}
//**********************************************************
// inscreer(int i)//在显示区?
//**********************************************************
BOOL game::inscreer(int i)//在显示区?
{ int xs=man[i].xix-scrx-man[i].w/2; //x当前位置
int ys=man[i].xiy-scry-man[i].h; //y当前位置
if(xs>(-man[i].w+2)&&xs<WIDTH&&ys>(-man[i].h+10)&&ys<HEIGHT)
return TRUE;
else return FALSE;
}
//**********************************************************
// sort() 排序(冒泡法)
// 将rs个对象序列对Y位置进行排序;用于在显示时分出前后位置。
//**********************************************************
void game::sort()//排序(冒泡法)
{ MAN man0;
for(int a=0;a<rs-1;a++)
for(int b=a+1;b<rs;b++)
if(man[a].xiy>man[b].xiy)//前数大于后数
{man0=man[a]; //两数交换
man[a]=man[b];
man[b]=man0;
} //排序结果,当前位置Y小的在前。
mans=0; //显示区对象数置0
}
//**************************************************
// getobjwh(int q) 取对象的尺寸
// 取序号q对象的尺寸(宽man[q].w高man[q].h)。
//**************************************************
void game::getobjwh(int q)//取对象的尺寸
{ CString cc;
if(man[q].lb==0) {cc="人";}
if(man[q].lb==1) {cc="兽";}
if(man[q].lb==2) {cc="景";}
if(getpic(cc,man[q].p)==FALSE) return;
man[q].w=w; man[q].h=h; //对象的尺寸
}
//**********************************************************************
// TransparentBlt2 (......)透明显示
// 根据关键色,将hdc1中的图形在hdc0中
// 自动生成掩模,并生成透明图形。
// 注:TransparentBlt(......)是一个WIN API函数,功能和这里的相同。
// 在WIN2000和以后的系统上可用。在WIN98中有严重的资源泄漏,根本不能用。
// 使用TransparentBlt(......)前,需引用:
// #include <wingdi.h>
// #pragma comment (lib,"msimg32.lib")
//**********************************************************************
void game::TransparentBlt2(HDC hdc0, //目标DC
int nX0,int nY0,int nW0,int nH0,//目标左坐标,目标宽高宽
HDC hdc1, //源DC
int nX1,int nY1,int nW1,int nH1,//源起点坐标,源宽高宽
UINT Tcol) //透明色,COLORREF类型
{ if(sys>1)//是win98以上的系统,直接调API函数TransparentBlt()
{TransparentBlt(hdc0,nX0,nY0,nW0,nH0,hdc1,nX1,nY1,nW1,nH1,Tcol);
return;
}
HBITMAP hBMP =CreateCompatibleBitmap(hdc0,nW0, nH0); //创建位图内存
HBITMAP mBMP =CreateBitmap(nW0,nH0,1,1,NULL); //创建单色掩码位图
HDC hDC =CreateCompatibleDC(hdc0); //创建设备句柄
HDC mDC =CreateCompatibleDC(hdc0); //创建设备句柄
HBITMAP oldBMP =(HBITMAP)SelectObject(hDC, hBMP);
HBITMAP oldmBMP=(HBITMAP)SelectObject(mDC, mBMP);
// 将源DC中的位图拷贝到临时DC中
if (nW0==nW1&&nH0==nH1)
BitBlt(hDC,0,0,nW0,nH0,hdc1,nX1,nY1,SRCCOPY);
else
StretchBlt(hDC,0,0,nW0,nH0,hdc1,nX1,nY1,nW1,nH1,SRCCOPY);
SetBkColor(hDC, Tcol);// 设置透明色
BitBlt(mDC,0,0,nW0,nH0,hDC,0,0,SRCCOPY);//生成透明区域为白色,其它区域为黑色的掩码位图
SetBkColor(hDC, RGB(0,0,0)); //生成透明区域为黑色,其它区域保持不变的位图
SetTextColor(hDC, RGB(255,255,255)); //白色
BitBlt(hDC,0,0,nW0,nH0,mDC,0,0,SRCAND);
SetBkColor(hdc0,RGB(255,255,255)); //透明部分保持屏幕不变,其它部分变成黑色
SetTextColor(hdc0,RGB(0,0,0)); //黑色
BitBlt(hdc0,nX0,nY0,nW0,nH0,mDC,0,0,SRCAND); //"与"运算,在hdc0生成掩模
BitBlt(hdc0,nX0,nY0,nW0,nH0,hDC,0,0,SRCPAINT);//"或"运算,生成最终透明效果
SelectObject(hDC,oldBMP);
SelectObject(mDC,oldmBMP);
DeleteDC(hDC);
DeleteDC(mDC);
DeleteObject(hBMP);
DeleteObject(mBMP);
}
//**************************************************
// setman(int q) 设置活动对象初值
// 由给定的对象、方位、动作计算出图形的位置和数量。
//**************************************************
void game::setman(int q)//设置活动对象初值
{ int a=400;
if(man[q].lb==0)//人
{man[q].m0=man[q].js*a+zjdz[man[q].zs].qi
+man[q].fw*zjdz[man[q].zs].bc;//位置初值
man[q].m1=zjdz[man[q].zs].bc+man[q].m0;//位置终值
man[q].p=man[q].m0; //数量计数
}
if(man[q].lb==1)//兽
{man[q].m0=man[q].js*a+zjdw[man[q].zs].qi
+man[q].fw*zjdw[man[q].zs].bc;//位置初值
man[q].m1=zjdw[man[q].zs].bc+man[q].m0;//位置终值
man[q].p=man[q].m0; //数量计数
}
man[q].zd=0;
}
//**************************************************
// manmove(int i) 活动对象的移动
// 由当前、目标位置的差,计算当前位置向不同方位的改变。
//**************************************************
void game::manmove(int i)//活动对象的移动
{ if(man[i].lb==2) return; //是静物返回
if(find_p==1&&man[i].pk<1) return;//无搜索路径返回,没加寻路时不要这句。
int stx,sty,qx,qy;
switch(man[i].zs)
{case 2: {stx=9;sty=6;break;}//跑步长
case 1: {stx=4;sty=2;break;}//走步长
default:{stx=2;sty=1;break;}
}
qx=man[i].x0-man[i].xix; //x当前、目标位置差
qy=man[i].y0-man[i].xiy; //y当前、目标位置差
if (qx==0&&qy==0)
{if(find_p==1) find_a(i); //没加寻路时不要这句。
return ; //到达返回
}
int qxa=abs(qx); //x位置差绝对值
int qya=abs(qy); //y位置差绝对值
if(qxa<stx) stx=qxa; //位置差不足步长,步长为差
if(qya<sty) sty=qya; //
if(qx!=0) man[i].xix+=qxa/qx*stx;//当前位置加步长
if(qy!=0) man[i].xiy+=qya/qy*sty;//[qya/qy]单位绝对值
}
//**************************************************
// bianfw(int q)//方位转换
// 由当前、目标位置的差,计算活动图形的方向取向。
//**************************************************
void game::bianfw(int q)//方位转换
{ int qx=man[q].x0-man[q].xix; //x当前,目标位置差
int qy=man[q].y0-man[q].xiy; //y当前,目标位置差
if(qx==0&&qy==0)
{if(man[q].zd==0) man[q].zs=0; //为0,动作为站,方位保留
goto aa;
}
if(man[q].zd==0) //没打
{int a=rand()%2+1; //随机产生走、跑
if(man[q].lb==0) man[q].zs=1; //是人设为走
if(man[q].lb==1) man[q].zs=dw[man[q].js][a];//是兽
}
if(qx<0&&qy>0) {man[q].fw=1;goto aa;}//取西南向
if(qx<0&&qy<0) {man[q].fw=3;goto aa;}//取西北向
if(qx>0&&qy<0) {man[q].fw=5;goto aa;}//取东北向
if(qx>0&&qy>0) {man[q].fw=7;goto aa;}//取东南向
if (qy>0) {man[q].fw=0;goto aa;}//取南向
if(qx<0) {man[q].fw=2;goto aa;}//取西向
if (qy<0) {man[q].fw=4;goto aa;}//取北向
if(qx>0) {man[q].fw=6;goto aa;}//取东向
aa: setman(q); //设置活动对象初值
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -