飞机大战游戏源码
程序员文章站
2022-06-21 10:46:41
...
大家好,我是业余写来玩玩的,写不好的地方不要取笑哦!
自定义头文件WinMain.h源码
#include <Windows.h>
#include<list>
#include<time.h>
#include<ctime>
#include "resource.h"
#include "resource1.h"
#include <gdiplus.h>
#include <mmsystem.h>
#pragma comment(lib,"gdiplus.lib")
#pragma comment(lib,"Msimg32.lib")
#pragma comment(lib,"Winmm.lib")
using namespace Gdiplus;
using namespace std;
#define CLIENTWIDTH 400
#define CLIENTHEIGHT 600
#define TIMERID_1 10 //定时器ID
#define TIMERID_2 20 //定时器ID
#define GAMEFRAME 180 //游戏帧
#define VE_NPCONE 1 //一号敌机速度
#define VE_NPCTWO 1 //二号敌机速度
#define VE_NPCTRE 1 //三号敌机速度
#define MENU_ITEM_WIDTH 120 //菜单宽度
#define MENU_ITEM_HEIGHT 40 //菜单高度
#define RATIO 0.1 //碰撞矩形系数
enum GAMESCENE//游戏场景
{
SCENE_START,
SCENE_PLAY,
SCENE_OVER
};
enum ENEMYTYPE//敌机类型
{
NPCONE,
NPCTWO,
NPCTRE,
SUPNPCONE
};
enum BULLETTYPE//子弹类型
{
BULLETONE,
BULLETTWO
};
enum MENUTYPE
{
SETFOCUS,
KILLFOCUS
};
enum AWARD
{
AWARDONE,
AWARDTWO
};
HBITMAP hBitmap_start, hBitmap_play, hBitmap_over;
HBITMAP hBitmap_npc1, hBitmap_npc2, hBitmap_npc3, hBitmap_player, hBitmap_bullet1, hBitmap_bullet2, hBitmap_supnpc1, hBitmap_award1, hBitmap_award2, hBitmap_bomb;
GAMESCENE curScene;//游戏场景
Point point;//记录玩家飞机轨迹
Rect PlayerCollisionRect;
int player_xPos, player_yPos;//玩家位置
int collision_maxY, collision_minY, collision_maxX, collision_minX;//玩家碰撞检测
int index;//玩家爆炸动画
bool death;//玩家死亡
bool isdeath;//玩家被撞击
int flag, flag_bullet;//指向生成敌机类型
bool upgrade;//子弹升级
int upgrade_num;//二级子弹数量
bool Bomb;//炸弹
int Bomb_num;//炸弹数量
clock_t tmp;
void GameInit();//初始化
void LoadImg();//加载位图
void GamePaint(HDC hdc);//游戏界面重绘
void ReleaseRes();//释放资源
void DelImage();//删除位图资源
void MouseClick(int x,int y,HWND hwnd);//鼠标点击事件
void DrawStartOver(HDC hdc, HBITMAP hBmp);//重绘开始结束场景
void DrawPlay(HDC hdc);//重绘玩游戏场景
void GameLogic();//游戏逻辑帧
void DrawMenu(HDC hdc, RectF rect, MENUTYPE type, PTCHAR text);//输出菜单
void CreateNpc(HBITMAP hbmp);//生成敌机
void CreateBullet(HBITMAP hbmp);//生成敌机
void IsHit();//子弹是否击中敌机
void IsFocus(int x, int y);//是否获得焦点
void CreateAward(HBITMAP hbmp);//生成奖励
bool isCollsionWithRect(Rect rect1, Rect rect2);//碰撞检测
void CreateBomb(HBITMAP hbmp);//生成炸弹
void BigBang();//飞机爆炸声
void LoadSound();//加载音频
void CloseSound();//关闭音频
void Update(HDC hdc, HDC hdcMem, HDC hdcMemTemp, BLENDFUNCTION dc_bf);//游戏画面帧
class EnemyPlane //敌机类
{
private:
public:
double PosX;
double PosY;
int Blood;
int collision_maxY, collision_minY, collision_maxX, collision_minX;
int index;
bool isdeath;
bool death;
Rect ColRect;
HBITMAP Type;
ENEMYTYPE enemyType;
EnemyPlane(HBITMAP h)
{
Type = h;
if (h == hBitmap_npc1)
{
enemyType = NPCONE;
Blood = 2;
index = 0;
isdeath = death = false;
}
if (h == hBitmap_npc2)
{
enemyType = NPCTWO;
Blood = 6;
index = 0;
isdeath = death = false;
}
if (h == hBitmap_npc3)
{
enemyType = NPCTRE;
PosY = -245;
Blood = 20;
index = 0;
isdeath = death = false;
}
if (h == hBitmap_supnpc1)
{
enemyType = SUPNPCONE;
Blood = 3;
index = 0;
isdeath = death = false;
}
}
void CollsionRect(HBITMAP Type, Rect &ColRect)//碰撞矩形
{
BITMAP bmp;
GetObject(Type, sizeof(BITMAP), &bmp);
ColRect.X = PosX + bmp.bmWidth/4*RATIO;
ColRect.Y = PosY + bmp.bmHeight*RATIO;
ColRect.Width = bmp.bmWidth/4 - bmp.bmWidth/4*RATIO*2;
ColRect.Height = bmp.bmHeight - bmp.bmHeight*RATIO*2;
}
double Vel()//返回敌机速度
{
switch (enemyType)
{
case NPCONE:
return 4;
break;
case NPCTWO:
return 1;
break;
case NPCTRE:
return 0.5;
break;
case SUPNPCONE:
return 2;
break;
default:
break;
}
}
};
list <EnemyPlane> npcList;//储存敌机实例链表
list <EnemyPlane>::iterator iter_npc;//迭代器访问链表
class Bullet //子弹类
{
private:
public:
int PosX;
int PosY;
int velocity = 20;
int tmp;//子弹碰撞点偏移距离
Rect ColRect;
HBITMAP Type;
BULLETTYPE bulletType;
Bullet(HBITMAP h)
{
Type = h;
if (h == hBitmap_bullet1)
{
bulletType = BULLETONE;
}
if (h == hBitmap_bullet2)
{
bulletType = BULLETTWO;
}
}
void CollsionRect(HBITMAP Type, Rect &ColRect)
{
BITMAP bmp;
GetObject(Type, sizeof(BITMAP), &bmp);
ColRect.X = PosX + bmp.bmWidth*RATIO;
ColRect.Y = PosY + bmp.bmHeight*RATIO;
ColRect.Width = bmp.bmWidth - bmp.bmWidth*RATIO*2;
ColRect.Height = bmp.bmHeight - bmp.bmHeight*RATIO*2;
}
};
list <Bullet> bulletList;//储存子弹实例链表
list <Bullet>::iterator iter_bullet;
class Menu//菜单类
{
public:
RectF rect;
MENUTYPE menuType = KILLFOCUS;
PTCHAR menuText;
Menu(int x, int y, PTCHAR text)
{
rect.X = x;
rect.Y = y;
rect.Width = MENU_ITEM_WIDTH;
rect.Height = MENU_ITEM_HEIGHT;
menuText = text;
};
private:
};
list <Menu> menuList_Start;
list <Menu> menuList_End;
list <Menu>::iterator iter_menu;
class Award//奖励类
{
public:
double PosX;
double PosY;
double velocity = 0.8;
Rect ColRect;
HBITMAP Type;
AWARD awardType;
Award(HBITMAP h)
{
Type = h;
if (h == hBitmap_award1)
{
awardType = AWARDONE;
}
if (h == hBitmap_award2)
{
awardType = AWARDTWO;
}
}
void CollsionRect(HBITMAP Type, Rect &ColRect)
{
BITMAP bmp;
GetObject(Type, sizeof(BITMAP), &bmp);
ColRect.X = PosX + bmp.bmWidth*RATIO;
ColRect.Y = PosY + bmp.bmHeight*RATIO;
ColRect.Width = bmp.bmWidth - bmp.bmWidth*RATIO*2;
ColRect.Height = bmp.bmHeight - bmp.bmHeight*RATIO*2;
}
private:
};
list <Award> awardList;//储存奖励实例链表
list <Award>::iterator iter_award;
class Bomb_//炸弹类
{
public:
int PosX;
int PosY;
HBITMAP Type;
Bomb_(HBITMAP h)
{
PosX = 0;
PosY = CLIENTHEIGHT - 36;
Type = h;
}
private:
};
list <Bomb_> bombList;//储存炸弹实例链表
list <Bomb_>::iterator iter_bomb;
主程序源文件WinMain.cpp源码
#include"WinMain.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//第1个参数,是消息要传递的窗口,参数2是消息的id(也就是这是个什么样的消息,比如鼠标左键按下对应的消息是WM_LBUTTONDOWN),参数3和参数4是消息的具体内容
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szWndClassName[] = TEXT("hellowin");
HWND hwnd;//窗口句柄
MSG msg;//消息类型
WNDCLASS wndclass;//窗口类
//GDI+初始化
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
wndclass.style = CS_HREDRAW | CS_VREDRAW;//窗口的风格,这里两个参数的意思是水平和垂直方向改变时重绘窗口
wndclass.lpfnWndProc = WndProc;//窗口过程
wndclass.cbClsExtra = 0;//额外分配的内存
wndclass.cbWndExtra = 0;//额外分配的内存
wndclass.hInstance = hInstance;//实例句柄
wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));//设置图标,使用自定义图标第一个参数为实例句柄,第二个参数调用MAKEINTRESOURCE(图标ID)
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//设置鼠标样式
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//设置背景
wndclass.lpszMenuName = NULL;//设置菜单
wndclass.lpszClassName = szWndClassName;//窗口类名
if (!RegisterClass(&wndclass))//注册窗口类
{
MessageBox(NULL, L"注册失败", L"错误", MB_ICONERROR);
return 0;
}
int cxScreen = GetSystemMetrics(SM_CXSCREEN);//获取屏幕宽度
int cyScreen = GetSystemMetrics(SM_CYSCREEN);//获取屏幕高度
RECT rc;//定义工作区域矩形
rc.left = (cxScreen - CLIENTWIDTH) / 2;//工作区左上点x坐标
rc.top = (cyScreen - CLIENTHEIGHT) / 2;//工作区左上点y坐标
rc.right = rc.left + CLIENTWIDTH;//工作区右下点x坐标
rc.bottom = rc.top + CLIENTHEIGHT;//工作区右下点y坐标
//执行完此函数后rc返回的是整个窗口矩形
AdjustWindowRect(&rc, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE);
hwnd = CreateWindow(
szWndClassName,//窗口类名,指定基于哪个窗口类
L"飞机大战",//窗口标题
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,//窗口样式
rc.left,//设置窗口左上相对屏幕的x坐标
rc.top,//设置窗口左上相对屏幕的y坐标
rc.right - rc.left,//设置窗口大小
rc.bottom - rc.top,//设置窗口大小
NULL,//父窗口句柄
NULL,//菜单句柄
hInstance,//实例句柄
NULL//分配的额外参数
);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))//消息队列
{
TranslateMessage(&msg);//转向消息
DispatchMessage(&msg);//传递消息
}
GdiplusShutdown(gdiplusToken);//关闭GDI+
return msg.wParam;//此语句将发送WM_QUIT消息,接收此消息窗口关闭
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)//窗口过程函数
{
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE://窗口加载时执行此case
GameInit();
return 0;
case WM_LBUTTONDOWN:
point.X = LOWORD(lParam);
point.Y = HIWORD(lParam);
MouseClick(point.X, point.Y, hwnd);
return 0;
case WM_MOUSEMOVE:
if (curScene == SCENE_START)
{
IsFocus(LOWORD(lParam), HIWORD(lParam));
}
else if (curScene == SCENE_PLAY)
{
if (WM_LBUTTONDOWN&wParam)
{
int dx = LOWORD(lParam) - point.X;
int dy = HIWORD(lParam) - point.Y;
player_xPos += dx;
player_yPos += dy;
point.X = LOWORD(lParam);
point.Y = HIWORD(lParam);
PlayerCollisionRect.X = player_xPos + 20;
PlayerCollisionRect.Width = 60;
PlayerCollisionRect.Y = player_yPos + 20;
PlayerCollisionRect.Height = 80;
}
}
else if (curScene == SCENE_OVER)
{
IsFocus(LOWORD(lParam), HIWORD(lParam));
}
return 0;
case WM_TIMER://定时器周期事件
switch (wParam)
{
case TIMERID_1:
GameLogic();
InvalidateRect(hwnd, NULL, FALSE);//-------------------使得界面重绘-------------------
break;
case TIMERID_2:
if (curScene == SCENE_PLAY)
{
flag++;
if (flag % 6 == 0)
{
CreateNpc(hBitmap_npc2);
}
else if (flag % 15 == 0)
{
CreateNpc(hBitmap_npc3);
mciSendString(L"play big_spaceship_flying from 0", NULL, 0, NULL);
}
else if (flag % 11 == 0)
{
CreateAward(hBitmap_award2);
}
else if (flag % 23 == 0 && Bomb == false)
{
CreateAward(hBitmap_award1);
}
else
{
CreateNpc(hBitmap_npc1);
}
if (clock() - tmp > 3000)//3秒生成一架supnpc1
{
tmp = clock();
CreateNpc(hBitmap_supnpc1);
}
}
if (flag == 500)
{
flag = 0;
}
break;
default:
break;
}
return 0;
case WM_PAINT://窗口必须重绘时执行此case
hdc = BeginPaint(hwnd, &ps);//返回设备描述表句柄
GamePaint(hdc);
EndPaint(hwnd, &ps);
return 0;
case WM_ERASEBKGND:
return 0;
case WM_SETFOCUS://程序获得焦点
SetTimer(hwnd, TIMERID_1, 1000 / GAMEFRAME, NULL);//设置定时器,游戏主要逻辑执行间隔
SetTimer(hwnd, TIMERID_2, 1000, NULL);//设置定时器,敌机生成间隔
return 0;
case WM_KILLFOCUS://程序失去焦点
KillTimer(hwnd, TIMERID_1);//关闭定时器
KillTimer(hwnd, TIMERID_2);//关闭定时器
return 0;
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE) //劫持关闭按钮消息
{
if (IDCANCEL == MessageBox(hwnd, L"你确定要退出吗?",
L"", MB_OKCANCEL | MB_ICONQUESTION))
{
return 0;
}
}
break;
case WM_DESTROY://窗口关闭时执行此case
ReleaseRes();
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void GameInit()
{
srand(time(NULL));
LoadImg();
LoadSound();
curScene = SCENE_START;
Menu menu_Start = Menu((CLIENTWIDTH - MENU_ITEM_WIDTH) / 2, (CLIENTHEIGHT - MENU_ITEM_HEIGHT) / 2, L"开始游戏");
menuList_Start.push_front(menu_Start);
Menu menu_Exit = Menu((CLIENTWIDTH - MENU_ITEM_WIDTH) / 2, (CLIENTHEIGHT - MENU_ITEM_HEIGHT) / 2 + 40, L"退出游戏");
menuList_Start.push_front(menu_Exit);
Menu menu_RePlay = Menu((CLIENTWIDTH - MENU_ITEM_WIDTH) / 2, (CLIENTHEIGHT - MENU_ITEM_HEIGHT) / 2, L"重新开始");
menuList_End.push_front(menu_RePlay);
Menu menu_End = Menu((CLIENTWIDTH - MENU_ITEM_WIDTH) / 2, (CLIENTHEIGHT - MENU_ITEM_HEIGHT) / 2 + 40, L"结束游戏");
menuList_End.push_front(menu_End);
player_xPos = 150;
player_yPos = 400;
death = false;
upgrade = false;
upgrade_num = 0;
Bomb = false;
Bomb_num = 0;
flag = 0;
index = 0;
}
void LoadImg()
{
//Bitmap* pBmp = Bitmap::FromResource(GetModuleHandle(NULL), (const WCHAR*)MAKEINTRESOURCE(IDB_BITMAP1));
Bitmap* pBmp = Bitmap::FromFile(L".\\image\\img\\first.png");
pBmp->GetHBITMAP(NULL, &hBitmap_start);
pBmp = Bitmap::FromFile(L".\\image\\img\\back.png");
pBmp->GetHBITMAP(NULL, &hBitmap_play);
pBmp = Bitmap::FromFile(L".\\image\\img\\over.png");
pBmp->GetHBITMAP(NULL, &hBitmap_over);
pBmp = Bitmap::FromFile(L".\\image\\img\\npc1.png");
pBmp->GetHBITMAP(NULL, &hBitmap_npc1);
pBmp = Bitmap::FromFile(L".\\image\\img\\npc2.png");
pBmp->GetHBITMAP(NULL, &hBitmap_npc2);
pBmp = Bitmap::FromFile(L".\\image\\img\\npc3.png");
pBmp->GetHBITMAP(NULL, &hBitmap_npc3);
pBmp = Bitmap::FromFile(L".\\image\\img\\player.png");
pBmp->GetHBITMAP(NULL, &hBitmap_player);
pBmp = Bitmap::FromFile(L".\\image\\img\\bullet1.png");
pBmp->GetHBITMAP(NULL, &hBitmap_bullet1);
pBmp = Bitmap::FromFile(L".\\image\\img\\bullet2.png");
pBmp->GetHBITMAP(NULL, &hBitmap_bullet2);
pBmp = Bitmap::FromFile(L".\\image\\img\\npc1.png");
pBmp->GetHBITMAP(NULL, &hBitmap_supnpc1);
pBmp = Bitmap::FromFile(L".\\image\\img\\award1.png");
pBmp->GetHBITMAP(NULL, &hBitmap_award1);
pBmp = Bitmap::FromFile(L".\\image\\img\\award2.png");
pBmp->GetHBITMAP(NULL, &hBitmap_award2);
pBmp = Bitmap::FromFile(L".\\image\\img\\bomb.png");
pBmp->GetHBITMAP(NULL, &hBitmap_bomb);
delete pBmp;
pBmp = NULL;
//hBitmap = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1));
}
void LoadSound()
{
mciSendString(L"open .\\image\\sound\\backmusic.wav alias backmusic", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\get_double_laser.wav alias get_double_laser", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\get_bomb.wav alias get_bomb", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\use_bomb.wav alias use_bomb", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\enemy1_down.wav alias enemy1_down", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\enemy2_down.wav alias enemy2_down", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\enemy3_down.wav alias enemy3_down", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\game_over.wav alias game_over", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\big_spaceship_flying.wav alias big_spaceship_flying", NULL, 0, NULL);
mciSendString(L"open .\\image\\sound\\bullet.wav alias bulletmusic", NULL, 0, NULL);
}
void GamePaint(HDC hdc)
{
switch (curScene)
{
case SCENE_START:
DrawStartOver(hdc, hBitmap_start);
break;
case SCENE_PLAY:
DrawPlay(hdc);
break;
case SCENE_OVER:
DrawStartOver(hdc, hBitmap_over);
break;
default:
break;
}
}
void DrawStartOver(HDC hdc, HBITMAP h)
{
//双缓冲贴图会增加几个步骤
//1.1、创建与设备DC兼容的内存DC
HDC hdcMem = CreateCompatibleDC(hdc);
//1.1、创建与设备DC兼容的内存DC并关联画布
HBITMAP hBmp = CreateCompatibleBitmap(hdc, CLIENTWIDTH, CLIENTHEIGHT);
SelectObject(hdcMem, hBmp);
//1.2、创建与DC兼容的临时内存DC
HDC hdcMemTemp = CreateCompatibleDC(hdc);
//2、将位图对象选进临时内存DC中
SelectObject(hdcMemTemp, h);
//3.1、将临时内存中的位图贴到内存上
BitBlt(hdcMem, 0, 0, CLIENTWIDTH, CLIENTHEIGHT, hdcMemTemp, 0, 0, SRCCOPY);
switch (curScene)
{
case SCENE_START:
for (iter_menu = menuList_Start.begin(); iter_menu != menuList_Start.end(); iter_menu++)
{
DrawMenu(hdcMem, iter_menu->rect, iter_menu->menuType, iter_menu->menuText);//画菜单
}
break;
case SCENE_PLAY:
break;
case SCENE_OVER:
for (iter_menu = menuList_End.begin();iter_menu != menuList_End.end();iter_menu++)
{
DrawMenu(hdcMem, iter_menu->rect, iter_menu->menuType, iter_menu->menuText);//画菜单
}
break;
default:
break;
}
//3.2、将内存中的位图贴到屏幕上
BitBlt(hdc, 0, 0, CLIENTWIDTH, CLIENTHEIGHT, hdcMem, 0, 0, SRCCOPY);
//4、释放内存DC
DeleteObject(hBmp);//删除位图对象,即释放资源。
DeleteDC(hdcMemTemp);
DeleteDC(hdcMem);
//5、删除位图对象,即释放资源。放在程序结尾,关闭gdi+前
}
void Update(HDC hdc, HDC hdcMem, HDC hdcMemTemp, BLENDFUNCTION dc_bf)
{
for (iter_npc = npcList.begin(); iter_npc != npcList.end(); iter_npc++)
{
////2、将位图对象选进临时内存DC中
SelectObject(hdcMemTemp, iter_npc->Type);
switch (iter_npc->enemyType)
{
case NPCONE:
////3.1、将临时内存中的位图贴到内存上
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 50, 40, hdcMemTemp, iter_npc->index * 50, 0, 50, 40, dc_bf);
break;
case NPCTWO:
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 75, 95, hdcMemTemp, iter_npc->index * 75, 0, 75, 95, dc_bf);
break;
case NPCTRE:
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 170, 245, hdcMemTemp, iter_npc->index * 170, 0, 170, 245, dc_bf);
break;
case SUPNPCONE:
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 50, 40, hdcMemTemp, iter_npc->index * 50, 0, 50, 40, dc_bf);
break;
default:
break;
}
}
SelectObject(hdcMemTemp, hBitmap_player);
AlphaBlend(hdcMem, player_xPos, player_yPos, 100, 120, hdcMemTemp, index * 100, 0, 100, 120, dc_bf);
for (iter_bullet = bulletList.begin(); iter_bullet != bulletList.end(); iter_bullet++)
{
SelectObject(hdcMemTemp, iter_bullet->Type);
switch (iter_bullet->bulletType)
{
case BULLETONE:
AlphaBlend(hdcMem, iter_bullet->PosX, iter_bullet->PosY, 6, 14, hdcMemTemp, 0, 0, 6, 14, dc_bf);
break;
case BULLETTWO:
AlphaBlend(hdcMem, iter_bullet->PosX, iter_bullet->PosY, 24, 14, hdcMemTemp, 0, 0, 24, 14, dc_bf);
break;
default:
break;
}
}
for (iter_award = awardList.begin(); iter_award != awardList.end(); iter_award++)
{
SelectObject(hdcMemTemp, iter_award->Type);
AlphaBlend(hdcMem, iter_award->PosX, iter_award->PosY, 65, 90, hdcMemTemp, 0, 0, 65, 90, dc_bf);
}
for (iter_bomb = bombList.begin(); iter_bomb != bombList.end(); iter_bomb++)
{
SelectObject(hdcMemTemp, iter_bomb->Type);
AlphaBlend(hdcMem, iter_bomb->PosX, iter_bomb->PosY, 42, 36, hdcMemTemp, 0, 0, 42, 36, dc_bf);
}
//3.2、将内存中的位图贴到屏幕上
BitBlt(hdc, 0, 0, CLIENTWIDTH, CLIENTHEIGHT, hdcMem, 0, 0, SRCCOPY);
}
/*1.只在WM_ERASEBKGND消息里处理画图部分, 不要在wm_pain中, 窗口刷新快点
2.用双缓冲, 且内存DC不要释放, 下次接着用, 真没办法再重建立内存DC
3.改变画图策略, 不要什么都在画图部分实现.*/
void DrawPlay(HDC hdc)
{
//双缓冲贴图会增加几个步骤
//1.1、创建与设备DC兼容的内存DC
HDC hdcMem = CreateCompatibleDC(hdc);
//1.1、创建与设备DC兼容的内存DC并关联画布
HBITMAP hBmp = CreateCompatibleBitmap(hdc, CLIENTWIDTH, CLIENTHEIGHT);
SelectObject(hdcMem, hBmp);
//1.2、创建与DC兼容的临时内存DC
HDC hdcMemTemp = CreateCompatibleDC(hdc);
//2、将位图对象选进临时内存DC中
SelectObject(hdcMemTemp, hBitmap_play);
//3.1、将临时内存中的位图贴到内存上
BitBlt(hdcMem, 0, 0, CLIENTWIDTH, CLIENTHEIGHT, hdcMemTemp, 0, 0, SRCCOPY);
//此方法贴png透明度图片
BLENDFUNCTION dc_bf = { AC_SRC_OVER ,0,250,AC_SRC_ALPHA };
//dc_bf.BlendOp = AC_SRC_OVER;
//dc_bf.BlendFlags = 0;
//dc_bf.SourceConstantAlpha = 250; //0全透明,255不透明
//dc_bf.AlphaFormat = AC_SRC_ALPHA;
//Update(hdc, hdcMem, hdcMemTemp,dc_bf);
for (iter_npc = npcList.begin(); iter_npc != npcList.end(); iter_npc++)
{
////2、将位图对象选进临时内存DC中
SelectObject(hdcMemTemp, iter_npc->Type);
switch (iter_npc->enemyType)
{
case NPCONE:
////3.1、将临时内存中的位图贴到内存上
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 50, 40, hdcMemTemp, iter_npc->index * 50, 0, 50, 40, dc_bf);
break;
case NPCTWO:
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 75, 95, hdcMemTemp, iter_npc->index * 75, 0, 75, 95, dc_bf);
break;
case NPCTRE:
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 170, 245, hdcMemTemp, iter_npc->index * 170, 0, 170, 245, dc_bf);
break;
case SUPNPCONE:
AlphaBlend(hdcMem, iter_npc->PosX, iter_npc->PosY, 50, 40, hdcMemTemp, iter_npc->index * 50, 0, 50, 40, dc_bf);
break;
default:
break;
}
}
SelectObject(hdcMemTemp, hBitmap_player);
AlphaBlend(hdcMem, player_xPos, player_yPos, 100, 120, hdcMemTemp, index * 100, 0, 100, 120, dc_bf);
for (iter_bullet = bulletList.begin(); iter_bullet != bulletList.end(); iter_bullet++)
{
SelectObject(hdcMemTemp, iter_bullet->Type);
switch (iter_bullet->bulletType)
{
case BULLETONE:
AlphaBlend(hdcMem, iter_bullet->PosX, iter_bullet->PosY, 6, 14, hdcMemTemp, 0, 0, 6, 14, dc_bf);
break;
case BULLETTWO:
AlphaBlend(hdcMem, iter_bullet->PosX, iter_bullet->PosY, 24, 14, hdcMemTemp, 0, 0, 24, 14, dc_bf);
break;
default:
break;
}
}
for (iter_award = awardList.begin(); iter_award != awardList.end(); iter_award++)
{
SelectObject(hdcMemTemp, iter_award->Type);
AlphaBlend(hdcMem, iter_award->PosX, iter_award->PosY, 65, 90, hdcMemTemp, 0, 0, 65, 90, dc_bf);
}
for (iter_bomb = bombList.begin(); iter_bomb != bombList.end(); iter_bomb++)
{
SelectObject(hdcMemTemp, iter_bomb->Type);
AlphaBlend(hdcMem, iter_bomb->PosX, iter_bomb->PosY, 42, 36, hdcMemTemp, 0, 0, 42, 36, dc_bf);
}
//3.2、将内存中的位图贴到屏幕上
BitBlt(hdc, 0, 0, CLIENTWIDTH, CLIENTHEIGHT, hdcMem, 0, 0, SRCCOPY);
//4、释放内存DC
DeleteObject(hBmp);//删除位图对象,即释放资源。
DeleteDC(hdcMemTemp);
DeleteDC(hdcMem);
//5、删除位图对象,即释放资源。放在程序结尾,关闭gdi+前
}
void DrawMenu(HDC hdc, RectF rect, MENUTYPE type, PTCHAR text)
{
Color fontColor;
switch (type)
{
case SETFOCUS:
fontColor = Color::Red;
break;
case KILLFOCUS:
fontColor = Color::White;
default:
break;
}
Graphics graph(hdc);
FontFamily fontFamily(L"黑体");
Font font(&fontFamily, 17, FontStyleBold, UnitPoint);
StringFormat format;
format.SetAlignment(StringAlignmentCenter);
format.SetLineAlignment(StringAlignmentCenter);
SolidBrush brush(fontColor);
graph.SetTextRenderingHint(TextRenderingHintAntiAlias);
graph.DrawString(text, (INT)wcslen(text), &font, rect, &format, &brush);
graph.ReleaseHDC(hdc);
}
void CreateNpc(HBITMAP hbmp)
{
BITMAP bmp;
GetObject(hbmp, sizeof(BITMAP), &bmp);
EnemyPlane npc = EnemyPlane(hbmp);
npc.PosX = rand() % (CLIENTWIDTH - bmp.bmWidth / 4);
npcList.push_front(npc);
}
void CreateBullet(HBITMAP hbmp)
{
BITMAP bmp;
GetObject(hbmp, sizeof(BITMAP), &bmp);
Bullet bullet = Bullet(hbmp);
bullet.PosX = player_xPos + ((100 - bmp.bmWidth) / 2);
bullet.PosY = player_yPos - bmp.bmHeight;
bulletList.push_front(bullet);
mciSendString(L"play bulletmusic from 0", NULL, 0, NULL);
}
void CreateAward(HBITMAP hbmp)
{
BITMAP bmp;
GetObject(hbmp, sizeof(BITMAP), &bmp);
Award award = Award(hbmp);
award.PosX = rand() % (CLIENTWIDTH - bmp.bmWidth);
awardList.push_front(award);
}
void CreateBomb(HBITMAP hbmp)
{
Bomb_ bomb = Bomb_(hbmp);
bombList.push_front(bomb);
}
void IsHit()
{
for (iter_npc = npcList.begin();iter_npc != npcList.end();iter_npc++)
{
for (iter_bullet = bulletList.begin();iter_bullet != bulletList.end();)
{
if (isCollsionWithRect(iter_npc->ColRect, iter_bullet->ColRect))
{
iter_npc->Blood--;
iter_bullet = bulletList.erase(iter_bullet);
if (iter_npc->Blood <= 0)
{
iter_npc->isdeath = true;
mciSendString(L"play enemy3_down from 0", NULL, 0, NULL);
}
}
else
{
iter_bullet++;
}
}
if (isCollsionWithRect(iter_npc->ColRect, PlayerCollisionRect))
{
isdeath = true;
mciSendString(L"play game_over from 0", NULL, 0, NULL);
}
}
for (iter_award = awardList.begin();iter_award != awardList.end();)
{
iter_award->CollsionRect(hBitmap_award1, iter_award->ColRect);
if (iter_award->PosY >= CLIENTHEIGHT)
{
iter_award = awardList.erase(iter_award);
}
else if (upgrade == true && iter_award->awardType == AWARDTWO)
{
iter_award = awardList.erase(iter_award);
}
else if (Bomb == true && iter_award->awardType == AWARDONE)
{
iter_award = awardList.erase(iter_award);
}
else if (isCollsionWithRect(iter_award->ColRect, PlayerCollisionRect))
{
switch (iter_award->awardType)
{
case AWARDONE:
mciSendString(L"play get_bomb from 0", NULL, 0, NULL);
Bomb = true;
Bomb_num++;
iter_award++;
break;
case AWARDTWO:
mciSendString(L"play get_double_laser from 0", NULL, 0, NULL);
upgrade = true;
iter_award++;
break;
default:
break;
}
}
else
{
iter_award->PosY += iter_award->velocity;
iter_award++;
}
}
}
bool isCollsionWithRect(Rect rect1, Rect rect2)
{
if (rect1.X >= rect2.X && rect1.X >= rect2.X + rect2.Width) {
return FALSE;
}
else if (rect1.X <= rect2.X && rect1.X + rect1.Width <= rect2.X) {
return FALSE;
}
else if (rect1.Y >= rect2.Y && rect1.Y >= rect2.Y + rect2.Height) {
return FALSE;
}
else if (rect1.Y <= rect2.Y && rect1.Y + rect1.Height <= rect2.Y) {
return FALSE;
}
return TRUE;
}
void GameLogic()
{
if (curScene == SCENE_PLAY)
{
flag_bullet++;
if (flag_bullet == 8)
{
flag_bullet = 0;
if (upgrade)
{
upgrade_num++;
CreateBullet(hBitmap_bullet2);
if (upgrade_num == 50)
{
upgrade_num = 0;
upgrade = false;
}
}
else
{
CreateBullet(hBitmap_bullet1);
}
if (Bomb)
{
CreateBomb(hBitmap_bomb);
}
}
for (iter_npc = npcList.begin();iter_npc != npcList.end();)
{
switch (iter_npc->enemyType)
{
case NPCONE:
case SUPNPCONE:
iter_npc->CollsionRect(hBitmap_npc1, iter_npc->ColRect);
break;
case NPCTWO:
iter_npc->CollsionRect(hBitmap_npc2, iter_npc->ColRect);
break;
case NPCTRE:
iter_npc->CollsionRect(hBitmap_npc3, iter_npc->ColRect);
break;
default:
break;
}
if (iter_npc->isdeath)
{
iter_npc->index++;
if (iter_npc->index > 3)
{
iter_npc->death = true;
}
}
if (iter_npc->PosY >= CLIENTHEIGHT || iter_npc->death)
{
iter_npc = npcList.erase(iter_npc);
}
else
{
iter_npc->PosY += iter_npc->Vel();
iter_npc++;
}
}
for (iter_bullet = bulletList.begin();iter_bullet != bulletList.end();)
{
switch (iter_bullet->bulletType)
{
case BULLETONE:
iter_bullet->CollsionRect(hBitmap_bullet1, iter_bullet->ColRect);
break;
case BULLETTWO:
iter_bullet->CollsionRect(hBitmap_bullet2, iter_bullet->ColRect);
break;
default:
break;
}
if (iter_bullet->PosY <= 0)
{
iter_bullet = bulletList.erase(iter_bullet);
}
else
{
iter_bullet->PosY -= iter_bullet->velocity;
iter_bullet++;
}
}
IsHit();
if (isdeath)
{
index++;
if (index >= 4)
{
death = true;
mciSendString(L"stop backmusic", NULL, 0, NULL);
}
}
if (death)
{
bulletList.clear();
npcList.clear();
curScene = SCENE_OVER;
}
}
}
void ReleaseRes()
{
DelImage();
CloseSound();
}
void DelImage()//删除位图对象
{
DeleteObject(hBitmap_start);
DeleteObject(hBitmap_play);
DeleteObject(hBitmap_over);
DeleteObject(hBitmap_npc1);
DeleteObject(hBitmap_npc2);
DeleteObject(hBitmap_npc3);
DeleteObject(hBitmap_supnpc1);
DeleteObject(hBitmap_player);
DeleteObject(hBitmap_bullet1);
DeleteObject(hBitmap_bullet2);
DeleteObject(hBitmap_award1);
DeleteObject(hBitmap_award2);
DeleteObject(hBitmap_bomb);
}
void CloseSound()
{
mciSendString(L"close bulletmusic", NULL, 0, NULL);
mciSendString(L"close backmusic", NULL, 0, NULL);
mciSendString(L"close get_double_laser", NULL, 0, NULL);
mciSendString(L"close get_bomb", NULL, 0, NULL);
mciSendString(L"close use_bomb", NULL, 0, NULL);
mciSendString(L"close enemy1_down", NULL, 0, NULL);
mciSendString(L"close enemy2_down", NULL, 0, NULL);
mciSendString(L"close enemy3_down", NULL, 0, NULL);
mciSendString(L"close game_over", NULL, 0, NULL);
mciSendString(L"close big_spaceship_flying", NULL, 0, NULL);
}
void MouseClick(int x, int y, HWND hwnd)
{
switch (curScene)
{
case SCENE_START:
for (iter_menu = menuList_Start.begin();iter_menu != menuList_Start.end();iter_menu++)
{
if (iter_menu->menuText == L"开始游戏"&&iter_menu->menuType == SETFOCUS)
{
curScene = SCENE_PLAY;
tmp = clock();
mciSendString(L"play backmusic from 0", NULL, 0, NULL);
}
else if (iter_menu->menuText == L"退出游戏"&&iter_menu->menuType == SETFOCUS)
{
SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
}
}
case SCENE_OVER:
for (iter_menu = menuList_End.begin();iter_menu != menuList_End.end();iter_menu++)
{
if (iter_menu->menuText == L"重新开始"&&iter_menu->menuType == SETFOCUS)
{
curScene = SCENE_PLAY;
tmp = clock();
mciSendString(L"play backmusic from 0", NULL, 0, NULL);
player_xPos = 150;
player_yPos = 400;
death = false;
isdeath = false;
upgrade = false;
upgrade_num = 0;
Bomb = false;
Bomb_num = 0;
flag = 0;
index = 0;
bombList.clear();
}
else if (iter_menu->menuText == L"结束游戏"&&iter_menu->menuType == SETFOCUS)
{
SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
}
}
break;
case SCENE_PLAY:
if (x < 42 && y > 564 && Bomb == true)
{
bombList.clear();
Bomb = false;
BigBang();
}
break;
default:
break;
}
}
void BigBang()
{
for (iter_npc = npcList.begin();iter_npc != npcList.end();iter_npc++)
{
iter_npc->isdeath = true;
}
mciSendString(L"play use_bomb from 0", NULL, 0, NULL);
}
void IsFocus(int x, int y)
{
switch (curScene)
{
case SCENE_START:
for (iter_menu = menuList_Start.begin();iter_menu != menuList_Start.end();iter_menu++)
{
if (x > iter_menu->rect.X && x < iter_menu->rect.X + MENU_ITEM_WIDTH
&& iter_menu->rect.Y < y && iter_menu->rect.Y + MENU_ITEM_HEIGHT > y)
{
iter_menu->menuType = SETFOCUS;
}
else
{
iter_menu->menuType = KILLFOCUS;
}
}
case SCENE_OVER:
for (iter_menu = menuList_End.begin();iter_menu != menuList_End.end();iter_menu++)
{
if (x > iter_menu->rect.X && x < iter_menu->rect.X + MENU_ITEM_WIDTH
&& iter_menu->rect.Y < y && iter_menu->rect.Y + MENU_ITEM_HEIGHT > y)
{
iter_menu->menuType = SETFOCUS;
}
else
{
iter_menu->menuType = KILLFOCUS;
}
}
}
}
至此完啦,希望各位大牛指点
上一篇: 移动端页面
下一篇: Caffe2源码理解系列之IO
推荐阅读