📄 xinvader.cpp
字号:
//
// Programed by Johnhans (C)2002 All Rights Reserved!
//
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
#include "MD_Engine.h"
#include "MD_Surface.h"
#include "MD_Input.h"
#include "MD_Audio.h"
#include "MD_Sound.h"
#include "MD_Timer.h"
#include "MD_File.h"
#include "XInvader.h"
#include "resource.h"
//--------------------------------------------------------------------
// 宏定义
//--------------------------------------------------------------------
#define NAME "XInvader"
#define G_MENU 0
#define G_RUN 1
#define G_CREDITS 2
#define G_HELP 3
#define G_GAMEOVER 4
#define G_LEVEL 5
#define SAFE_DELETE(A) if( (A) != NULL ) { delete [] (A); (A) = NULL; }
//-----------------------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------------------
CMD_Engine Engine;
CMD_Surface sur_menu;
CMD_Surface sur_bkgnd;
CMD_Surface sur_Alphabet;
CMD_Surface sur_Extras;
CMD_Surface sur_Ship;
CMD_Surface sur_Ufo[3];
CMD_Surface *sur_UfoN;
CMD_Surface sur_Bullet;
CMD_Input Input;
CMD_Timer Timer;
CMD_Timer TimerTP;
CMD_Audio Audio;
CMD_Sound snd_stop;
CMD_Sound snd_sel;
CMD_Sound snd_sfire;
CMD_Sound snd_ufire;
CMD_Sound snd_explode;
CMD_Sound snd_extra;
CMD_Sound snd_gameover;
CMD_Sound snd_level;
BOOL bActive; // 程序是否挂起
bool RunGame=true; // 程序运行中
BYTE m_State=G_MENU; // 游戏状态
Bullet m_Bullet[MAX_BULLET];
UFO m_UFO[MAX_UFO];
Extra m_Extra[MAX_EXTRA];
unsigned int iScore = 0; // 得分
int iShipPos = 285; // 飞船位置X
int iShipMov = 0; // 飞船移动量
int iShipframe = 0; // 当前飞船动画帧
int iWeapon = 0; // 当前武器
int iMaxWeapon = 5; // 可用武器
int iLaserAmmo = 100; // Laser 剩余弹药
int iPhotonAmmo = 0; // Photon 剩余弹药
int iShield = 10; // 剩余防护层
int iAttack = 0; // 额外攻击力
int iLevel = 0; // 当前关数
int ShootChance = 0; // 敌人开火几率
int inc = 0;
void DrawFPS();
bool InitEngine(HWND hWnd); // 初始化引擎设备
void InitLevel();
void UpdateFrame();
void ShowMenu();
void ShowCredits();
void ShowHelp();
void DrawBkgnd();
void DrawStatus();
void DrawShip();
void DrawBullet();
bool DrawUFO();
bool DrawExtra();
void ProcessInput();
void HitTest();
//-----------------------------------------------------------------------------
// Name: WindowProc()
// Desc: 主窗口消息处理
//-----------------------------------------------------------------------------
LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_ACTIVATE: //应用程序激活消息
if(LOWORD(wParam)==WA_INACTIVE)
bActive = false;
else if(HIWORD(wParam))
{
bActive = false;
return 0;
}
else
bActive = true;
return 0;
case WM_SYSKEYDOWN:
switch(wParam)
{
case VK_F4:
RunGame=false;
break;
case VK_RETURN:
Engine.ChangeDisplayMode(Engine.GetScreenSize()->cx,Engine.GetScreenSize()->cy,!Engine.IsFullScreen());
break;
case 18:
return 0;
}
break;
case WM_SETCURSOR:
if(Engine.IsFullScreen())
SetCursor(NULL);
else
SetCursor(LoadCursor(NULL, IDC_ARROW));
return TRUE;
case WM_SIZE:
case WM_MOVE:
Engine.CalcWindowPos();
break;
case WM_KEYDOWN: //击键消息
switch( wParam )
{
case VK_F1:
Engine.ChangeDisplayMode(Engine.GetScreenSize()->cx,Engine.GetScreenSize()->cy,!Engine.IsFullScreen());
break;
case VK_F12:
{
static int index=1;
char str[20];
sprintf(str,"ScreenShot%d.bmp",index++);
Engine.SaveScreen(str);
}
break;
}
break;
case WM_DESTROY: //销毁窗口消息
PostQuitMessage(0);
RunGame=false;
break;
}
//调用缺省的过程处理过程
return DefWindowProc(hWnd, message, wParam, lParam);
}
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: 初始化, 消息循环
//-----------------------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wcex={0};
//建立并注册窗口类
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WinProc;
wcex.hInstance=hInstance;
wcex.lpszClassName = NAME;
wcex.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_XINVADER));
RegisterClassEx(&wcex);
//创建窗口
hWnd = CreateWindowEx(WS_EX_APPWINDOW,NAME,NAME,WS_OVERLAPPEDWINDOW | WS_VISIBLE,0,0,GetSystemMetrics(SM_CXSCREEN)/2,GetSystemMetrics(SM_CYSCREEN)/2,NULL,NULL,hInstance,NULL);
if (!hWnd)
{
UnregisterClass(NAME,hInstance);
MessageBox(hWnd,"程序主框架创建失败!",NAME,MB_OK);
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
if(!InitEngine(hWnd))
{
MessageBox(hWnd,"游戏引擎初始化失败!",NAME,MB_OK);
return false;
}
// Main message loop:
while(RunGame)
{
//如果有消息则截获它
if(PeekMessage(&msg,hWnd,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
RunGame=false;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(bActive)
{
UpdateFrame();
}
}
return msg.wParam;
}
bool InitEngine(HWND hWnd)
{
if(!Engine.Create(hWnd,640,480,16,true))
return false;
CMD_File file;
int len=0;
LPBYTE buf=NULL;
if(!file.Open("xipres.pak",true,true))
return false;
len=file.GetPackFileInfo("xinvader.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"xinvader.bmp"))
return false;
if(!sur_menu.Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("backgnd.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"backgnd.bmp"))
return false;
if(!sur_bkgnd.Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("alphabet.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"alphabet.bmp"))
return false;
if(!sur_Alphabet.Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("extras.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"extras.bmp"))
return false;
if(!sur_Extras.Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("ship.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"ship.bmp"))
return false;
if(!sur_Ship.Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("bullet.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"bullet.bmp"))
return false;
if(!sur_Bullet.Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("ufo1.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"ufo1.bmp"))
return false;
if(!sur_Ufo[0].Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("ufo2.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"ufo2.bmp"))
return false;
if(!sur_Ufo[1].Create(buf,0))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("ufo3.bmp")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"ufo3.bmp"))
return false;
if(!sur_Ufo[2].Create(buf,0))
return false;
SAFE_DELETE(buf);
if(!Input.Create(hWnd,INPUT_KEYBOARD))
return false;
if(!Audio.Create(hWnd))
return false;
if(!file.Open("xisres.pak",true,true))
return false;
len=file.GetPackFileInfo("sel.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"sel.wav"))
return false;
if(!snd_sel.Create(buf,len))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("stop.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"stop.wav"))
return false;
if(!snd_stop.Create(buf,len))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("sfire.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"sfire.wav"))
return false;
if(!snd_sfire.Create(buf,len))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("ufire.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"ufire.wav"))
return false;
if(!snd_ufire.Create(buf,len))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("explode.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"explode.wav"))
return false;
if(!snd_explode.Create(buf,len))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("extras.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"extras.wav"))
return false;
if(!snd_extra.Create(buf,len))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("gameover.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"gameover.wav"))
return false;
if(!snd_gameover.Create(buf,len))
return false;
SAFE_DELETE(buf);
len=file.GetPackFileInfo("level.wav")->length;
buf=new BYTE[len];
if(!file.ReadFromPackage(buf,"level.wav"))
return false;
if(!snd_level.Create(buf,len))
return false;
SAFE_DELETE(buf);
srand(GetTickCount());
return true;
}
void InitLevel()
{
inc=iLevel/6+1; // UFO移动速度, UFO防御力
for(int i=0;i<MAX_BULLET;i++)
{
m_Bullet[i].type=0;
m_Bullet[i].frame=0;
}
for(i=0;i<MAX_UFO;i++)
{
m_UFO[i].type=_UFO_DIED_;
m_UFO[i].shield=inc;
m_UFO[i].inc=inc;
m_UFO[i].frame=rand()%49;
}
for(i=0;i<MAX_EXTRA;i++)
{
m_Extra[i].type=0;
m_Extra[i].frame=rand()%18;
}
sur_UfoN=&sur_Ufo[0];
iShipPos = 285;
iShipMov = 0;
if((ShootChance = 180 - (40 * (iLevel / 7)))<50)
ShootChance = 50;
switch(iLevel%6)
{
case 0:
for(i=0;i<5;i++)
{
m_UFO[i].type=_UFO_1_;
m_UFO[i].move=0;
m_UFO[i].x=550-(abs(i-2)*30);
m_UFO[i].y=(i*65)+10;
}
for(i=5;i<10;i++)
{
m_UFO[i]=m_UFO[i-5];
m_UFO[i].x=640-m_UFO[i-5].x-70;
m_UFO[i].inc=-inc;
}
break;
case 1:
for(i=0;i<5;i++)
{
m_UFO[i].type=_UFO_1_;
m_UFO[i].x=20+i*30;
m_UFO[i].y=(i*65)+10;
m_UFO[i].move=0;
m_UFO[5+i].type=_UFO_1_;
m_UFO[5+i].x=550-i*30;
m_UFO[5+i].y=(i*65)+10;
m_UFO[5+i].move=0;
m_UFO[5+i].inc=-inc;
}
break;
case 2:
for(i=0;i<24;i++)
{
m_UFO[i].type=_UFO_1_;
m_UFO[i].x=5+i%8*80;
m_UFO[i].y=i/8*80+10;
m_UFO[i].move=1;
if((i/8)%2==0)
m_UFO[i].inc=-inc;
}
break;
case 3:
sur_UfoN=&sur_Ufo[1];
for(i=0;i<5;i++)
m_UFO[i].type=_UFO_2_;
m_UFO[0].x=200;
m_UFO[0].y=20;
m_UFO[0].move=6;
m_UFO[1].x=180;
m_UFO[1].y=180;
m_UFO[1].move=6;
m_UFO[2].x=530;
m_UFO[2].y=110;
m_UFO[2].move=5;
m_UFO[3].x=100;
m_UFO[3].y=100;
m_UFO[3].move=6;
m_UFO[4].x=450;
m_UFO[4].y=190;
m_UFO[4].move=5;
break;
case 4:
sur_UfoN=&sur_Ufo[1];
for(i=0;i<6;i++)
m_UFO[i].type=_UFO_2_;
m_UFO[0].x=20;
m_UFO[0].y=20;
m_UFO[0].move=3;
m_UFO[1].x=110;
m_UFO[1].y=90;
m_UFO[1].move=6;
m_UFO[2].x=20;
m_UFO[2].y=160;
m_UFO[2].move=6;
m_UFO[3].x=540;
m_UFO[3].y=20;
m_UFO[3].move=4;
m_UFO[4].x=470;
m_UFO[4].y=90;
m_UFO[4].move=5;
m_UFO[5].x=540;
m_UFO[5].y=160;
m_UFO[5].move=5;
break;
case 5:
sur_UfoN=&sur_Ufo[2];
for(i=0;i<6;i++)
{
m_UFO[i].type=_UFO_3_;
m_UFO[i].move=7;
}
m_UFO[0].x=20;
m_UFO[0].y=20;
m_UFO[1].x=90;
m_UFO[1].y=90;
m_UFO[2].x=20;
m_UFO[2].y=160;
m_UFO[3].x=540;
m_UFO[3].inc=-m_UFO[3].inc;
m_UFO[3].y=20;
m_UFO[4].x=470;
m_UFO[4].y=90;
m_UFO[4].inc=-m_UFO[4].inc;
m_UFO[5].x=540;
m_UFO[5].y=160;
m_UFO[5].inc=-m_UFO[5].inc;
break;
}
iLevel++;
snd_level.Play();
}
void UpdateFrame()
{
static int nt=0,ot=0; //////////////////////////
nt=GetTickCount(); // //
if(nt<ot+18) // 帧速限制50FPS //
return; // //
ot=nt; //////////////////////////
Engine.FlipScreen();
switch(m_State)
{
case G_MENU:
ShowMenu();
break;
case G_RUN:
{
ProcessInput(); // 处理玩家输入
DrawBkgnd(); // 绘制背景
bool a=DrawUFO(); // 绘制敌方UFO
bool b=DrawExtra(); // 绘制物品
DrawBullet(); // 绘制子弹
DrawShip(); // 绘制玩家飞船
DrawStatus(); // 绘制状态
HitTest(); // 撞击测试
if(iShield<=0 && iShipframe>20)
{
m_State=G_GAMEOVER;
Timer.Reset();
TimerTP.Reset();
snd_gameover.Play();
}
if(a && b)
{
InitLevel();
Timer.Reset();
TimerTP.Reset();
m_State=G_LEVEL;
}
}
break;
case G_CREDITS:
ShowCredits();
break;
case G_HELP:
ShowHelp();
break;
case G_LEVEL:
{
char str[10]={'L','E','V','E','L',' '};
str[6]=iLevel/100+'0';
str[7]=iLevel%100/10+'0';
str[8]=iLevel%10+'0';
str[9]='\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -