#include <stdio.h> #include <easyx.h> #include <time.h> #include <Mmsystem.h> #pragma comment(lib,"winmm.lib") #define WIDTH 600 #define HEIGHT 850 #define bullet_max 5000 //我方飞机子弹最大量 #define enemy_bul_max 1500 //敌方飞机子弹最大量 #define enemy1_hp 30 //敌方飞机生命值 #define enemy2_hp 50 #define enemy3_hp 30 #define enemy4_hp 10000 #define enemy5_hp 12000 IMAGE bgimg; //主界面图片 IMAGE bkimg0; IMAGE bkimg1; IMAGE bkimg2; IMAGE bkimg3; IMAGE bkimg4; IMAGE bkimg5; IMAGE Myplane[2]; //飞机图片个数 IMAGE Enemy1[2]; //小飞机 IMAGE Enemy2[2]; //中飞机 IMAGE Enemy2Bullet[2]; //中飞机子弹 IMAGE Enemy3[2]; //横行飞机 IMAGE Enemy3Bullet[2]; //横行飞机子弹 IMAGE Enemy4[2]; //第二关boss IMAGE Enemy4Bullet[2]; //第二关boss子弹 IMAGE Enemy5[2]; //第三关boss IMAGE Enemy5Bullet[2]; //第三关boss子弹 IMAGE Lighter[2]; //飞机大招 IMAGE AntiAddictionNotice; //防沉迷公告 IMAGE HowToPlay; //玩法说明 //加载图片 void loadimg(); //初始化游戏 void initGame(); //加载主界面 void DrawInterface(ExMessage* msg); //绘制游戏 void DrawGame(); //更新背景 void UpdateBack(); //更新飞机 void UpdatePlane(); //绘制子弹 void DrawBullet(); //绘制雷霆 void DrawLighter(); //子弹移动 void MoveBullet(); //雷霆移动 void MoveLighter(); //关卡转换 void level_change(); //失败界面 void FailMenu(); //结束界面 void EndMenu(); //进入每一关的初始分数 void Judge(); //敌机移动机制 void EnemyMove(); //判定子弹碰撞敌机 void Bulletcrush(); //判定大招攻击敌机 void LighterCrush(); //创建敌机 void EnemyCreat_L1(); void EnemyCreat_L2(); void EnemyCreat_L3(); void EnemyCreat_L4(); //敌机清除 void EnemyClean(); //敌机产生子弹 void Enemy_Bullet_Creat(); //敌机子弹移动 void Enemy_Bullet_Move(); //敌机子弹打击 void Enemy_Bullet_Crush(); //碰撞敌机 void EnemyCrush(); //显示分数血量 void Print(); //挑战模式 void ChallengeMode(); //定义音效(用于开启或关闭音效) struct Music { bool isExit; }music; //定义我方飞机类 struct Myplane { int x; int y; int hp; int width = 95; int height = 90; bool isExit; //飞机是否存在 }myplane[1]; IMAGE Bullet[2]; //子弹图片个数 //定义我方飞机子弹类 struct Bullet { int x1; int y1; int x2; int y2; bool isExit; //是否存在 } bullet[bullet_max]; //子弹个数 struct Lighter { int x; int y; bool isExit; }lighter[1]; //定义敌方飞机类 struct Enemyplane { double x; double y; int hp; int width; int height; bool isExit; }enemy1[10], enemy2[5], enemy3[5], enemy4[1], enemy5[1]; //定义敌方飞机子弹类 struct Enemybullet { int x; int y; int hp; int atk; //用于后面判断打击 int width; int height; bool isExit; } enemy2_bullet[enemy_bul_max], enemy3_bullet[enemy_bul_max], enemy4_bullet[enemy_bul_max], enemy5_bullet[enemy_bul_max]; int bky0, bky1, bk1y0, bk1y1, bk2y0, bk2y1, bk3y0, bk3y1; int score = 0; //5000通过第一关,8000分第二关boss出现,12000分进入第三关 int enemy2_direct0 = 1; //用于下面判断敌机向左向右移动 int enemy3_direct0 = 1; int enemy3_direct1 = 0; int enemy3_direct2 = 1; int enemy3_direct3 = 0; int enemy3_direct4 = 1; int enemy4_direct0 = 1; int level_change_count = 1; int flag = 0; int flag1 = 1; int main(); int level() { if (flag == 0) { return 0; } else if (flag == 1) { if (score > 5000 && score < 12000) { return 2;//第二关 } else if (score < 5000) { return 1;//返回第一关 } else if (score > 12000) { return 3;//第三关 } else if (score > 17000) { return 4;//结束界面 } } else if (flag == 2) { return 5; } } void loadimg() { //主界面图片 loadimage(&bgimg, L"bg.jpg"); //关卡背景图片 if (level() == 1) { loadimage(&bkimg0, L"bk.jpg"); } else if (level() == 2) { loadimage(&bkimg1, L"bk1.jpg"); } else if (level() == 3) { loadimage(&bkimg2, L"bk2.jpg"); } else if(level() == 5) { loadimage(&bkimg4, L"bk4.jpg"); } loadimage(&bkimg3, L"bk3.jpg"); loadimage(&bkimg5, L"bk5.jpg"); //我方飞机图片 loadimage(&Myplane[0], L"uiPlane0.jpg"); loadimage(&Myplane[1], L"uiPlane1.jpg"); //加载子弹 loadimage(&Bullet[0], L"bullet0.jpg"); loadimage(&Bullet[1], L"bullet1.jpg"); //敌机1 loadimage(&Enemy1[0], L"enemy10.jpg"); loadimage(&Enemy1[1], L"enemy11.jpg"); //敌机2 loadimage(&Enemy2[0], L"enemy20.jpg"); loadimage(&Enemy2[1], L"enemy21.jpg"); loadimage(&Enemy2Bullet[0], L"enemybullet10.jpg"); loadimage(&Enemy2Bullet[1], L"enemybullet11.jpg"); //敌机3 loadimage(&Enemy3[0], L"enemy10.jpg"); loadimage(&Enemy3[1], L"enemy11.jpg"); loadimage(&Enemy3Bullet[0], L"enemybullet20.jpg"); loadimage(&Enemy3Bullet[1], L"enemybullet21.jpg"); //敌机4 loadimage(&Enemy4[0], L"enemy30.jpg"); loadimage(&Enemy4[1], L"enemy31.jpg"); loadimage(&Enemy4Bullet[0], L"enemybullet40.jpg"); loadimage(&Enemy4Bullet[1], L"enemybullet41.jpg"); //敌机5 loadimage(&Enemy5[0], L"enemy50.jpg"); loadimage(&Enemy5[1], L"enemy51.jpg"); loadimage(&Enemy5Bullet[0], L"enemybullet50.jpg"); loadimage(&Enemy5Bullet[1], L"enemybullet51.jpg"); //飞机大招 loadimage(&Lighter[0], L"lighter0.jpg"); loadimage(&Lighter[1], L"lighter1.jpg"); //加载防沉迷公告页面 loadimage(&AntiAddictionNotice, L"防沉迷公告.jpg"); //加载玩法说明页面 loadimage(&HowToPlay, L"玩法说明.jpg"); } DWORD WINAPI MouseMusic(LPVOID lpVoid) { mciSendString(L"open 鼠标点击.mp3", 0, 0, 0); mciSendString(L"play 鼠标点击.mp3 wait", 0, 0, 0); mciSendString(L"close 鼠标点击.mp3", 0, 0, 0); return 0; //多线程播放音乐 } bool isInRect(ExMessage* msg, int x, int y, int width, int height) { //判断鼠标是否在某个区域 if (msg->x > x && msg->x < x + width && msg->y > y && msg->y < y + height) { return true; } return false; } enum MenuOp { Start, //开始游戏按钮 Challenge, //挑战模式按钮 Description, //玩法说明按钮 AntiNotice, //防沉迷公告 Home, //主菜单 End, End2, Pause, Exit }; enum MenuOp menuState = Home;//开始在主菜单 void DrawInterface(ExMessage* msg) { if (GetAsyncKeyState(VK_LBUTTON)) { CreateThread(0, 0, MouseMusic, 0, 0, 0); switch (menuState) { case Home: //开始游戏按钮 if (isInRect(msg, 141, 539, 305, 80)) { menuState = Start; } //挑战模式按钮 if (isInRect(msg, 141, 635, 303, 80)) { menuState = Challenge; } //玩法说明按钮 if (isInRect(msg, 0, 790, 131, 44)) { menuState = Description; } //防沉迷公告按钮 if (isInRect(msg, 447, 790, 161, 44)) { menuState = AntiNotice; } break; case Start: break; case Challenge: break; case Description: if (isInRect(msg, 473, 806, 125, 42)) menuState = Home; break; case AntiNotice: if (isInRect(msg, 461, 794, 125, 42)) menuState = Home; break; case End: if (isInRect(msg, 32, 798, 126, 45)) { menuState = Home; initGame(); score = 0; } if (isInRect(msg, 453, 800, 126, 45)) { menuState = Exit; } break; case End2: if (isInRect(msg, 32, 798, 126, 45)) { menuState = Home; initGame(); score = 0; } if (isInRect(msg, 453, 800, 126, 45)) { menuState = Exit; } break; case Pause: if (isInRect(msg, 14, 800, 125, 45)) { menuState = Home; initGame(); score = 0; } if (isInRect(msg, 455, 800, 125, 45)) { menuState = Exit; } if (isInRect(msg, 230, 266, 129, 42)) { if (flag1 == 1) { flag = 1; } else if (flag1 == 2) { flag = 2; } } if (isInRect(msg, 225, 125, 129, 42)) { music.isExit = true; } if (isInRect(msg, 230, 195, 129, 42)) { music.isExit = false; } break; } } if (menuState == Home) { putimage(0, 0, &bgimg); } else { if (menuState == Description) { putimage(0, 0, &HowToPlay); } else if (menuState == AntiNotice) { putimage(0, 0, &AntiAddictionNotice); } else if (menuState == Start) { flag = 1; } else if (menuState == Challenge) { flag = 2; } else if (menuState == Exit) { exit(0); } else if (menuState == End) { int x = 10; int y = 20; putimage(0, 0, &bkimg3); TCHAR time_test1[50]; TCHAR time_test2[50]; _stprintf(time_test1, _T("恭喜您!")); _stprintf(time_test2, _T("您的本次得分为:%d"), score); setbkmode(TRANSPARENT); settextstyle(40, 0, L"华文行楷"); outtextxy(x, y, time_test1); outtextxy(x, y + 50, time_test2); } else if (menuState == End2) { int x = 10; int y = 20; putimage(0, 0, &bkimg3); TCHAR time_test1[50]; TCHAR time_test2[50]; TCHAR time_test3[50]; _stprintf(time_test1, _T("许多年以后,")); _stprintf(time_test2, _T("当我再次仰望那片星空")); _stprintf(time_test3, _T("战机的轰鸣声依旧回荡在耳畔...")); setbkmode(TRANSPARENT); settextstyle(40, 0, L"华文行楷"); outtextxy(x, y, time_test1); outtextxy(x, y + 50, time_test2); outtextxy(x, y + 100, time_test3); } else if (menuState == Pause) { putimage(0, 0, &bkimg5); } } } bool Timer(int ms)//定时器 { static DWORD t1 = 0, t2 = 0;//申请静态变量,DWORD实质就是一个无符号长整型类型 if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } bool Timer1(int ms)//定时器 { static DWORD t1 = 0, t2 = 0; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } DWORD WINAPI PlaneFireMusic(LPVOID lpVoid) { if (music.isExit == true) { mciSendString(L"open 发射子弹.mp3", 0, 0, 0); mciSendString(L"play 发射子弹.mp3 wait", 0, 0, 0); mciSendString(L"close 发射子弹.mp3", 0, 0, 0); } return 0; } DWORD WINAPI PlaneLighterMusic(LPVOID lpVoid) { if (music.isExit == true) { mciSendString(L"open 发射大招.mp3", 0, 0, 0); mciSendString(L"play 发射大招.mp3 wait", 0, 0, 0); mciSendString(L"close 发射大招.mp3", 0, 0, 0); } return 0; } DWORD WINAPI Boom(LPVOID lpVoid) { if (music.isExit == true) { mciSendString(L"open 爆炸.mp3", 0, 0, 0); mciSendString(L"play 爆炸.mp3 wait", 0, 0, 0); mciSendString(L"close 爆炸.mp3", 0, 0, 0); } return 0; } void DrawGame() { BeginBatchDraw(); loadimg(); //绘制关卡背景 if (level() == 1) { putimage(0, bky0, &bkimg0); putimage(0, bky1, &bkimg0); } else if (level() == 2) { putimage(0, bk1y0, &bkimg1); putimage(0, bk1y1, &bkimg1); } else if(level() == 3) { putimage(0, bk2y0, &bkimg2); putimage(0, bk2y1, &bkimg2); } else if(level() == 5) { putimage(0, bk3y0, &bkimg4); putimage(0, bk3y1, &bkimg4); } //绘制我方飞机子弹(透明贴图) int i; for (i = 0; i < 1; i++) { if (myplane[i].isExit) //如果飞机存在,则绘制飞机 { putimage(myplane[i].x, myplane[i].y, &Myplane[0], SRCPAINT); putimage(myplane[i].x, myplane[i].y, &Myplane[1], SRCAND); } } for (i = 0; i < bullet_max; i++) { //遍历所有子弹,若子弹存在则贴图 if (bullet[i].isExit) { //SRCPAINT三元光栅操作码(用于实现透明贴图) putimage(bullet[i].x1, bullet[i].y1, &Bullet[0], SRCPAINT); putimage(bullet[i].x1, bullet[i].y1, &Bullet[1], SRCAND); putimage(bullet[i].x2, bullet[i].y2, &Bullet[0], SRCPAINT); putimage(bullet[i].x2, bullet[i].y2, &Bullet[1], SRCAND); } } for (i = 0; i < 10; i++)//敌机1 { if (enemy1[i].isExit) { putimage(enemy1[i].x, enemy1[i].y, &Enemy1[0], SRCPAINT); putimage(enemy1[i].x, enemy1[i].y, &Enemy1[1], SRCAND); } } for (i = 0; i < 5; i++)//敌机2 { if (enemy2[i].isExit) { putimage(enemy2[i].x, enemy2[i].y, &Enemy2[0], SRCPAINT); putimage(enemy2[i].x, enemy2[i].y, &Enemy2[1], SRCAND); } } for (i = 0; i < enemy_bul_max; i++) { if (enemy2_bullet[i].isExit) { putimage(enemy2_bullet[i].x, enemy2_bullet[i].y, &Enemy2Bullet[0], SRCPAINT); putimage(enemy2_bullet[i].x, enemy2_bullet[i].y, &Enemy2Bullet[1], SRCAND); } } for (i = 0; i < 5; i++)//敌机3 { if (enemy3[i].isExit) { putimage(enemy3[i].x, enemy3[i].y, &Enemy3[0], SRCPAINT); putimage(enemy3[i].x, enemy3[i].y, &Enemy3[1], SRCAND); } } for (i = 0; i < enemy_bul_max; i++) { if (enemy3_bullet[i].isExit) { putimage(enemy3_bullet[i].x, enemy3_bullet[i].y, &Enemy3Bullet[0], SRCPAINT); putimage(enemy3_bullet[i].x, enemy3_bullet[i].y, &Enemy3Bullet[1], SRCAND); } } for (i = 0; i < 1; i++) { if (enemy4[i].isExit) { putimage(enemy4[i].x, enemy4[i].y, &Enemy4[0], SRCPAINT); putimage(enemy4[i].x, enemy4[i].y, &Enemy4[1], SRCAND); } } for (i = 0; i < enemy_bul_max; i++) { if (enemy4_bullet[i].isExit) { putimage(enemy4_bullet[i].x, enemy4_bullet[i].y, &Enemy4Bullet[0], SRCPAINT); putimage(enemy4_bullet[i].x, enemy4_bullet[i].y, &Enemy4Bullet[1], SRCAND); } } for (i = 0; i < 1; i++) { if (enemy5[i].isExit) { putimage(enemy5[i].x, enemy5[i].y, &Enemy5[0], SRCPAINT); putimage(enemy5[i].x, enemy5[i].y, &Enemy5[1], SRCAND); } } for (i = 0; i < enemy_bul_max; i++) { if (enemy5_bullet[i].isExit) { putimage(enemy5_bullet[i].x, enemy5_bullet[i].y, &Enemy5Bullet[0], SRCPAINT); putimage(enemy5_bullet[i].x, enemy5_bullet[i].y, &Enemy5Bullet[1], SRCAND); } } for (i = 0; i < 1; i++) { if (lighter[i].isExit) { putimage(lighter[i].x, lighter[i].y, &Lighter[0], SRCPAINT); putimage(lighter[i].x, lighter[i].y, &Lighter[1], SRCAND); } } EndBatchDraw(); } bool Timer_enemycreat(int ms)//定时器 { static DWORD t1 = 0, t2 = 0; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } bool Timer2(int ms)//定时器 { static DWORD t1 = 0, t2 = 0; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } bool Timer_enemy2_bullet_creat(int ms)//定时器 { static DWORD t1 = 0, t2 = 0; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } bool Timer_enemy3_bullet_creat(int ms)//定时器 { static DWORD t1 = 0, t2 = 0; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } bool Timer_enemy4_bullet_creat(int ms)//定时器 { static DWORD t1 = 0, t2 = 0; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } bool Timer_enemy5_bullet_creat(int ms)//定时器 { static DWORD t1 = 0, t2 = 0; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } void EnemyMove() { int i; for (i = 0; i < 10; i++)//最小敌机前进,不发射子弹 { if (enemy1[i].isExit == true)//如果敌机1存在 { enemy1[i].y += 0.5; if (enemy1[i].y > HEIGHT) { enemy1[i].isExit = false;//如果敌机1出界则判定为不存在 } } } for (i = 0; i < 5; i++)//中飞机,缓慢前进,并发射子弹 { if (enemy2[i].isExit == true) { enemy2[i].y += 0.7; if (enemy2[i].y > HEIGHT) { enemy2[i].isExit = false; } } } for (i = 0; i < 5; i++)//横行飞机,左右移动,偶尔前进,并发射子弹 { if (enemy3[i].isExit == true) { if (i == 0)//型号为0的飞机,奇数向左,偶数向右,且先向左 { if (enemy3[i].y < HEIGHT / 2) { enemy3[i].y += 10; } else { if (enemy3_direct0 % 2 == 1) { enemy3[i].x -= 2; if (enemy3[i].x < 0) { enemy3_direct0++; } } if (enemy3_direct0 % 2 == 0) { enemy3[i].x += 2; if (enemy3[i].x + enemy3[i].width > WIDTH) { enemy3_direct0++; } } } } if (i == 1)//型号为1的飞机,奇数向右,偶数向左,且先向右边 { if (enemy3[i].y < HEIGHT / 2)//先移动到画面中 { enemy3[i].y += 10; } else { if (enemy3_direct1 % 2 == 0) { enemy3[i].x -= 2; if (enemy3[i].x < 0) { enemy3_direct1++; } } if (enemy3_direct1 % 2 == 1) { enemy3[i].x += 2; if (enemy3[i].x + enemy3[i].width > WIDTH) { enemy3_direct1++; } } } } if (i == 2)//型号为2的飞机,奇数向左,偶数向右,且先向左 { if (enemy3[i].y < HEIGHT / 2)//先移动到画面中 { enemy3[i].y += 10; } else { if (enemy3_direct2 % 2 == 1) { enemy3[i].x -= 2; if (enemy3[i].x < 0) { enemy3_direct2++; } } if (enemy3_direct2 % 2 == 0) { enemy3[i].x += 2; if (enemy3[i].x + enemy3[i].width > WIDTH) { enemy3_direct2++; } } } } if (i == 3)//型号为3的飞机,奇数向右,偶数向左,且先向右边 { if (enemy3[i].y < HEIGHT / 2)//先移动到画面中 { enemy3[i].y += 10; } else { if (enemy3_direct3 % 2 == 0) { enemy3[i].x -= 2; if (enemy3[i].x < 0) { enemy3_direct3++; } } if (enemy3_direct3 % 2 == 1) { enemy3[i].x += 2; if (enemy3[i].x + enemy3[i].width > WIDTH) { enemy3_direct3++; } } } } if (i == 4)//型号为4的飞机,奇数向左,偶数向右,且先向左 { if (enemy3[i].y < HEIGHT / 2)//先移动到画面中 { enemy3[i].y += 10; } else { if (enemy3_direct4 % 2 == 1) { enemy3[i].x -= 2; if (enemy3[i].x < 0) { enemy3_direct4++; } } if (enemy3_direct4 % 2 == 0) { enemy3[i].x += 2; if (enemy3[i].x + enemy3[i].width > WIDTH) { enemy3_direct4++; } } } } if (enemy3[i].y < -3) { enemy3[i].isExit = false; } } } for (i = 0; i < 1; i++) { if (enemy4[i].isExit) { if (enemy4_direct0 % 2 == 1)//奇数向左,偶数向右且先向左 { enemy4[i].x -= 1; if (enemy4[i].x < 0) { enemy4_direct0++; } } if (enemy4_direct0 % 2 == 0) { enemy4[i].x += 1; if (enemy4[i].x + enemy4[i].width > WIDTH) { enemy4_direct0++; } } } } } void EnemyClean() { //主要用于产生BOSS前,将其他飞机和子弹清除 int i; for (i = 0; i < 10; i++)//敌机1,遍历所有敌机位,若敌机存在则清除 { if (enemy1[i].isExit == true) { enemy1[i].isExit = false; } } for (i = 0; i < 5; i++)//敌机2 { if (enemy2[i].isExit == true) { enemy2[i].isExit = false; } } for (i = 0; i < 5; i++)//敌机3 { if (enemy3[i].isExit == true) { enemy3[i].isExit = false; } } for (i = 0; i < enemy_bul_max; i++)//遍历所有子弹位,若子弹存在则清除 { if (enemy2_bullet[i].isExit == true) { enemy2_bullet[i].isExit = false; } if (enemy3_bullet[i].isExit == true) { enemy3_bullet[i].isExit = false; } if (enemy4_bullet[i].isExit == true) { enemy4_bullet[i].isExit = false; } } for (i = 0; i < 1; i++) { if (lighter[i].isExit == true) lighter[i].isExit = false; } } void EnemyCreat_L1() { int i, j; int count1 = 0, count2 = 0; if (Timer_enemycreat(5000)) { if (level() == 1) { for (i = 0; i < 10; i++)//敌机1 { if (enemy1[i].isExit == false) { enemy1[i].isExit = true; enemy1[i].x = rand() % (WIDTH - 60); enemy1[i].y = 0; enemy1[i].hp = 30; count1++; if (count1 == 2)//每个循环产生3次敌机 { count1 = 0; break; } } } for (j = 0; j < 5; j++)//敌机2 { if (enemy2[j].isExit == false) { enemy2[j].isExit = true; enemy2[j].hp = 50; enemy2[j].x = rand() % (WIDTH - 60); enemy2[j].y = 0; count2++; if (count2 == 1)//每个循环产生2次敌机 { count2 = 0; break; } } } if (score > 2500) { for (j = 0; j < 5; j++)//敌机3 { if (enemy3[j].isExit == false) { enemy3[j].isExit = true; enemy3[j].hp = 30; enemy3[j].x = rand() % (WIDTH - 60); enemy3[j].y = 0; break;//每个循环只产生1次敌机 } } } } } } void EnemyCreat_L2() { int i, j; if (Timer_enemycreat(3000)) { if (level() == 2) { if (score > 5000 && score <= 8000) { for (i = 0; i < 10; i++)//敌机1 { if (enemy1[i].isExit == false) { enemy1[i].isExit = true; enemy1[i].x = rand() % (WIDTH - 60); enemy1[i].y = 0; enemy1[i].hp = 30; break; } } for (j = 0; j < 5; j++)//敌机2 { if (enemy2[j].isExit == false) { enemy2[j].isExit = true; enemy2[j].hp = 50; enemy2[j].x = rand() % (WIDTH - 60); enemy2[j].y = 0; break; } } for (j = 0; j < 5; j++)//敌机3 { if (enemy3[j].isExit == false) { enemy3[j].isExit = true; enemy3[j].hp = 50; enemy3[j].x = -enemy3[j].width * 1.5; enemy3[j].y = 0; break; } } } if (score > 8000) { EnemyClean();//boss出现时清理其他的所有的飞机 for (j = 0; j < 1; j++) { if (enemy4[j].isExit == false) { enemy4[j].isExit = true; enemy4[j].hp = 10000; enemy4[j].x = WIDTH / 2 - enemy4[j].width / 2; enemy4[j].y = 0; break; } } } } } } void EnemyCreat_L3() { EnemyClean(); int j; if (level() == 3) { if (score < 17000); { for (j = 0; j < 1; j++) { if (enemy5[j].isExit == false) { enemy5[j].isExit = true; enemy5[j].hp = 12000; enemy5[j].x = WIDTH / 2 - enemy5[j].width / 2; enemy5[j].y = 0; break; } } } } } void EnemyCreat_L4() { int i, j; int count1 = 0, count2 = 0; if (Timer_enemycreat(3000)) { if (level() == 5) { for (i = 0; i < 10; i++)//敌机1 { if (enemy1[i].isExit == false) { enemy1[i].isExit = true; enemy1[i].x = rand() % (WIDTH - 60); enemy1[i].y = 0; enemy1[i].hp = 30; count1++; if (count1 == 2)//每个循环产生3次敌机 { count1 = 0; break; } } } for (j = 0; j < 5; j++)//敌机2 { if (enemy2[j].isExit == false) { enemy2[j].isExit = true; enemy2[j].hp = 50; enemy2[j].x = rand() % (WIDTH - 60); enemy2[j].y = 0; count2++; if (count2 == 1)//每个循环产生2次敌机 { count2 = 0; break; } } } for (j = 0; j < 5; j++)//敌机3 { if (enemy3[j].isExit == false) { enemy3[j].isExit = true; enemy3[j].hp = 50; enemy3[j].x = -enemy3[j].width * 1.5; enemy3[j].y = 0; break; } } } } } void Enemy_Bullet_Creat() { int i, j; if (Timer_enemy2_bullet_creat(3000))//子弹发射频率 { for (j = 0; j < 5; j++) { for (i = 0; i < enemy_bul_max; i++) { if (enemy2_bullet[i].isExit == false && enemy2[j].isExit == true) { enemy2_bullet[i].isExit = true; enemy2_bullet[i].x = enemy2[j].x + enemy2[j].width / 2.0 ; enemy2_bullet[i].y = enemy2[j].y; break; } } } } if (Timer_enemy3_bullet_creat(2000)) { for (j = 0; j < 3; j++) { for (i = 0; i < enemy_bul_max; i++) { if (enemy3_bullet[i].isExit == false && enemy3[j].isExit == true) { enemy3_bullet[i].isExit = true; enemy3_bullet[i].x = enemy3[j].x + enemy3[j].width / 2.0; enemy3_bullet[i].y = enemy3[j].y; break; } } } } int count4 = 1;//boss两侧发射子弹 if (Timer_enemy4_bullet_creat(100)) { for (j = 0; j < 1; j++) { for (i = 0; i < enemy_bul_max; i++) { if (enemy4_bullet[i].isExit == false && enemy4[j].isExit == true) { enemy4_bullet[i].isExit = true; if (count4 == 1)//每次循环先左侧发射一次 { enemy4_bullet[i].x = enemy4[j].x + 38; enemy4_bullet[i].y = enemy4[j].y + 37; count4 += 1; continue; } if (count4 == 2)//再右侧发射一次 { count4 = 1; enemy4_bullet[i].x = enemy4[j].x + enemy4[j].width - 73; enemy4_bullet[i].y = enemy4[j].y + 37; break; } } } } } int count5 = 1; if (Timer_enemy5_bullet_creat(200)) { for (j = 0; j < 1; j++) { for (i = 0; i < enemy_bul_max; i++) { if (enemy5_bullet[i].isExit == false && enemy5[j].isExit == true) { enemy5_bullet[i].isExit = true; if (count5 == 1) { enemy5_bullet[i].x = enemy5[j].x + 155; enemy5_bullet[i].y = enemy5[j].y + 360; count5 += 1; continue; } if (count5 == 2) { count5 = 1; enemy5_bullet[i].x = enemy5[j].x + enemy5[j].width - 175; enemy5_bullet[i].y = enemy5[j].y + 360; break; } } } } } } void Enemy_Bullet_Move() { int i; //敌机2 for (i = 0; i < enemy_bul_max; i++) { if (enemy2_bullet[i].isExit == true) { enemy2_bullet[i].y += rand() % 2 + 2; if (enemy2_bullet[i].y < 0) { enemy2_bullet[i].isExit = false; } } } //敌机3 for (i = 0; i < enemy_bul_max; i++) { if (enemy3_bullet[i].isExit == true) { enemy3_bullet[i].y += rand() % 3 + 3; if (enemy3_bullet[i].y < 0) { enemy3_bullet[i].isExit = false; } } } //敌机4 for (i = 0; i < enemy_bul_max; i++) { if (enemy4_bullet[i].isExit == true) { enemy4_bullet[i].y += 8; if (enemy4_bullet[i].y > HEIGHT) { enemy4_bullet[i].isExit = false; } } } //敌机5 for (i = 0; i < enemy_bul_max; i++) { if (enemy5_bullet[i].isExit == true) { enemy5_bullet[i].y += 8; if (enemy5_bullet[i].y > HEIGHT) { enemy5_bullet[i].isExit = false; } } } } void Enemy_Bullet_Crush() { for (int i = 0; i < 1; i++) { if (!myplane[i].isExit)//如果我方飞机不存在,则跳出本次循环 continue; for (int j = 0; j < enemy_bul_max; j++) { if (!enemy2_bullet[j].isExit) continue; if (enemy2_bullet[j].x > myplane[i].x && enemy2_bullet[j].x < myplane[i].x + myplane[i].width && enemy2_bullet[j].y < myplane[i].y + myplane[i].height && enemy2_bullet[j].y > myplane[i].y) { myplane[i].hp -= 10; setbkmode(TRANSPARENT);//如果飞机扣血,则输出扣血量 settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { outtextxy(myplane[i].x, myplane[i].y + rand() % (myplane[i].height), _T("-10")); } } if (myplane[i].hp <= 0) { Judge(); } } } for (int i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (int j = 0; j < enemy_bul_max; j++) { if (!enemy3_bullet[j].isExit) continue; if (enemy3_bullet[j].x > myplane[i].x && enemy3_bullet[j].x < myplane[i].x + myplane[i].width && enemy3_bullet[j].y < myplane[i].y + myplane[i].height && enemy3_bullet[j].y > myplane[i].y) { myplane[i].hp -= 10; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { outtextxy(myplane[i].x, myplane[i].y + rand() % (myplane[i].height), _T("-10")); } } if (myplane[i].hp <= 0) { Judge(); } } } for (int i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (int j = 0; j < enemy_bul_max; j++) { if (!enemy4_bullet[j].isExit) continue; if (enemy4_bullet[j].x > myplane[i].x && enemy4_bullet[j].x < myplane[i].x + myplane[i].width && enemy4_bullet[j].y < myplane[i].y + myplane[i].height && enemy4_bullet[j].y > myplane[i].y) { myplane[i].hp -= 10; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { outtextxy(myplane[i].x, myplane[i].y + rand() % (myplane[i].height), _T("-10")); } } if (myplane[i].hp <= 0) { Judge(); } } } for (int i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (int j = 0; j < enemy_bul_max; j++) { if (!enemy5_bullet[j].isExit) continue; if (enemy5_bullet[j].x > myplane[i].x && enemy5_bullet[j].x < myplane[i].x + myplane[i].width && enemy5_bullet[j].y < myplane[i].y + myplane[i].height && enemy5_bullet[j].y > myplane[i].y) { myplane[i].hp -= 10; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { outtextxy(myplane[i].x, myplane[i].y + rand() % (myplane[i].height), _T("-10")); } } if (myplane[i].hp <= 0) { Judge(); } } } } void EnemyCrush() { for (int i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (int j = 0; j < 10; j++) { if (!enemy1[j].isExit) continue; if (enemy1[j].x > myplane[i].x && enemy1[j].x < myplane[i].x + myplane[i].width && enemy1[j].y > myplane[i].y && enemy1[j].y < myplane[i].y + myplane[i].height) { myplane[i].hp -= 100; enemy1[j].isExit = false; score += rand() % 10 + 20; enemy1[j].hp = 30; CreateThread(0, 0, Boom, 0, 0, 0); } if (myplane[i].hp <= 0) { Judge(); } } } for (int i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (int j = 0; j < 5; j++) { if (!enemy2[j].isExit) continue; if (enemy2[j].x > myplane[i].x && enemy2[j].x<myplane[i].x + myplane[i].width && enemy2[j].y>myplane[i].y && enemy2[j].y < myplane[i].y + myplane[i].height) { myplane[i].hp -= 100; enemy2[j].isExit = false; score += rand() % 50 + 100; enemy2[j].hp = 50; CreateThread(0, 0, Boom, 0, 0, 0); } if (myplane[i].hp <= 0) { Judge(); } } } for (int i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (int j = 0; j < 5; j++) { if (!enemy3[j].isExit) continue; if (enemy3[j].x > myplane[i].x && enemy3[j].x<myplane[i].x + myplane[i].width && enemy3[j].y>myplane[i].y && enemy3[j].y < myplane[i].y + myplane[i].height) { myplane[i].hp -= 100; enemy3[j].isExit = false; score += rand() % 50 + 100; enemy3[j].hp = 30; CreateThread(0, 0, Boom, 0, 0, 0); } if (myplane[i].hp <= 0) { Judge(); } } } } void UpdatePlane() { //GetAsyncKeyState非阻塞获取键盘信息函数 //飞机移动 if (GetAsyncKeyState(VK_UP)) //按UP键 { for (int i = 0; i < 1; i++) { if (myplane[i].y > 0)//如果没有超过边界再执行 { myplane[i].y -= 8; //加载飞机移动音乐 mciSendString(L"open 飞机移动.mp3", 0, 0, 0); mciSendString(L"play 飞机移动.mp3", 0, 0, 0); } } } if (GetAsyncKeyState(VK_DOWN)) //按DOWN键 { for (int i = 0; i < 1; i++) { if (myplane[i].y < HEIGHT - myplane[i].height) { myplane[i].y += 8; //加载飞机移动音乐 mciSendString(L"open 飞机移动.mp3", 0, 0, 0); mciSendString(L"play 飞机移动.mp3", 0, 0, 0); } } } if (GetAsyncKeyState(VK_LEFT)) //按LEFT键 { for (int i = 0; i < 1; i++) { if (myplane[i].x > -(myplane[i].width) / 2) { myplane[i].x -= 8; //加载飞机移动音乐 mciSendString(L"open 飞机移动.mp3", 0, 0, 0); mciSendString(L"play 飞机移动.mp3", 0, 0, 0); } } } if (GetAsyncKeyState(VK_RIGHT)) //按RIGHT键 { for (int i = 0; i < 1; i++) { if (myplane[i].x < WIDTH - (myplane[i].width) / 2) { myplane[i].x += 8; //加载飞机移动音乐 mciSendString(L"open 飞机移动.mp3", 0, 0, 0); mciSendString(L"play 飞机移动.mp3", 0, 0, 0); } } } if (GetAsyncKeyState('J') || GetAsyncKeyState('j')) { CreateThread(0, 0, PlaneFireMusic, 0, 0, 0); DrawBullet(); } if (GetAsyncKeyState('L') || GetAsyncKeyState('l')) { if (Timer1(30000)) { CreateThread(0, 0, PlaneLighterMusic, 0, 0, 0); DrawLighter(); } } } void initGame() { int i; //初始化背景地图Y轴坐标(为了后续移动背景地图) bky0 = -HEIGHT; bky1 = 0; bk1y0 = -HEIGHT; bk1y1 = 0; bk2y0 = -HEIGHT; bk2y1 = 0; bk3y0 = -HEIGHT; bk3y1 = 0; //初始化我方飞机 for (i = 0; i < 1; i++) { myplane[i].x = (WIDTH - myplane[i].width) / 2; myplane[i].y = (HEIGHT - myplane[i].height); myplane[i].hp = 500; myplane[i].isExit = true; } //初始化敌机 for (i = 0; i < 10; i++) { enemy1[i].isExit = false; enemy1[i].hp = 30; enemy1[i].width = 70; enemy1[i].height = 70; } for (i = 0; i < 5; i++) { enemy2[i].isExit = false; enemy2[i].hp = 50; enemy2[i].width = 85; enemy2[i].height = 90; } for (i = 0; i < 5; i++) { enemy3[i].isExit = false; enemy3[i].hp = 30; enemy3[i].width = 70; enemy3[i].height = 70; } for (i = 0; i < 1; i++) { enemy4[i].isExit = false; enemy4[i].hp = 10000; enemy4[i].width = 450; enemy4[i].height = 300; } for (i = 0; i < 1; i++) { enemy5[i].isExit = false; enemy5[i].hp = 12000; enemy5[i].width = 500; enemy5[i].height = 375; } //初始化子弹 bullet[i].x1; bullet[i].y1; bullet[i].x2; bullet[i].y2; for (i = 0; i < bullet_max; i++) { bullet[i].isExit = false; } //初始化敌机子弹 for (i = 0; i < enemy_bul_max; i++) { enemy2_bullet[i].isExit = false; } for (i = 0; i < enemy_bul_max; i++) { enemy3_bullet[i].isExit = false; } for (i = 0; i < enemy_bul_max; i++) { enemy4_bullet[i].isExit = false; } for (i = 0; i < enemy_bul_max; i++) { enemy5_bullet[i].isExit = false; } for (i = 0; i < 1; i++) { lighter[i].isExit = false; } //加载背景音乐 music.isExit = true; if (music.isExit == true) { mciSendString(L"open level.mp3", 0, 0, 0); mciSendString(L"play level.mp3 repeat", 0, 0, 0); } } void level_change() { int ret = level(),i = 0; if (flag == 1) { if (level_change_count == 1 && score > 5000) { level_change_count += 1; myplane[i].hp = 500; EnemyClean();//切换关卡时清除所有飞机 } if (level_change_count == 2 && score > 12000) { score = 12001; level_change_count += 1; myplane[i].hp = 500; EnemyClean(); } } } void FailMenu() { initgraph(800, 240); setbkmode(TRANSPARENT); settextstyle(30, 0, L"宋体"); outtextxy(10, 20, _T("游戏失败")); outtextxy(10, 70, _T("按Delete键退出")); outtextxy(10, 120, _T("按Enter(回车键)复活并继续游戏")); while (1) { if (GetAsyncKeyState(VK_DELETE)) exit(0);//如果按下DELETE键则直接结束程序 if (GetAsyncKeyState(VK_RETURN)) //如果按下回车键则继续游戏 { break; } } main(); } void PauseMenu() { if (GetAsyncKeyState(VK_SPACE)) { if (flag == 1) { menuState = Pause; flag1 = 1; flag = 0; } else if (flag == 2) { menuState = Pause; flag1 = 2; flag = 0; } } } void Judge() { if (flag == 1) { if (myplane->hp <= 0) { if (level() == 1) { score = 0;//第一关初始分数为0 } if (level() == 2 && score < 8000) { score = 5001;//进入第二关,且第二关boss出现前,初始分数为5001 } if (level() == 2 && score > 8000) { score = 8001;//第二关boss出现后,初始分数 } if (level() == 3) { score = 12001;//进入第三关,初始分数 } FailMenu(); } if (score > 17000) { EndMenu(); } } } void UpdateBack() { //背景移动 bky0++; bky1++; if (bky0 > HEIGHT) (bky0 = -HEIGHT); //如果背景移出初始界面,则放到下面 if (bky1 > HEIGHT) (bky1 = -HEIGHT); bk1y0++; bk1y1++; if (bk1y0 > HEIGHT) (bk1y0 = -HEIGHT); //如果背景移出初始界面,则放到下面 if (bk1y1 > HEIGHT) (bk1y1 = -HEIGHT); bk2y0++; bk2y1++; if (bk2y0 > HEIGHT) (bk2y0 = -HEIGHT); //如果背景移出初始界面,则放到下面 if (bk2y1 > HEIGHT) (bk2y1 = -HEIGHT); bk3y0++; bk3y1++; if (bk3y0 > HEIGHT) (bk3y0 = -HEIGHT); //如果背景移出初始界面,则放到下面 if (bk3y1 > HEIGHT) (bk3y1 = -HEIGHT); } void DrawBullet() { if (Timer(140)) { //绘制子弹 for (int i = 0; i < bullet_max; i++) { if (!bullet[i].isExit) //遍历所有子弹位,找到一个空位存放子弹 { bullet[i].x1 = myplane->x + 18; //若子弹存在初始化子弹坐标 bullet[i].y1 = myplane->y + 25; bullet[i].x2 = myplane->x + 65; bullet[i].y2 = myplane->y + 25; bullet[i].isExit = true; break; //发射一次子弹 } } } } void DrawLighter() { for (int i = 0; i < 1; i++) { if (!lighter[i].isExit) { lighter[i].x = myplane->x - (305 - myplane->width) / 2; lighter[i].y = myplane->y - 200; lighter[i].isExit = true; break; } } } void MoveBullet() { //子弹移动 for (int i = 0; i < bullet_max; i++) { if (bullet[i].isExit) { bullet[i].y1 -= 10; bullet[i].y2 -= 10; if (bullet[i].y1 > HEIGHT || bullet[i].y2 > HEIGHT ) bullet[i].isExit = false; //若子弹飞出则腾出一个子弹位 } } } void MoveLighter() { for (int i = 0; i < 1; i++) { if (lighter[i].isExit) { lighter[i].y -= 5; if (lighter[i].y < -200) lighter[i].isExit = false; } } } void Bulletcrush() { for (int i = 0; i < 10; i++) { if (!enemy1[i].isExit) continue; for (int j = 0; j < bullet_max; j++) { if (!bullet[j].isExit) continue; if ((bullet[j].x1 > enemy1[i].x && bullet[j].x1<enemy1[i].x + enemy1[i].width && bullet[j].y1>enemy1[i].y && bullet[j].y1 < enemy1[i].y + enemy1[i].height) || (bullet[j].x2>enemy1[i].x && bullet[j].x2<enemy1[i].x + enemy1[i].width && bullet[j].y2>enemy1[i].y && bullet[j].y2 < enemy1[i].y + enemy1[i].height)) { enemy1[i].hp -= 1; if (Timer2(1)) { setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); outtextxy(enemy1[i].x, enemy1[i].y + rand() % (enemy1[i].height), _T("-1")); } } } if (enemy1[i].hp <= 0) { enemy1[i].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += rand() % 10 + 20; enemy1[i].hp = 30; } }//小飞机 for (int i = 0; i < 5; i++) { if (!enemy2[i].isExit) continue; for (int j = 0; j < bullet_max; j++) { if (!bullet[j].isExit) continue; if ((bullet[j].x1 > enemy2[i].x && bullet[j].x1<enemy2[i].x + enemy2[i].width && bullet[j].y1>enemy2[i].y && bullet[j].y1 < enemy2[i].y + enemy2[i].height) || (bullet[j].x2>enemy2[i].x && bullet[j].x2<enemy2[i].x + enemy2[i].width && bullet[j].y2>enemy2[i].y && bullet[j].y2 < enemy2[i].y + enemy2[i].height)) { enemy2[i].hp -= 1; if (Timer2(1)) { setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); outtextxy(enemy2[i].x, enemy2[i].y + rand() % (enemy2[i].height), _T("-1")); } } } if (enemy2[i].hp <= 0) { enemy2[i].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += rand() % 50 + 100; enemy2[i].hp = 50; } }//中飞机 for (int i = 0; i < 5; i++) { if (!enemy3[i].isExit) continue; for (int j = 0; j < bullet_max; j++) { if (!bullet[j].isExit) continue; if ((bullet[j].x1 > enemy3[i].x && bullet[j].x1<enemy3[i].x + enemy3[i].width && bullet[j].y1>enemy3[i].y && bullet[j].y1 < enemy3[i].y + enemy3[i].height) || (bullet[j].x2>enemy3[i].x && bullet[j].x2<enemy3[i].x + enemy3[i].width && bullet[j].y2>enemy3[i].y && bullet[j].y2 < enemy3[i].y + enemy3[i].height)) { enemy3[i].hp -= 1; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { outtextxy(enemy3[i].x, enemy3[i].y + rand() % (enemy3[i].height), _T("-1")); } } } if (enemy3[i].hp <= 0) { enemy3[i].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += rand() % 50 + 100; enemy3[i].hp = 30; } }//横行飞机 for (int i = 0; i < 1; i++) { if (!enemy4[i].isExit) continue; for (int j = 0; j < bullet_max; j++) { if(!bullet[j].isExit) continue; if ((bullet[j].x1 > enemy4[i].x && bullet[j].x1<enemy4[i].x + enemy4[i].width && bullet[j].y1>enemy4[i].y && bullet[j].y1 < enemy4[i].y + enemy4[i].height) || (bullet[j].x2 > enemy4[i].x && bullet[j].x2<enemy4[i].x + enemy4[i].width && bullet[j].y2>enemy4[i].y && bullet[j].y2 < enemy4[i].y + enemy4[i].height)) { enemy4[i].hp -= rand() % 4 + 1; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { if (enemy4[i].hp -= 1) { outtextxy(enemy4[i].x + rand() % (enemy4[i].width), enemy4[i].y + rand() % (enemy4[i].height), _T("-1")); } if (enemy4[i].hp -= 2) { outtextxy(enemy4[i].x + rand() % (enemy4[i].width), enemy4[i].y + rand() % (enemy4[i].height), _T("-2")); } if (enemy4[i].hp -= 3) { outtextxy(enemy4[i].x + rand() % (enemy4[i].width), enemy4[i].y + rand() % (enemy4[i].height), _T("-3")); } if (enemy4[i].hp -= 4) { outtextxy(enemy4[i].x + rand() % (enemy4[i].width), enemy4[i].y + rand() % (enemy4[i].height), _T("暴击 -4")); } if (enemy4[i].hp -= 5) { outtextxy(enemy4[i].x + rand() % (enemy4[i].width), enemy4[i].y + rand() % (enemy4[i].height), _T("暴击 -5")); } } } if (enemy4[i].hp <= 0) { enemy4[i].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += 4000; } } } //第二关BOSS for (int i = 0; i < 1; i++) { if (!enemy5[i].isExit) continue; for (int j = 0; j < bullet_max; j++) { if (!bullet[j].isExit) continue; if ((bullet[j].x1 > enemy5[i].x && bullet[j].x1<enemy5[i].x + enemy5[i].width && bullet[j].y1>enemy5[i].y && bullet[j].y1 < enemy5[i].y + enemy5[i].height && bullet[j].x2>enemy5[i].x) || (bullet[j].x2<enemy5[i].x + enemy5[i].width && bullet[j].y2>enemy5[i].y && bullet[j].y2 < enemy5[i].y + enemy5[i].height)) { enemy5[i].hp -= rand() % 5 + 1; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { if (enemy5[i].hp -= 1) { outtextxy(enemy5[i].x + rand() % (enemy5[i].width), enemy5[i].y + rand() % (enemy5[i].height), _T("-1")); } if (enemy5[i].hp -= 2) { outtextxy(enemy5[i].x + rand() % (enemy5[i].width), enemy5[i].y + rand() % (enemy5[i].height), _T("-2")); } if (enemy5[i].hp -= 3) { outtextxy(enemy5[i].x + rand() % (enemy5[i].width), enemy5[i].y + rand() % (enemy5[i].height), _T("-3")); } if (enemy5[i].hp -= 4) { outtextxy(enemy5[i].x + rand() % (enemy5[i].width), enemy5[i].y + rand() % (enemy5[i].height), _T("暴击 -4")); } if (enemy5[i].hp -= 5) { outtextxy(enemy5[i].x + rand() % (enemy5[i].width), enemy5[i].y + rand() % (enemy5[i].height), _T("暴击 -5")); } if (enemy5[i].hp -= 6) { outtextxy(enemy5[i].x + rand() % (enemy5[i].width), enemy5[i].y + rand() % (enemy5[i].height), _T("暴击 -6")); } } } if (enemy5[i].hp <= 0) { enemy5[i].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += 5000; Judge(); } } } //第三关BOSS } void LighterCrush() { for (int j = 0; j < 1; j++) { if (!lighter[j].isExit) continue; for (int i = 0; i < 10; i++) { if (!enemy1[i].isExit) continue; if (enemy1[i].x > lighter[j].x - 20 && enemy1[i].x < lighter[j].x + 305 && enemy1[i].y > lighter[j].y && enemy1[i].y < lighter[j].y + 200) { enemy1[i].hp -= 100; if (Timer2(1)) { setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); outtextxy(enemy1[i].x, enemy1[i].y + rand() % (enemy1[i].height), _T("-100")); } } } if (enemy1[j].hp <= 0) { enemy1[j].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += rand() % 10 + 20; enemy1[j].hp = 30; } }//小飞机 for (int j = 0; j < 1; j++) { if (!lighter[j].isExit) continue; for (int i = 0; i < 5; i++) { if (!enemy2[i].isExit) continue; if (enemy2[i].x > lighter[j].x - 20 && enemy2[i].x < lighter[j].x + 305 && enemy2[i].y > lighter[j].y && enemy2[i].y < lighter[j].y + 200) { enemy2[i].hp -= 100; if (Timer2(1)) { setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); outtextxy(enemy2[i].x, enemy2[i].y + rand() % (enemy2[i].height), _T("-100")); } } } if (enemy2[j].hp <= 0) { enemy2[j].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += rand() % 50 + 100; enemy2[j].hp = 50; } }//大飞机 for (int j = 0; j < 1; j++) { if (!lighter[j].isExit) continue; for (int i = 0; i < 5; i++) { if (!enemy3[i].isExit) continue; if (enemy3[i].x > lighter[j].x - 20 && enemy3[i].x < lighter[j].x + 305 && enemy3[i].y > lighter[j].y && enemy3[i].y < lighter[j].y + 200) { enemy3[i].hp -= 100; if (Timer2(1)) { setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); outtextxy(enemy3[i].x, enemy3[i].y + rand() % (enemy3[i].height), _T("-100")); } } } if (enemy3[j].hp <= 0) { enemy3[j].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += rand() % 50 + 100; enemy3[j].hp = 30; } }//横行飞机 for (int i = 0; i < 1; i++) { if (!enemy4[i].isExit) continue; for (int j = 0; j < 1; j++) { if (!lighter[j].isExit) continue; if ((lighter[j].x > enemy4[i].x && lighter[j].x < enemy4[i].x + enemy4[i].width && lighter[j].y > enemy4[i].y && lighter[j].y < enemy4[i].y + enemy4[i].height) || (lighter[j].x + 305 > enemy4[i].x && lighter[j].x + 305 < enemy4[i].x + enemy4[i].width && lighter[j].y > enemy4[i].y && lighter[j].y < enemy4[i].y + enemy4[i].height) || lighter[j].x > enemy4[i].x && lighter[j].x < enemy4[i].x + enemy4[i].width && lighter[j].y + 200 > enemy4[i].y && lighter[j].y + 200 < enemy4[i].y + enemy4[i].height || lighter[j].x + 305 > enemy4[i].x && lighter[j].x + 305 < enemy4[i].x + enemy4[i].width && lighter[j].y + 200 > enemy4[i].y && lighter[j].y + 200 < enemy4[i].y + enemy4[i].height) { enemy4[i].hp -= 100; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { outtextxy(enemy4[i].x + rand() % (enemy4[i].width), enemy4[i].y + rand() % (enemy4[i].height), _T("-100")); } } if (enemy4[i].hp <= 0) { enemy4[i].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += 4000; } } } //第二关BOSS for (int i = 0; i < 1; i++) { if (!enemy5[i].isExit) continue; for (int j = 0; j < 1; j++) { if (!lighter[j].isExit) continue; if ((lighter[j].x > enemy5[i].x && lighter[j].x < enemy5[i].x + enemy5[i].width && lighter[j].y > enemy5[i].y && lighter[j].y < enemy5[i].y + enemy5[i].height) || (lighter[j].x + 305 > enemy5[i].x && lighter[j].x + 305 < enemy5[i].x + enemy5[i].width && lighter[j].y > enemy5[i].y && lighter[j].y < enemy5[i].y + enemy5[i].height) || lighter[j].x > enemy5[i].x && lighter[j].x < enemy5[i].x + enemy5[i].width && lighter[j].y + 200 > enemy5[i].y && lighter[j].y + 200 < enemy5[i].y + enemy5[i].height || lighter[j].x + 305 > enemy5[i].x && lighter[j].x + 305 < enemy5[i].x + enemy5[i].width && lighter[j].y + 200 > enemy5[i].y && lighter[j].y + 200 < enemy5[i].y + enemy5[i].height) { enemy5[i].hp -= 100; setbkmode(TRANSPARENT); settextstyle(60, 0, L"华文行楷"); if (Timer2(1)) { outtextxy(enemy5[i].x + rand() % (enemy5[i].width), enemy5[i].y + rand() % (enemy5[i].height), _T("-100")); } } if (enemy5[i].hp <= 0) { enemy5[i].isExit = false; CreateThread(0, 0, Boom, 0, 0, 0); score += 5000; Judge(); } } } } void Print() { setbkmode(TRANSPARENT); settextstyle(40, 0, L"华文行楷"); TCHAR ScorePrint[100]; _stprintf(ScorePrint, L"当前分数:%d", score); outtextxy(0, 750, ScorePrint); setbkmode(TRANSPARENT); settextstyle(40, 0, L"华文行楷"); TCHAR HPPrint[100]; _stprintf(HPPrint, L"当前血量:%d", myplane->hp); outtextxy(0, 800,HPPrint); } void ChallengeMode() { if (flag == 2) { int i, j; for (i = 0; i < 1; i++) { if (lighter[i].isExit == true) lighter[i].isExit = false; } for (i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (j = 0; j < 10; j++) { if (enemy1[j].y > HEIGHT) myplane[i].hp -= 100; } } for (i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (j = 0; j < 5; j++) { if (enemy2[j].y > HEIGHT) myplane[i].hp -= 100; } } for (i = 0; i < 1; i++) { if (!myplane[i].isExit) continue; for (j = 0; j < 5; j++) { if (enemy3[j].y > HEIGHT) myplane[i].hp -= 100; } } } } void EndMenu() { EnemyClean(); if (flag == 1 && enemy5[0].isExit == false) { menuState = End2; flag = 0; } } void EndScene() { if (flag == 2 && myplane->hp <= 0) { menuState = End; flag = 0; } }
#include "雷霆飞机.h" #include <conio.h> #include <stdio.h> #include <graphics.h> #include <windows.h> #include <conio.h> #include<mmsystem.h> #pragma comment(lib,"Winmm.lib") #define WIDTH 600 #define HEIGHT 850 #define bullet_max 5000//屏幕上同时出现的子弹上限、 #define enemy_bul_max 1500 //敌方飞机子弹最大量 //将所有封装函数放入主函数进行调用 int main() { HWND hwnd = initgraph(WIDTH, HEIGHT); SetWindowText(hwnd, L"雷霆战机"); initGame(); loadimg(); BeginBatchDraw();//双缓冲绘图 while (1) { while (level() == 0) { ExMessage msg; while (peekmessage(&msg, EX_MOUSE)) { DrawInterface(&msg); } FlushBatchDraw(); } UpdateBack(); level_change(); if (level() == 1) { EnemyCreat_L1(); } if (level() == 2) { EnemyCreat_L2(); } if (level() == 3) { EnemyCreat_L3(); } if (level() == 5) { EnemyCreat_L4(); ChallengeMode(); EndScene(); } PauseMenu(); EnemyMove(); Enemy_Bullet_Creat(); Enemy_Bullet_Move(); DrawGame(); UpdatePlane(); MoveBullet(); MoveLighter(); Bulletcrush(); LighterCrush(); Enemy_Bullet_Crush(); EnemyCrush(); Print(); FlushBatchDraw(); Sleep(1); } EndBatchDraw(); return 0; }
项目文档
一. 游戏概述
- 游戏类型和玩法
属于一款机战类具有挑战性和娱乐性的游戏
通过获取用户鼠标及键盘消息来控制界面转换和飞机移动以及释放子弹和技能
- 游戏目标和规则
普通模式:
通关最终BOSS,我方飞机受到敌机以及敌机子弹碰撞,则持续扣血,如果飞机血量为0,则返回失败界面(由用户选择复活继续游戏或退出游戏)
挑战模式:
采用无尽模式积分制,并且禁止实用技能,新增漏击判定(即敌机飞出画面认为被击毁,则我方飞机扣血),除非飞机血量为0或用户选择退出游戏,否则游戏持续进行,飞机血量为0,游戏结束并显示最终得分
二. 游戏设计
- 游戏界面设计
选用炫酷的飞机大战图片并且采取菜单模式,可以进行界面转换重复进行游戏
- 游戏关卡和难度设计
普通模式分为三关,分数达到则自动进入下一关卡,难度较小
挑战模式采用无尽模式积分,敌机创建频率增大,难度递增
三. 技术实现
- 游戏开发工具
采用VS2022,Easyx图形库,C语言/C++
- 游戏代码结构和模块划分
1.初始化游戏窗口
2.初始化游戏数据
3.循环游戏事件
编写玩家控制模块,碰撞模块,子弹发射模块,技能发射模块,关卡转换模块,界面转换模块
4.设置游戏结束标志
四. 测试和调试
- 游戏测试计划和用例
玩家控制模块:测试飞机移动边界以及按键响应时间
碰撞模块:测试敌机与子弹,敌机与技能,我方飞机与子弹,我方飞机与敌机碰撞会不会正常扣血与消失,会不会影响下一次敌机创建
子弹发射模块:检测子弹创建后能否按预定轨迹,并且从预定起始位置发射,子弹消失判定以及是否会影响下一次子弹创建
技能发射模块:检测技能创建后能否按预定轨迹,并且从预定起始位置发射,技能消失判定以及碰撞判定
关卡转换模块:分数达到后是否会正常切换关卡背景图,是否会按预定的方式和时间创建敌机和子弹,每次关卡转换之间是否会上一关的敌机和子弹,是否会初始化飞机血量
界面转换模块:检测获取鼠标消息后是否会转换界面以及响应时间,界面转换是否会影响游戏逻辑,如何通过界面转换将不同的模式联系在一起
- 游戏调试工具和方法
VS2022,先对各个模块单独调试,再对整个游戏逻辑(包括关卡转换,界面转换,计分等)进行调试
- 游戏修复和更新流程
1.0:未加入界面转换模块,未加入挑战模式,敌机子弹创建后不移动就消失,未加入暂停界面,未加入子弹发射,飞机移动,爆炸音效
2.0:修复1.0的bug,加入界面转换模块,加入子弹发射,飞机移动,爆炸音效
3.0:加入暂停界面,且通过暂停界面用户可选择继续游戏(保存之前的游戏数据),退出游戏,开启/关闭音效
五. 优化
- 游戏后续更新和改进计划
1.界面转换模块
问题:响应时间较长,且一次游戏结束后,用户选择返回菜单继续游戏,游戏画面会出现偶尔卡顿
猜想:游戏数据处理不当,内存无法及时释放导致卡顿
改进计划:引入数据结构,适当优化及存储游戏数据,增加游戏运行时间,流畅性
2.问题:持续按住攻击键不放,一段时间偶尔会出现卡顿
猜想:由按下攻击键后的音效引发,因为音效采用多线程,频繁调用多线程,且线程得不到及时释放会造成线程死锁,从而使程序卡顿
改进方法:设定线程存在时间,到达一定时间自动释放
六. 总结和展望
- 游戏开发过程中的经验和教训
增加我对C语言的使用熟练度,更好的掌握条件控制与循环控制程序运行
接触到一部分C++知识如IMAGE变量,MySQL数据库,多线程使用(基础版),有利于我之后进一步接触C++
对bug的调试更加熟练,同时掌握开发游戏最基础的逻辑,锻炼自己的逻辑思维
增加团队合作,增长团队合作精神