📄 mygame.cpp
字号:
// MyGame.cpp: implementation of the MyGame class.
//游戏类工程文件
//创建于 2006. 修改于 2008.10
//吴文捷
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mmsystem.h"
#pragma comment(lib,"winmm.lib")
#include "常数定义.h"
#include "MyGame.h"
#include "Control.h"
//==============全局变量=================
MyDDraw ddraw;
MyDInput dinput;
MyDSound dsound;
CMyFile file;
CTank *tank;
CPlayer player;
CBullete *bullete;
bool NewGame;
bool ShowMainMenu;
bool ShowStage;
short MainMenuSelect;
bool SetPause;
bool StartGame1,StartGame2;
bool DrawGame;
bool playsound[10];
//===============================
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/**********构造函数*************
函数名:CGame()
用途:游戏开始前只初始化一次的
参数:
返回值:
其它:
********************************/
MyGame::MyGame()
{
//变量初始化
DrawGame=false;
ShowStage=false;
StartGame1=false;
StartGame2=false;
SetPause=false;
MainMenuSelect=0;
ShowMainMenu=true;
NewGame=false;
player.blood =24;
m_iFrameRate=FPS;
ThisTick=0;
LastTick=0;
Fps=0;
tFPS=0;
SetFrameRate(m_iFrameRate); //设置帧频(1秒30帧)
//加载声音文件到各次缓冲区
// char c[10];
dsound.CreateBuffer("Music\\menu.WAV",0);
dsound.CreateBuffer("Music\\butt_press.wav",1);
dsound.CreateBuffer("Music\\决定.wav",2);
dsound.CreateBuffer("Music\\PShot.wav",3);
dsound.CreateBuffer("Music\\EShot.wav",4);
dsound.CreateBuffer("Music\\击中.WAV",5);
dsound.CreateBuffer("Music\\爆炸.WAV",6);
dsound.CreateBuffer("Music\\吸收.WAV",7);
dsound.CreateBuffer("Music\\炸弹.WAV",8);
for(i=0;i<9;i++){playsound[i]=false,playsound[0]=true;}
}
/******析构函数*****
函数名:~CGame()
用途:
参数:
返回值:
其它:
********************/
MyGame::~MyGame()
{
FreeSpace();
// ChangeDisplaySettings(NULL,0); //恢复原有设置
}
/******************************
函数名:GameInit()
用途:每关开始前的游戏初始化
参数:程序主窗口句柄,程序实例句柄
返回值:初始化成功返回TRUE
其它:
*******************************/
BOOL MyGame::GameInit()
{
/* MySprite= new CSprite; //重新创建子画面
//读取地图文件
char s[12];
sprintf(s,"map\\%d.txt",MyFile->m_MapIndex);
m_Mappath=s;
MyFile->ReadFile(m_Mappath);
CGame::GameMusic("sound\\BACK.MID",1,1);
*/
//读取地图文件
char s[15];
//sprintf(s,"map\\MapDIY.map");
if(MainMenuSelect==0){sprintf(s,"map\\%d.map",file.MapIndex);}
if(MainMenuSelect==32){sprintf(s,"map\\MapDIY.map");}
m_MapPath=s;
file.ReadFile(m_MapPath);
tank = new CTank[11];
bullete= new CBullete[11];
for(i=1;i<11;i++)
{
tank[i].OnShip=false;
tank[i].BoomNow=false;
tank[i].EatKind=0;
short k=tank[i].things.kind=Rando(6);
if(k!=0)
{
tank[i].things.BmpXY.x=k*23;
tank[i].things.BmpXY.y=0;
tank[i].things.LiveTime=10;
}
tank[i].showrect=false;
tank[i].things.show=false;
tank[i].blood=16; //8的倍数
tank[i].GetBulleteStartPoint=true;
tank[i].way=1;
tank[i].MoveSpeed=2;
tank[i].ScreenXY.x=GAMET_X+i*64-32;
tank[i].ScreenXY.y=32;
tank[i].MoveStop=false;
tank[i].GetTankRect(); // 取得坦克矩形结构
bullete[i].Speed=3;
bullete[i].BulleteHit=true;
bullete[i].ShowBomb=false;
}
tank[0].OnShip=false;
tank[0].BoomNow=false;
tank[0].showrect=false;
tank[0].things.show=false;
tank[0].EatKind=0;
tank[0].blood =player.blood;
tank[0].GetBulleteStartPoint=true;
tank[0].way=3;
tank[0].MoveSpeed=2;
tank[0].ScreenXY.x=player.ScreenXY.x=GAMET_X+16*20;
tank[0].ScreenXY.y=player.ScreenXY.y=16*30;
tank[0].MoveStop=player.MoveStop=false;
tank[0].GetTankRect();
bullete[0].Speed=6;
bullete[0].BulleteHit=true;
bullete[0].ShowBomb=false;
ddraw.showdoop=false;
ddraw.PutDoop=0;
ddraw.StartDoopTest=true;
return FALSE;
}
/******************************
函数名:GameStart()
用途: 开始游戏
参数: 无
返回值:无
其它:
*******************************/
void MyGame::GameStart()
{
dinput.GetKey();
GetFrameDelay();
//playsound
if(playsound[0]){dsound.PlayWav(0,1);}
else{dsound.StopWav(0);}
for(i=1;i<9;i++)
{
if(playsound[i]){dsound.PlayWav(i,0);playsound[i]=false;}
}
//======================================================
short t=0;
for(i=1;i<11;i++)
{
if(tank[i].dead){t++;}
else
{
//检测吃到的物品
tank[i].EatKind=EatThingTest(tank[i].ScreenXY);
ChangeTankStyle(i,tank[i].EatKind);
}
}
tank[0].ScreenXY=player.ScreenXY;
tank[0].EatKind=EatThingTest(tank[0].ScreenXY);
ChangeTankStyle(0,tank[0].EatKind);
if(t==10)
{
t=0;
file.NextFile=true;
FreeSpace();
file.MapIndex++;
if(file.MapIndex>10){file.MapIndex=1;}
GameInit();
ShowStage=true;
for(i=0;i<8;i++){playsound[i]=false,dsound.StopWav(i);}
return ;
}
if(NewGame)
{
file.MapIndex=1;
GameInit();
tank[0].blood=24;
}
//=========================================================
ddraw.Render(); //绘制场景
/*
//文本
DrawText(g_hOffscreenDC, 0 ,0,TRUE);
BitBlt(hdc1, 0, 0, 800, 600, g_hOffscreenDC, 0 ,0, SRCCOPY); //绘制到屏幕
*/
}
/******************************
函数名:GameEnd()
用途: 清理
参数: 无
返回值:无
其它:
*******************************/
void MyGame::GameEnd()
{
/*
delete MyFile;
delete []MyBitmap;
delete MySprite;
*/
}
/******************************
函数名:HandleKeys()
用途: 取得键盘控制
参数: 无
返回值:无
其它:
*******************************/
void MyGame::HandleKeys()
{
/* 用在DP中
//检测闪屏
if(GetAsyncKeyState(VK_RETURN) < 0 && m_ShowStartScreen)
{
}
if(GetAsyncKeyState(VK_RETURN) < 0 && m_ShowEndScreen)
{
}
//不是闪屏状态
if(!m_ShowStartScreen && !m_ShowEndScreen)
{
if (GetAsyncKeyState(VK_LEFT) < 0 || GetAsyncKeyState('A') < 0)
{
//MessageBox(GetFocus(),"按下左方向键!","键盘消息!",MB_OK);
if(m_movex !=0)m_movex -=10;
}
if (GetAsyncKeyState(VK_RIGHT) < 0 || GetAsyncKeyState('D') < 0)
{
if(m_movex <2*SCREEN_W)m_movex +=10;
}
if (GetAsyncKeyState(VK_UP) < 0 || GetAsyncKeyState('W') < 0)
{
if(m_movey!=0)m_movey-=10;
}
if (GetAsyncKeyState(VK_DOWN) < 0 || GetAsyncKeyState('S') < 0)
{
if(m_movey<2*SCREEN_H)m_movey+=10;
}
if (GetAsyncKeyState('J') < 0 )
{
}
if (GetAsyncKeyState('K') < 0 )
{}
}
*/
}
/******************************
函数名:SetFrameRate()
用途: 设置帧频
参数: 帧频率
返回值:无
其它:
*******************************/
inline void MyGame::SetFrameRate(int iFrameRate)
{
m_iFrameDelay=1000/iFrameRate; //得到1帧经过的毫秒数
}
/******************************
函数名:GetFrameDelay()
用途: 建立并进入游戏循环
参数: 无
返回值:无
其它:
*******************************/
void MyGame::GetFrameDelay()
{
tFPS++;
ThisTick = timeGetTime(); //须包含#include "mmsystem.h"
//和#pragma comment(lib,"winmm.lib")头文件
if (ThisTick - LastTick > m_iFrameDelay ) //1帧
{
LastTick = ThisTick;
Fps = tFPS;
tFPS = 0;
ddraw.OneFps=true; //1帧
static short add=0;
static short add2=0;
static short add3=0;
add++;add2++;add3++;
if(add>=FPS){ddraw.OneSecond=true;add=0;}//1秒
else{ddraw.OneSecond=false;}
if(add2>=FPS/15){ddraw.flash=true;add2=0;} //1/15秒
else{ddraw.flash=false;}
if(add3>=FPS/2){ddraw.halfsecond=true;add3=0;} //1/2秒
else{ddraw.halfsecond=false;}
// HandleKeys(); //取得键盘控制
// GamePaint(g_hOffscreenDC); //绘制游戏
}else{ddraw.OneFps=false;}
}
/******************************
函数名:GamePaint()
用途: 游戏重绘
参数: 离屏页DC
返回值:无
其它:
*******************************/
void MyGame::GamePaint(HDC &hDC)
{
/* if(MyFile->NextFile) //下一关
{
delete MySprite;
GameInit();
MyFile->NextFile=false;
}
*/
/*
//背景
MySprite->Render(hDC,MySprite->flashdc);
MySprite->DrawMenu(hdc2);
BitBlt(hDC, m_movex ,490+m_m_movey, 800, 600, hdc2, 0 ,0, SRCCOPY);
//地图
MySprite->DrawMap(hDC,21,17,32,32);
//物品(仅序号2、4、6、8的坦克可能携带)
for(i=2;i<=8;i+=2){MySprite->DrawThings(hDC,i);}
//坦克
for(i=1;i<=10;i++){MySprite->DrawSharp(hDC,i);DrawBloodBar(hDC,i);} //敌人
MySprite->DrawPlayer(hDC); //玩家
//血槽
DrawBloodBar(hDC,0,RGB(0,255,0));
//子弹
MySprite->DrawMyBullets(hDC,Bullet[0].m_MoveWay); //玩家的
MySprite->DrawBoom(hDC,0); //玩家爆炸
for(i=1;i<=10;i++)
{
MySprite->DrawEnemyBullets(hDC,Bullet[i].m_MoveWay,i); //敌人的
//爆炸
MySprite->DrawBoom(hDC,i);
}
//草地
MySprite->DrawGress(hDC,21,17,32,32);
//开始的闪屏
if(m_ShowStartScreen){MySprite->DrawFlassScreen(hDC,true);}
//游戏结束的闪屏
if(m_ShowEndScreen){MySprite->DrawFlassScreen(hDC,false);}
*/
}
/******************************
函数名:DrawText()
用途: 绘制文本
参数: 离屏页DC,是否绘制
返回值:无
其它:
*******************************/
void MyGame::DrawText(HDC &hDC, int x, int y, BOOL draw)
{/*
if(!draw){return;}
SetTextColor(hDC,RGB(0,255,255)); //文本颜色
SetBkMode(hDC,TRANSPARENT); //背景透明
char s8[9];
ZeroMemory( s8, 9 );
sprintf(s8, "每秒=%d帧", m_iFrameRate);
TextOut(hDC,x,y,s8,9);
TextOut(hDC,x,20+y,"ESC退出",7);
char s1[6];
ZeroMemory( s1, 6 );
sprintf(s1, "第%d关", gs->GMT.y);
TextOut(hDC,10,50,s1,6);
char s2[7];
ZeroMemory( s2, 7 );
sprintf(s2, "敌人:%d", (10-(MySprite->m_DeadAdd)));
TextOut(hDC,10,100,s2,7);
char s3[13];
ZeroMemory( s3, 13 );
sprintf(s3, "有效时间:%d", MySprite->t);
TextOut(hDC,350,550,s3,13);
char s4[9];
ZeroMemory( s4, 9 );
sprintf(s4, "最高分:%d", Tank[0].m_MoveSpeed);
TextOut(hDC,10,160,s4,9);
char s9[5];
ZeroMemory( s4, 5 );
sprintf(s4, "分数:%d", Tank[0].m_rect.top);
TextOut(hDC,10,160,s4,5);
char s5[11];
ZeroMemory( s5, 11 );
sprintf(s5, "粒子数:%d", bomb->m_n);
TextOut(hDC,150,550,s5,11);
char s6[5];
ZeroMemory( s5, 5 );
sprintf(s6, "血:%d", Tank[0].m_blood);
TextOut(hDC,10,180,s6,5);
*/
// TextOut(hDC,650,550,"吴文捷 于 2007.11.5",19);
}
/****************************************************************
函数名:GameMusic()
用途: 播放游戏音乐和音效
参数: 音乐路径,音乐格式代号(1:MIDI,2:WAV,3:MP3),
播放状态(0:停止,1播放,2:重播)
返回值:
其它:
*****************************************************************/
void MyGame::GameMusic(char *path, short n, short control)
{
/* 用在DS中
if(m_ShowStartScreen){return;}
if(n==1){playmusic.PlayMIDI(g_hwnd,path);}
if(n==2){playmusic.PlayWav(path,false);}
if(control==0){playmusic.Stop();}
if(control==1){}
if(control==2){playmusic.Replay();}
*/
}
/****************************************************************
函数名:SetDevMode()
用途: 设置显示模式
参数:
返回值:
其它:
*****************************************************************/
void MyGame::SetDevMode()
{
/* DX环境中暂时不用
DEVMODE lpDevMode;
lpDevMode.dmBitsPerPel=32;
lpDevMode.dmPelsWidth=SCREEN_W;
lpDevMode.dmPelsHeight=SCREEN_H;
lpDevMode.dmSize=sizeof(lpDevMode);
lpDevMode.dmFields =DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL;
LONG result;
result=ChangeDisplaySettings(&lpDevMode,0);
if (result==DISP_CHANGE_SUCCESSFUL)
{
//AfxMessageBox("修改成功!");
ChangeDisplaySettings(&lpDevMode,0); //使用0表示动态修改//使用CDS_UPDATEREGISTRY表示次修改是持久的,//并在注册表中写入了相关的数据
}
else
{
MessageBox(GetFocus(),"修改失败,恢复原有设置!","窗口关闭!",MB_OK|MB_ICONHAND);
ChangeDisplaySettings(NULL,0); //恢复原有设置
}
*/
}
void MyGame::FreeSpace()
{
delete []tank;
delete []bullete;
}
short MyGame::Rando(short n)
{
short r=rand() % (n+1); //r的范围在0~n间
// if(r==2 || r==5){r=rand() % (n+1);} //减少定时和炸弹的出现几率
return r;
}
short MyGame::EatThingTest(POINT &TankScreenPoint)
{
short kind=0;
RECT RT,rect1,rect2;
rect2.left=TankScreenPoint.x+1;
rect2.top=TankScreenPoint.y+1;
rect2.right=rect2.left+30;
rect2.bottom=rect2.top+30;
for(int i=1;i<11;i++)
{
if(tank[i].things.show)
{
int a=tank[i].things.ScreenXY.x;
int b=tank[i].things.ScreenXY.y;
SetRect(&rect1,a,b,a+23,b+23); //物品矩形范围
if(IntersectRect(&RT,&rect2,&rect1))
{
playsound[7]=true;
kind=tank[i].things.kind;
tank[i].things.show=false; //吃掉了不显示
tank[i].things.LiveTime=0;
//sound!
return kind;
}
}
}
return 0;
}
void MyGame::ChangeTankStyle(int n, short &EatKind)
{
switch (EatKind)
{
case 0:
break;
case 1:
tank[n].MoveSpeed++;
bullete[n].Speed+=2;
break;
case 2:
if(n==0)
{
for(i=1;i<11;i++){tank[i].MoveStop=true;}
}
else{tank[0].MoveStop=true;}
break;
case 3:
if(tank[n].blood<32){tank[n].blood+=8;}
break;
case 4:
tank[n].showrect=true;
break;
case 5:
ddraw.StartDoopTest=true;
ddraw.showdoop=true;
ddraw.setdoop =true;
if(n==0){ddraw.PutDoop=1;}
else{ddraw.PutDoop=2;}
break;
case 6:
tank[n].OnShip=true;
break;
default:
break;
}
}
//DEL void MyGame::SetTimer(int n, short kind)
//DEL {/*
//DEL static int tt;
//DEL if(kind==2)
//DEL {
//DEL tt++;
//DEL if(tt>=10)
//DEL {
//DEL tt=0;
//DEL if(n==0){tank[0].MoveSpeed=2;}
//DEL for(i=1;i<11;i++)
//DEL {
//DEL if(kind==2){tank[i].MoveSpeed=2;}
//DEL tank[i].EatKind=0;
//DEL }
//DEL }
//DEL }
//DEL else{tt=0;}*/
//DEL }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -