📄 game.cpp
字号:
/*==============================================================================
文件: Game.cpp
说明:游戏实现部分
时间:2003-12-06
编写:oshj || oshj@21cn.com
环境:EVC3.0 or Win2000 Pro/SP4/1024*768分辨率
特别说明:仅作学习参考,请勿用于商业目的,转载请保留作者信息
==============================================================================*/
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
//未完成部分:
//1、游戏的BOSS部分(BOSS贴图、BOSS子弹、BOSS爆炸效果)
//2、游戏难度控制,目前比较幼稚
//未解决的BUG:
//1、CE下需要按退出菜单退出,点窗口的关闭按钮进程仍然存在
//------------------------------------------------------------------------------
#include "stdafx.h"
#include "Game.h"
//------------------------------------------------------------------------------
//仅做调试之用!正式时不能有Msg,否则可能陷入死循环
#define Msg(str) MessageBox(GetActiveWindow(),TEXT(str),TEXT("Error"),\
MB_OK|MB_ICONINFORMATION);
//
#define PlaneW 50 //飞机宽度
#define PlaneH 60 //飞机高度
#define PassFoe 100 //过关需要打掉的飞机数
#define PassBlood 100 //过关BOSS的血
//------------------------------------------------------------------------------
extern HWND hWnd;
extern HINSTANCE g_hInst;
extern TCHAR tcAppExePath[MAX_PATH];
extern TCHAR iniFile[256]; //ini文件
//------------------------------------------------------------------------------
#if _WIN32_WCE
const int FOENUM = 8; //敌机总数
#else
const int FOENUM = 16;
#endif
const int BALLNUM = 20; //我机子弹总数
POINT BallPosL[BALLNUM]; //我机左侧子弹位置
POINT BallPosR[BALLNUM]; //我机右侧子弹位置
POINT FoePos[FOENUM]; //敌机位置
int FoeSpeed[FOENUM]; //敌机速度
int FoeWay[FOENUM]; //敌机方向
int FoeType[FOENUM]; //敌机是子弹还是飞机
int FoeDead[FOENUM]; //敌机是否已死
POINT FoeBlastPos[FOENUM]; //敌机爆炸位置
int FoeBlastType[FOENUM]; //敌机爆炸火焰状态
POINT BlastPos; //我机爆炸时的火焰位置
int BlastTpye = 0; //我机爆炸火焰状态
//------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
//构造
CGame::CGame()
{
#if _WIN32_WCE
;
#else
wcscpy(m_MidiOpen,TEXT("play "));
wcscat(m_MidiOpen,tcAppExePath);
wcscat(m_MidiOpen,TEXT("Q11\\北国之春.mid "));
wcscpy(m_MidiClose,TEXT("close "));
wcscat(m_MidiClose,tcAppExePath);
wcscat(m_MidiClose,TEXT("Q11\\北国之春.mid"));
//播放midi
char buf[256];
mciSendString(m_MidiOpen,buf,sizeof(buf),NULL);
#endif
movespeed = 0;
}
//------------------------------------------------------------------------------
//析构
CGame::~CGame()
{
#if _WIN32_WCE
;
#else
//关闭midi
char buf[256];
mciSendString(m_MidiClose,buf,sizeof(buf),NULL);
#endif
CGameFree();
}
//------------------------------------------------------------------------------
//释放资源,这个函数名字有点怪,排在一起容易看,哈哈
void CGame::CGameFree()
{
if(NULL != g_hScoreDC)
DeleteDC(g_hScoreDC);
if(NULL != g_hMapDC)
DeleteDC(g_hMapDC);
if(NULL != g_hBomDC)
DeleteDC(g_hBomDC);
if(NULL != g_hBufDC)
DeleteDC(g_hBufDC);
if(NULL != g_hPlaDC)
DeleteDC(g_hPlaDC);
if(NULL != g_hBalDC[0])
DeleteDC(g_hBalDC[0]);
if(NULL != g_hBalDC[1])
DeleteDC(g_hBalDC[1]);
if(NULL != g_hBusDC)
DeleteDC(g_hBusDC);
if(NULL != g_hFoePlaDC[0])
DeleteDC(g_hFoePlaDC[0]);
if(NULL != g_hFoePlaDC[1])
DeleteDC(g_hFoePlaDC[1]);
if(NULL != g_hFoeBalDC[0])
DeleteDC(g_hFoeBalDC[0]);
if(NULL != g_hFoeBalDC[1])
DeleteDC(g_hFoeBalDC[1]);
if(NULL != g_hFoeBusDC)
DeleteDC(g_hFoeBusDC);
if(NULL != g_hFoeBossDC)
DeleteDC(g_hFoeBossDC);
if(NULL != g_hFoeBossBalDC)
DeleteDC(g_hFoeBossBalDC);
if(NULL != m_pFoeBossBalPos)
{
m_pFoeBossBalPos = NULL;
delete [] m_pFoeBossBalPos;
}
if(NULL != m_iFoeBossBalWay)
{
m_iFoeBossBalWay = NULL;
delete [] m_iFoeBossBalWay;
}
if(NULL != m_iFoeBossBalSpeed)
{
m_iFoeBossBalSpeed = NULL;
delete [] m_iFoeBossBalSpeed;
}
}
//------------------------------------------------------------------------------
//初始化
void CGame::InitGame()
{
m_iGameStatus = 0;
m_iTotalPlane = 0;
m_iFoeDead = 0;
m_iLevel = 1; //缺省从第1关开始
m_bResetGame = FALSE;
static BOOL bFirst = TRUE ;
HDC hDC = GetDC(hWnd);
HBITMAP hBitMap = NULL;
if( TRUE == bFirst)
{
g_hBufDC = CreateCompatibleDC(hDC);
g_hMapDC = CreateCompatibleDC(hDC);
g_hPlaDC = CreateCompatibleDC(hDC);
g_hBusDC = CreateCompatibleDC(hDC); //我机爆炸火焰
g_hBomDC = CreateCompatibleDC(hDC); //我机雷
g_hBalDC[0] = CreateCompatibleDC(hDC); //我机子弹1
g_hBalDC[1] = CreateCompatibleDC(hDC); //我机子弹2
g_hFoePlaDC[0] = CreateCompatibleDC(hDC); //敌机1
g_hFoeBalDC[0] = CreateCompatibleDC(hDC); //敌机子弹1
g_hFoePlaDC[1] = CreateCompatibleDC(hDC); //敌机2
g_hFoeBalDC[1] = CreateCompatibleDC(hDC); //敌机子弹2
g_hFoeBusDC = CreateCompatibleDC(hDC); //敌机爆炸火焰
g_hFoeBossDC = CreateCompatibleDC(hDC); //敌机BOSS
g_hFoeBossBalDC = CreateCompatibleDC(hDC); //敌机BOSS临时子弹
g_hScoreDC = CreateCompatibleDC(hDC); //后台信息
TCHAR tcTempFile[MAX_PATH]={'\0'};
//Buffer
wcscpy(tcTempFile,tcAppExePath);
#if _WIN32_WCE
wcscat(tcTempFile,TEXT("Q11\\buf24.bmp"));
#else
wcscat(tcTempFile,TEXT("Q11\\bufPC.bmp"));
#endif
hBitMap = SHLoadDIBitmap(tcTempFile);
//仅做调试之用!正式时不能有Msg,否则可能陷入死循环
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hBufDC,hBitMap);
//MAP
//wcscpy(tcTempFile,tcAppExePath);
//wcscat(tcTempFile,TEXT("Q11\\map.bmp"));
//hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
//SelectObject(g_hMapDC,hBitMap);
//我机
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\center.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hPlaDC,hBitMap);
//我机炸弹
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\thunder.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hBomDC,hBitMap);
//我机子弹 //双排子弹PDA处理上会迟缓一些
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\ball.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hBalDC[0],hBitMap);
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\ball.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hBalDC[1],hBitMap);
//我机爆炸火焰
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\dead.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hBusDC,hBitMap);
//敌机1
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\foe1.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hFoePlaDC[0],hBitMap);
//敌机子弹1
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\ball1.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hFoeBalDC[0],hBitMap);
//敌机2
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\foe2.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hFoePlaDC[1],hBitMap);
//敌机子弹2
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\ball2.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hFoeBalDC[1],hBitMap);
//敌机爆炸火焰
wcscpy(tcTempFile,tcAppExePath);
wcscat(tcTempFile,TEXT("Q11\\dead.bmp"));
hBitMap = SHLoadDIBitmap(tcTempFile);
//if(NULL == hBitMap)
// Msg("加载位图失败!");
SelectObject(g_hFoeBusDC,hBitMap);
PlayCopyright();
}
bFirst = FALSE;
DeleteObject(hBitMap);
ReleaseDC(hWnd,hDC);
hDC = NULL;
///////////////////////////////////////////////////////////////////////////
VOpen();
}
//------------------------------------------------------------------------------
//重置所有游戏参数
void CGame::ResetAll()
{
LoadFromIni();
//如果是打通关重新开始的
if(3 == m_iGameStatus)
{
//重置相关参数
m_iTotalPlane = 0;
m_iFoeDead = 0;
m_iLevel = 1;
m_bResetGame = FALSE;
//奖励两个雷(是不是有点小气了?)
m_iBomb = m_iniBombSel + 2;
}
else
{
if(m_iLevel>5)
m_iLevel = 1;
m_iBomb = m_iniBombSel;
}
m_iReMain = 4;
switch(m_iniLevel)
{
case 0:
m_iBossTotalBalNum = 4;
break;
case 1:
m_iBossTotalBalNum = 6;
break;
case 2:
m_iBossTotalBalNum = 8;
break;
case 3:
m_iBossTotalBalNum = 10;
break;
}
//记得重置!
m_iGameStatus = 1;
m_iBallNum = 0;
m_iBossBallNum = 0;
m_iFoeTotalDead = 0;
m_bSeeBoss = FALSE;
m_bNewReset = FALSE;
m_bCanControl = FALSE;
for (int k=0; k<FOENUM; k++)
FoeDead[k]=0;
#if _WIN32_WCE
if(movespeed<m_iLevel)
movespeed = 5; //初始移动速度
#else
if(movespeed<m_iLevel)
movespeed = 1;
#endif
m_pFoeBossPos.x=m_pFoeBossPos.y=0; //BOSS位置
m_iFoeBossSpeed = 0; //BOSS速度
m_iFoeBossType = 0; //是BOSS还是BOSS放的子弹
//释放上一关分配的内存
if(NULL != m_pFoeBossBalPos)
{
m_pFoeBossBalPos = NULL;
delete [] m_pFoeBossBalPos;
}
if(NULL != m_iFoeBossBalWay)
{
m_iFoeBossBalWay = NULL;
delete [] m_iFoeBossBalWay;
}
if(NULL != m_iFoeBossBalSpeed)
{
m_iFoeBossBalSpeed = NULL;
delete [] m_iFoeBossBalSpeed;
}
m_pFoeBossBalPos = new POINT[m_iBossTotalBalNum];
m_iFoeBossBalWay = new int[m_iBossTotalBalNum];
m_iFoeBossBalSpeed = new int[m_iBossTotalBalNum];
m_bBossBalClr = TRUE;
m_iBossBalClr = 0;
}
//------------------------------------------------------------------------------
//播放片头
void CGame::PlayCopyright()
{
HDC hDC = GetDC(hWnd);
HBITMAP hBitMap = NULL;
BITMAP bitmap;
RECT rect;
TCHAR tcWaveFile[MAX_PATH]={'\0'};
wcscpy(tcWaveFile,tcAppExePath);
wcscat(tcWaveFile,TEXT("Q11\\pass.wav"));
PlaySound (tcWaveFile,NULL,SND_FILENAME|SND_ASYNC);
hBitMap = LoadBitmap(g_hInst,MAKEINTRESOURCE(IDB_WSDEMO));
//if(NULL == hBitMap)
// Msg("加载位图失败!");
GetObject(hBitMap,sizeof(BITMAP),&bitmap);
if( NULL == hDC)
hDC = GetDC(GetActiveWindow());
HDC hStartDC = CreateCompatibleDC(hDC);
SelectObject(hStartDC,hBitMap);
GetClientRect(GetActiveWindow(),&rect);
rect.left = (rect.right - rect.left) / 2 - 25;
rect.top = (rect.bottom - rect.top) / 2 - 80;
rect.right = rect.left + 50;
rect.bottom = rect.top + 168;
//播放片头
for (int m=0;m<20;m++)
{
for(int b=0;b<4;b++)
{
StretchBlt(hDC,rect.left,rect.top,
(rect.right - rect.left),
(rect.bottom - rect.top),
hStartDC,0,0,
bitmap.bmWidth,
bitmap.bmHeight,
SRCCOPY);
rect.left -= 1;
rect.right += 1;
::Sleep(10);
}
rect.top -= 1;
rect.bottom += 1;
}
DeleteObject(hBitMap);
DeleteDC(hStartDC);
ReleaseDC(hWnd,hDC);
hDC = NULL;
#if _WIN32_WCE
Sleep(1000);
#else
Sleep(1500);
#endif
}
//------------------------------------------------------------------------------
//开始
void CGame::StartGame()
{
if(1 == m_iGameStatus)
return;
ResetAll();
if(FALSE == m_bResetGame)
PassLevel();
}
//------------------------------------------------------------------------------
//填充一个RECT结构
void CGame::GetRect(RECT* rect, long left, long top, long width, long height)
{
rect->left = left;
rect->top = top;
rect->right = left+width;
rect->bottom = top+height;
return;
}
//------------------------------------------------------------------------------
//开火
void CGame::Fire()
{
#if _WIN32_WCE
PlaySound(MAKEINTRESOURCE(IDR_WAVE_SHOT),g_hInst,SND_RESOURCE|SND_ASYNC); //子弹声效
#endif
static int newtime,oldtime = GetTickCount();
newtime = GetTickCount();
if (newtime > oldtime+100)
{
oldtime = newtime;
BallPosL[m_iBallNum].x = pos.x + 10;
BallPosL[m_iBallNum].y = pos.y;
BallPosR[m_iBallNum].x = pos.x + 35;
BallPosR[m_iBallNum].y = pos.y;
m_iBallNum ++;
if (m_iBallNum == BALLNUM)
m_iBallNum = 0;
}
}
//------------------------------------------------------------------------------
//画地图
void CGame::DrawMap()
{
//背景贴图的偏移坐标
static int mapposX=64, mapposY=64;
mapposX--;
if (mapposX<=0 ) mapposX=64;
if (mapposY<=0) mapposY=64;
if (mapposY>64) mapposY=1;
for (int x=0; x<=(int)ScreenW/64; x++)
{
for (int y=0; y<=(int)ScreenH/64; y++)
{
RECT rect;
GetRect(&rect, 64*x-mapposY, 64*y-mapposX, 64, 64);
BitBlt(g_hBufDC,rect.left,rect.top,ScreenW,ScreenH,g_hMapDC,0,0,SRCCOPY);
}
}
}
//------------------------------------------------------------------------------
//画我机
void CGame::DrawPlane()
{
static int iPlaneNumber;
static unsigned int oldtime=0;
if (iPlaneNumber != m_iReMain)
{
oldtime = GetTickCount();
iPlaneNumber = m_iReMain;
m_bNewReset = TRUE;
m_bCanControl = FALSE;
pos.x = ScreenW/2 - 25;
pos.y = ScreenH;
}
if (TRUE == m_bNewReset)
{
if (GetTickCount()>oldtime+3000) //重新初始化,无敌时间3秒
{
m_iBomb = 4;
m_bNewReset = FALSE;
}
}
if (FALSE == m_bCanControl)
{
if (pos.y > ScreenH - 100) //飞机刚出现不受控制
pos.y -= movespeed;
else
m_bCanControl = TRUE;
}
else
{
//检测方向键
//#if _WIN32_WCE
//mousemove point
//#else
if(GetAsyncKeyState(m_iniUp)) {pos.y=pos.y-movespeed;}
if(GetAsyncKeyState(m_iniDown)) {pos.y=pos.y+movespeed;}
if(GetAsyncKeyState(m_iniLeft)) {pos.x=pos.x-movespeed;}
if(GetAsyncKeyState(m_iniRight)) {pos.x=pos.x+movespeed;}
//#endif
//范围检查
if (pos.x < 0)
pos.x = 0;
if (pos.x > (ScreenW - PlaneW)) //飞机图片宽度
pos.x = ScreenW - PlaneW;
if (pos.y < PlaneH - 26)
pos.y = PlaneH - 26;
if (pos.y > (ScreenH-PlaneH - 26)) //菜单条宽度
pos.y = ScreenH-PlaneH - 26;
}
if (TRUE == m_bNewReset) //无敌时的闪烁效果
{
static int ot=0; //延时
if (GetTickCount()-ot > 30)
ot = GetTickCount();
else
return;
}
//绘制飞机
RECT rect;
GetRect(&rect, pos.x, pos.y, 50, 60);
BitBlt(g_hBufDC,rect.left,rect.top,ScreenW,ScreenH,g_hPlaDC,0,0,SRCINVERT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -