📄 tankframe.cpp
字号:
/*-----------------------------------------------------
坦克大决战主窗口实现
版权所有:JT Studio 王景焘
2001年12月 保留所有权利
-------------------------------------------------------*/
#include "stdafx.h"
#include "Tank.h"
#include "TankFrame.h"
#include <math.h>
#include <stdio.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTankFrame
//IMPLEMENT_DYNCREATE(CTankFrame,CWnd)
CTankFrame::CTankFrame()
{
int x,y;
x=::GetSystemMetrics(SM_CXSCREEN);//显示屏幕宽度
y=::GetSystemMetrics(SM_CYSCREEN);
CRect rect((x-640)/2,(y-480)/2,(x-640)/2+640,(y-480)/2+480);
LPCSTR strClass=AfxRegisterWndClass(CS_DBLCLKS,::LoadCursor(NULL,IDC_ARROW),
(HBRUSH)GetStockObject(BLACK_BRUSH),
AfxGetApp()->LoadIcon(IDR_MAINFRAME));
if(CreateEx(WS_EX_APPWINDOW,strClass,"坦克大决战",WS_POPUP,rect.left,rect.top,
rect.Width(),rect.Height(),NULL,NULL,0)==FALSE)exit(1);
}
CTankFrame::~CTankFrame()
{
ReleaseObjects();//释放DirectX资源
Cleanup();//释放多媒体文件资源
DestroyLink();//释放链表资源
delete top;
delete tops;
delete topt;
delete topa;//释放表头
mciSendCommand(wDeviceID,MCI_CLOSE,MCI_WAIT,NULL);//释放背景midi
}
BEGIN_MESSAGE_MAP(CTankFrame, CWnd)
//{{AFX_MSG_MAP(CTankFrame)
ON_WM_ACTIVATEAPP()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_MESSAGE(MM_MCINOTIFY,OnMciNotify)//背景midi播完消息
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTankFrame message handlers
void CTankFrame::OnActivateApp(BOOL bActive, HTASK hTask)
{
CWnd::OnActivateApp(bActive, hTask);
// TODO: Add your message handler code here
window_active = bActive;
}
/*--------------------------------------------------
初始化函数
----------------------------------------------------*/
void CTankFrame::Init()
{
DDCOLORKEY ddck;
FILE *fp;
CDC *cdc;
cdc=GetDC();
cdc->SetBkMode(TRANSPARENT);
cdc->SetTextColor(RGB(255,255,0));
cdc->TextOut(250,200,"正在初始化,请稍候...");
ReleaseDC(cdc);
/*全局变量初始化*/
FrameTime=timeGetTime();
FrameCount=0;
Frames=0;
FrameTime=timeGetTime();
mapupdate=timeGetTime();
top=new TANK;
tops=new SHOT;
topt=new TREE;
topa=new APPL;
if(top==NULL||tops==NULL||topt==NULL||topa==NULL)Fail("链表初始化错误!");
top->next=NULL;
tops->next=NULL;
topt->next=NULL;
topa->next=NULL;
end=top;
ends=tops;
endt=topt;
enda=topa;//初始化链表
lpDSBFire=NULL;
lpDSBExplo=NULL;
lpDSBBem=NULL;
lpDSBBon=NULL;
if(FAILED(InitDdraw()))Fail("DirectDraw初始化错误!");
lpDDSOtank=DDLoadBmp(lpDD,"OTANK",0,0,0);
lpDDSTank=DDLoadBmp(lpDD,"TANK",0,0,0);
lpDDSShot=DDLoadBmp(lpDD,"SHOT",0,0,0);
lpDDSMap=DDLoadBmp(lpDD,"MAP",0,0,0);
lpDDSAppl=DDLoadBmp(lpDD,"APPL",0,0,0);
lpDDSExplo=DDLoadBmp(lpDD,"EXPLO",0,0,0);
if(lpDDSOtank==NULL||lpDDSShot==NULL||lpDDSMap==NULL
||lpDDSTank==NULL||lpDDSExplo==NULL||lpDDSAppl==NULL)
Fail("图片资源加载错误!");
if(FAILED(InitDsound()))Fail("DirectSound初始化错误!");
LoadStatic(lpDS,"Explo.wav",lpDSBExplo);
LoadStatic(lpDS,"fire.wav",lpDSBFire);
LoadStatic(lpDS,"BEM.wav",lpDSBBem);
LoadStatic(lpDS,"BON.wav",lpDSBBon);
if(lpDSBExplo==NULL||lpDSBFire==NULL||
lpDSBBem==NULL||lpDSBBon==NULL)Fail("声音资源加载错误!");
/*设置黑色为关键色*/
ddck.dwColorSpaceLowValue=RGB(0,0,0);
ddck.dwColorSpaceHighValue=RGB(0,0,0);
lpDDSOtank->SetColorKey(DDCKEY_SRCBLT,&ddck);
lpDDSTank->SetColorKey(DDCKEY_SRCBLT,&ddck);
lpDDSGround->SetColorKey(DDCKEY_SRCBLT,&ddck);
lpDDSMap->SetColorKey(DDCKEY_SRCBLT,&ddck);
lpDDSAppl->SetColorKey(DDCKEY_SRCBLT,&ddck);
lpDDSExplo->SetColorKey(DDCKEY_SRCBLT,&ddck);
/*加载配置文件*/
fp=fopen("tank.cfg","rb");
if(fp==NULL)Fail("配置文件错误!");
if(fread(&config,sizeof(config),1,fp)!=1)Fail("读取配置文件错误!");
fclose(fp);
config.playernum=1;
srand(timeGetTime());//初始化随机数发生器
/*初始化游戏状态变量*/
mode.gamestatus=0;
mode.stage=0;
mode.isplay=FALSE;
/*字体动画变量*/
txtupdate=timeGetTime();
spd=0;
}
/*-------------------------------------
初始化具体关卡
---------------------------------------*/
void CTankFrame::InitStage()
{
int i;
if(!mode.isplay)
{
sprintf(fname,"bkm%d.mid",rand()%6+1);//随机生成背景音乐的文件名
PlayMid();
}
if(config.playernum==1)mp.tanknum=4;
DisMap();//显示地图
for(i=0;i<config.playernum;i++)
{
InitOtank(&players[i],i);//初始化我方坦克
for(int j=0;j<4;j++)players[i].tank[j]=0;
}
bons.valid=0;//宝物无效
mode.status=0;
}
/*---------------------------------------------
加载地图初始化地图变量
-----------------------------------------------*/
BOOL CTankFrame::LoadMap()
{
FILE *fp;
mode.tanknum=0;//同现坦克数为0
fp=fopen("mm.map","rb");
if(fp==NULL)return FALSE;
fseek(fp,sizeof(mp)*(long)mode.stage,SEEK_SET);
if(!fread(&mp,sizeof(mp),1,fp))
{
mode.stage=0;
fseek(fp,0L,SEEK_SET);
if(!fread(&mp,sizeof(mp),1,fp))return FALSE;
}//如果读文件失败就读第一关
mode.stage++;
fclose(fp);
return TRUE;
}
/*-----------------------------------------------
显示所加载的地图
-------------------------------------------------*/
void CTankFrame::DisMap()
{
int i,j;
RECT src;
LPTREE tree;
Cls(lpDDSGround,RGB(0,0,0));//背景页面为黑色
for(i=0;i<36;i++)
{
for(j=0;j<46;j++)
{
if(mp.array[i][j]==7)//如果是树林就保存
{
tree=new TREE;
if(tree==NULL)Fail("内存不够!");
tree->x=i;
tree->y=j;
tree->next=NULL;
endt->next=tree;
endt=tree;
mp.array[i][j]=0;
}
else
{
src.top=0;
src.left=mp.array[i][j]*12;
if(mp.array[i][j]==11)src.left=6*12;
src.right=src.left+12;
src.bottom=12;
if(FAILED(lpDDSGround->BltFast(12*j,12*i,lpDDSMap,&src,
DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT)))
Fail("不能显示地图");//将地图元素画到背景页
}
}
}
}
/*--------------------------------------
游戏循环
----------------------------------------*/
void CTankFrame::Go()
{
HDC hdc;
HFONT ft,oldf;
HGDIOBJ hpen,hold;
DWORD time;
RECT src;
char tm[128];
int i,j,stg,tkn1=0,tkn2=0,score;
if(mode.gamestatus==0)//状态0--标题画面
{
time=timeGetTime();
if((time-txtupdate)>50&&spd<=420)//字体动画
{
Cls(lpDDSBack,RGB(0,0,0));
lpDDSBack->GetDC(&hdc);
SetBkMode(hdc,TRANSPARENT);
ft=CreateFont(100,0,0,0,500,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"隶书");
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(136,234,28));
TextOut(hdc,70,480-spd,"坦克大决战",10);
SelectObject(hdc,oldf);
DeleteObject(ft);
ft=CreateFont(30,0,0,0,200,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"楷体_GB2312");
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(220,234,28));
TextOut(hdc,260,600-spd,"版本 1.0b",9);
TextOut(hdc,280,680-spd,"单人游戏",8);
TextOut(hdc,280,720-spd,"双人游戏",8);
SelectObject(hdc,oldf);
DeleteObject(ft);
ft=CreateFont(20,0,0,0,200,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,NULL);
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(220,55,33));
TextOut(hdc,170,830-spd,"版权所有 JT Studio 王景焘 2001年12月",38);
TextOut(hdc,260,860-spd,"保留所有权利",12);
SelectObject(hdc,oldf);
DeleteObject(ft);
lpDDSBack->ReleaseDC(hdc);
txtupdate=time;
spd+=10;
if FAILED(lpDDSPrimary->Flip(NULL,DDFLIP_WAIT))Fail("不能翻转页面!");//翻转页面
}
if(spd>=420)//画选择坦克、写最初任务
{
src.top=0;
src.left=72;
src.bottom=24;
src.right=96;
if(FAILED(lpDDSPrimary->BltFast(240,225+config.playernum*40,lpDDSOtank,&src,
DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT)))Fail("不能生成标题画面");
lpDDSPrimary->GetDC(&hdc);
ft=CreateFont(20,0,0,0,200,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"楷体_GB2312");
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(0,255,255));
SetBkColor(hdc,RGB(0,0,0));
sprintf(tm,"任务%02d",mode.stage+1);
TextOut(hdc,280,350,tm,6);
SelectObject(hdc,oldf);
DeleteObject(ft);
lpDDSPrimary->ReleaseDC(hdc);
}
for(int i=0;i<config.playernum;i++)CreateOtank(&players[i],i);//生成我方坦克
players[0].score=0;players[0].lifenum=5;
players[1].score=0;players[1].lifenum=5;//分数为0,初始坦克数量为5
}
else if(mode.gamestatus==1)//状态1--加载地图
{
LoadMap();
mode.gamestatus=2;
}
else if(mode.gamestatus==2)//状态2--任务画面
{
Cls(lpDDSBack,RGB(60,113,60));
if(!mode.isplay)
{
strcpy(fname,"start.mid");
PlayMid();//播放开始音乐
mode.isplay=TRUE;
}
lpDDSBack->GetDC(&hdc);
SetBkMode(hdc,TRANSPARENT);
ft=CreateFont(50,0,0,0,200,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,NULL);
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(255,255,255));
if(mode.stage==0)stg=1;
else stg=mode.stage;
sprintf(tm,"任务 %d",stg);
TextOut(hdc,210,220,tm,strlen(tm));
SelectObject(hdc,oldf);
DeleteObject(ft);
lpDDSBack->ReleaseDC(hdc);
if FAILED(lpDDSPrimary->Flip(NULL,DDFLIP_WAIT))Fail("不能翻转页面!");//翻转页面
}
else if(mode.gamestatus==7)//状态7--初始化关卡
{
InitStage();
mode.gamestatus=3;
txtupdate=timeGetTime();
spd=0;//恢复字体动画变量
}
else if(mode.gamestatus==3)//状态3--正常游戏
{
if((mp.tank[0]+mp.tank[1]+mp.tank[2]+mp.tank[3]+mode.tanknum)==0)mode.gamestatus=5;//任务完成
if(players[0].lifenum==0&&config.playernum==1||
players[0].lifenum==0&&players[1].lifenum==0&&config.playernum==2)mode.gamestatus=4;//任务失败
Cls(lpDDSBack,RGB(0,0,0));
Update();//更新游戏画面
}
else if(mode.gamestatus==4)//状态4--任务失败
{
Update();
time=timeGetTime();
if((time-txtupdate)>50&&spd<=250)
{
txtupdate=time;
spd+=5;
}//设置字体动画变量
lpDDSPrimary->GetDC(&hdc);
IntersectClipRect(hdc,TANK_XL,TANK_YU,TANK_XR,TANK_YD);
SetBkMode(hdc,TRANSPARENT);
ft=CreateFont(50,0,0,0,500,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"隶书");
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(255,28,28));
TextOut(hdc,180,480-spd,"任务失败",8);
SelectObject(hdc,oldf);
DeleteObject(ft);
lpDDSPrimary->ReleaseDC(hdc);
}
else if(mode.gamestatus==5)//状态5--任务完成
{
Update();
time=timeGetTime();
if((time-txtupdate)>50&&spd<=250)
{
txtupdate=time;
spd+=5;
}//设置字体动画变量
lpDDSPrimary->GetDC(&hdc);
IntersectClipRect(hdc,TANK_XL,TANK_YU,TANK_XR,TANK_YD);
SetBkMode(hdc,TRANSPARENT);
ft=CreateFont(50,0,0,0,500,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"隶书");
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(28,255,28));
TextOut(hdc,180,480-spd,"任务完成",8);
SelectObject(hdc,oldf);
DeleteObject(ft);
lpDDSPrimary->ReleaseDC(hdc);
}
else if(mode.gamestatus==6)//状态6--游戏失败分数画面
{
Cls(lpDDSBack,RGB(0,0,0));
src.top=0;
src.left=72;
src.bottom=24;
src.right=96;
/*画各种敌方坦克*/
if(FAILED(lpDDSBack->BltFast(200,200,lpDDSTank,&src,
DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT)))Fail("不能生成得分画面");
src.top+=24;
src.bottom+=24;
if(FAILED(lpDDSBack->BltFast(250,200,lpDDSTank,&src,
DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT)))Fail("不能生成得分画面");
src.top+=24;
src.bottom+=24;
if(FAILED(lpDDSBack->BltFast(300,200,lpDDSTank,&src,
DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT)))Fail("不能生成得分画面");
src.top+=24;
src.bottom+=24;
if(FAILED(lpDDSBack->BltFast(350,200,lpDDSTank,&src,
DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT)))Fail("不能生成得分画面");
for(i=0;i<config.playernum;i++)
{
src.top=24*i;
src.bottom=src.top+24;
if(FAILED(lpDDSBack->BltFast(90,240+40*i,lpDDSOtank,&src,
DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT)))Fail("不能生成得分画面");
}//画我方坦克
lpDDSBack->GetDC(&hdc);
SetBkMode(hdc,TRANSPARENT);
ft=CreateFont(50,0,0,0,500,FALSE,FALSE,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"仿宋GB_2312");
oldf=(HFONT)SelectObject(hdc,ft);
SetTextColor(hdc,RGB(255,28,28));
TextOut(hdc,200,50,"任务失败!",10);
SelectObject(hdc,oldf);
DeleteObject(ft);
sprintf(tm,"第%02d关",mode.stage);
TextOut(hdc,280,130,tm,6);
TextOut(hdc,405,200,"奖励",4);
TextOut(hdc,455,200,"加分",4);
TextOut(hdc,550,200,"总分",4);
hpen=CreatePen(PS_SOLID,1,RGB(255,255,0));
hold=SelectObject(hdc,hpen);
MoveToEx(hdc,30,190,NULL);
LineTo(hdc,610,190);
for(i=0;i<config.playernum+1;i++)
{
MoveToEx(hdc,30,190+40*i,NULL);
LineTo(hdc,30,230+40*i);
MoveToEx(hdc,185,190+40*i,NULL);
LineTo(hdc,185,230+40*i);
MoveToEx(hdc,235,190+40*i,NULL);
LineTo(hdc,235,230+40*i);
MoveToEx(hdc,285,190+40*i,NULL);
LineTo(hdc,285,230+40*i);
MoveToEx(hdc,335,190+40*i,NULL);
LineTo(hdc,335,230+40*i);
MoveToEx(hdc,385,190+40*i,NULL);
LineTo(hdc,385,230+40*i);
MoveToEx(hdc,445,190+40*i,NULL);
LineTo(hdc,445,230+40*i);
MoveToEx(hdc,515,190+40*i,NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -