⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game.cpp

📁 一款不错的飞机模拟游戏
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*==============================================================================
文件: 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 + -