1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 基于C语言和EasyX图形库的简单飞行射击小游戏

基于C语言和EasyX图形库的简单飞行射击小游戏

时间:2019-03-26 08:37:19

相关推荐

基于C语言和EasyX图形库的简单飞行射击小游戏

基于C语言和EasyX图形库的简单飞行射击小游戏

基本游戏逻辑介绍

本次编写的游戏是一个空战小游戏,实现了一些简单的游戏功能。如主菜单和子菜单游戏界面均通过鼠标点击进行操作,通过按键来控制游戏角色的移动以及技能的释放。

下面简单的介绍一下游戏的大概流程和思路。 首先,对于游戏中的个体,存在着很多的信息,所以我们定义不同的结构体来存储这些个体的各种信息,如是否存活、子弹等级、敌机的种类、PH值等。关于easyx图形库就不做过多的介绍,大家可以自行去了解

游戏先进入主菜单,通过循环来实现获取鼠标信息,在通过判定鼠标是否点击以及点击的位置,达到选择不同功能的效果。选择开始游戏后跳出主菜单循环,进入游戏循环,通过定义不同的功能函数来实现角色的移动、图片的刷新、以及一部分简单的动态效果。通过GetKeyState()函数来判断用户是否按下移动键。进行移动,改变图片坐标位置。再产生敌机和敌机子弹,敌机和子弹的移动(通过改变坐标实现移动),判定是否被子弹击中或者与敌机碰撞。最后调用画地图的函数,将所有的图片画出。游戏死亡之后、暂停、退出等的功能与主菜单同理,通过鼠标控制(使用goto语句实现返回主菜单、重新开始游戏)。游戏还有能保存游戏分数的最好历史记录,涉及一些简单的文件操作。

在编写过程中遇见的一些坑

在图片的打印中会有闪烁的问题,这里使用双缓冲解决BeginBatchDraw();FlushBatchDraw();在实现暂停功能时,会有暂停的图片呈现,建议将图片设置成窗口大小,当你暂停时的图片比地图更小时,会有鼠标操作不灵敏的问题(若能解决建议还是比地图小一些),即需要点击多次才可能触发你的判断。敌机和子弹需要使用透明贴图,所以需要掩码图和原图来实现透明贴图。如

putimage(minePlan.x, minePlan.y, &minebit[0], NOTSRCERASE);putimage(minePlan.x, minePlan.y, &mine[0], SRCINVERT);

参考链接:如何制作掩码图

多种音效同时播放需要使用简单的多线程,否则会导致游戏卡顿。如背景音效和爆炸音效同时播放。请读者自行查阅资料。动态爆炸的实现,当使用多线程实现时,有爆炸闪烁的效果(这个问题还未解决),可以在打印图片的函数中实现。原理:每次图刷新都会打印爆炸的图片(地图刷新的速度很快),通过控制打印不同的图片实现爆炸效果(需要控制图片更新的时间),类似于通过快速翻动画在纸上的图片达到动态的效果,具体操作,参考代码。

头文件代码

头文件定义代码,函数的声明较少是因为在主文件中用到的函数较少,大多数函数的调用在AirGame.cpp中

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>//文件操作的头文件sprintf()函数#include<stdlib.h>#include<conio.h>#include<windows.h> //GetKeyState()函数需要#include<mmsystem.h>//playSound()函数需要.包含多媒体设备接口库#include<math.h>//rand()随机函数需要#pragma comment(lib,"Winmm.lib")//导入Winmm.lib库,让歌曲可以播放#include<graphics.h>//easyx图形库的头文件#include<process.h>#define NUM 20 //敌机数组数量#define WIDTH 600//地图宽600 #define HEIGHT 700//高700#define N 15//子弹数量#define BOSSBUL 100//boss子弹量#undef UNICODE //解决loadimage()的加载出问题的问题 //定义我方飞机和敌方飞机坐标血量,子弹等...typedef struct role//我方飞机{int x;//确定在图中的坐标int y;int type;//我方飞机子弹等级int kind;//我方飞机种类int live;//飞机是否存活int score; //存储分数}Role;typedef struct enemy //敌机{int x;//确定在图中的坐标int y;int type;//敌机飞机种类.int live;//飞机是否存活int HP;//血量char shot;//表示飞机是否发射过子弹}Enemy; typedef struct _bullte //子弹{int x;//确定在图中的坐标int y;int live;//子弹是否存活char shot;//导弹是否发射}Bullte; typedef struct ico//图标{int x;//确定在图中的坐标int y;int live;//飞机、子弹是否存活}Ico;char PlayKeyboard(char c);void texiao();void image(IMAGE *map1, Role *minePlan);//图片加载//飞机移动int keyDown(IMAGE* map1, int speed);//画出飞机移动后的地图void drowGame();void planMove(char c,IMAGE *mine);char GameOver();//游戏结束后 void DataConserve();//保存数据并退出 void OutScore(int number);//输出数字图片 int timeout();//暂停函数 int Datadir();//记录查看

Main.cpp代码

#include"airHead.h"//定义图片变量IMAGE map1, mine[2],map[7],tubiao[10], shuzi[3], shuziyama[3];Role minePlan;//定义我方飞机DWORD t1, t2,t3,t4,t5,t6,t7,t8;//什么变量IMAGE enemy2[5], enemy2yanma[5];int img_x, img_y;//IMAGE tu[2];int Num[7], count = 0;int MainMenu(){MOUSEMSG m, m2, m3, m4;//定义鼠标变量while (1)//主菜单操作{putimage(0, 0, &map[0]);FlushBatchDraw();m = GetMouseMsg();if (m.uMsg == WM_LBUTTONDOWN)//当鼠标左键按下{if (m.x > 230 && m.x < 371 && m.y>46 && m.y < 83)//选择角色{putimage(0, 0, &map[5]);//角色选择界面FlushBatchDraw();while (1){m3 = GetMouseMsg();if (m3.uMsg == WM_LBUTTONDOWN)//当鼠标左键按下{if (m3.x < 147 && m3.x>57 && m3.y > 210 && m3.y < 291)//1号机{minePlan.kind = 1;break;}if (m3.x < 537 && m3.x>449 && m3.y > 210 && m3.y < 291)//2号机{minePlan.kind = 2;break;}}}}if (m.x > 230 && m.x < 371 && m.y>154 && m.y < 193)//开始游戏{break;}if (m.x > 230 && m.x < 371 && m.y>270 && m.y < 306)//退出游戏{DataConserve();return 0;}if (m.x > 230 && m.x < 371 && m.y>381 && m.y < 421)//游戏记录{putimage(0, 0, &map[6]);//显示历史最高纪录putimage(0, 0, &tubiao[0], NOTSRCERASE);putimage(0, 0, &tubiao[1], SRCINVERT);int score = Datadir();//输出位置img_x = 196;img_y = 275;count = 0;//数组下标归零if (score == -1)OutScore(0);elseOutScore(score);FlushBatchDraw();while (1){m4 = GetMouseMsg();if (m4.uMsg == WM_LBUTTONDOWN)//当鼠标左键按下{if (m4.x < 50 && m4.x>0 && m4.y > 0 && m4.y < 50){break;}}}}if (m.x > 230 && m.x < 371 && m.y>484 && m.y < 3524)//游戏帮助{putimage(0, 0, &map[1]);//显示游戏操作说明putimage(0, 0, &tubiao[0], NOTSRCERASE);putimage(0, 0, &tubiao[1], SRCINVERT);FlushBatchDraw();while (1){m2 = GetMouseMsg();if (m2.uMsg == WM_LBUTTONDOWN)//当鼠标左键按下{if (m2.x < 50 && m2.x>0 && m2.y > 0 && m2.y < 50){break;}}}}}}}int main(){minePlan.kind = 1;//默认为1号机D://返回主菜单t1 = t2 = t3 = t4 = t5 = t6 = t7 = t8 = GetTickCount();//获取系统开机到当前所经过的毫秒数//图形化窗口initgraph(WIDTH, HEIGHT);//地图image(&map1, &minePlan);mciSendString("open startMusic.mp3 alias start", NULL, 0, NULL);//alias 起别为 mymusic;mciSendString("play start repeat", NULL, 0, NULL);putimage(0, 0, &map[0]);FlushBatchDraw();//主菜单if (MainMenu() == 0)//在主菜单中选择退出游戏时,结束游戏return 0;R://游戏重新开始image(&map1, &minePlan);mciSendString("close start ", NULL, 0, NULL);mciSendString("close time ", NULL, 0, NULL);mciSendString("open 倒计时.wav alias time", NULL, 0, NULL);//倒计时音乐mciSendString("play time ", NULL, 0, NULL);int jishu=3;while (jishu>0)//游戏开始倒计时{putimage(0, 0, &map1);putimage(300, 350, 17, 22, &shuziyama[0], jishu * 17, 0, NOTSRCERASE);putimage(300, 350, 17, 22, &shuzi[0], jishu * 17, 0, SRCINVERT);FlushBatchDraw();Sleep(1000);jishu--;}putimage(280, 350, &tubiao[5], NOTSRCERASE);putimage(280, 350,&tubiao[4], SRCINVERT);FlushBatchDraw();Sleep(1000);mciSendString("close start ", NULL, 0, NULL);mciSendString("open ll.mp3 alias mymusic", NULL, 0, NULL);//alias 起别为 mymusic;mciSendString("play mymusic repeat", NULL, 0, NULL);while (1){BeginBatchDraw();//开启双缓冲绘图,在内存中画好,再显示出来int b = keyDown(&map1, 10);drowGame();//更新当前的地图,飞机,子弹,重复执行子弹移动的函数,实现子弹的移动if (b == 1)//退出游戏{mciSendString("stop mymusic", NULL, 0, NULL);//关掉背景音乐PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//关掉子弹音效break;}else if (b == 2)//暂停{if (timeout() == 1)//返回1,代表返回主菜单{mciSendString("stop mymusic", NULL, 0, NULL);//关掉背景音乐goto D;}}else if (b == 3)//我方死亡,boss死亡{mciSendString("stop mymusic", NULL, 0, NULL);//关掉背景音乐PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//关掉子弹音效break;}FlushBatchDraw();Sleep(20);//延时函数}//判断游戏结束后的选择DataConserve();//每次退出游戏界面后保存数据char how;how = GameOver();//游戏结束结束界面的选择if (how == 'D')goto D;else if (how == 'R')goto R;return 0;}

AirGame.cpp

#define _CRT_SECURE_NO_WARNINGS#include"airHead.h"#pragma comment(lib,"Winmm.lib")//导入Winmm.lib库,让歌曲可以播放//图片加载函数extern int s = 0;//boss选择extern IMAGE map1, mine[2], map[7] ,tubiao[10], shuzi[3], shuziyama[3];//声明外部变量extern Role minePlan ;//定义我方飞机Ico ico[5], danger;//danger危险图标,ico图标Enemy enemyPlan[NUM], boss[2];//定义敌方飞机Bullte bullet[N], enemyBult[N], BossBul[BOSSBUL], developBul[15], shell ;//定义我方和地方子弹、炮弹extern DWORD t1, t2,t3,t4, t5, t6,t7,t8;IMAGE enemybul,blood[2],jineng[15],jinengyanma[15],img_developBul[15], boom2[2], boom2yanma[2],cue[2],bomb[2],hudun,relive, war[15], waryanma[15], enemy[10]; //relive提示复活的图片IMAGE boom[11], boomyanma[11], zidan, minebit[2];//爆炸、子弹、飞机掩码extern IMAGE enemy2[5], enemy2yanma[5];//旋转的敌机int m = 160, BloodWidth = -10, time[7] , show = 1;//dazao = 0,int x = 0,jj=0,enemy_x=-1,enemy_y=-1,speedx=2,speedy=2;//enemy_x确定敌机爆炸的位置,speedx确定升级图标的移动速度int score = 10;//击杀一定数量的敌机,boss出现,extern int Num[7],count, img_x, img_y;int fen = score / 2,num_death_enemy;int ene_2 = 0,my_2;//my_2飞机图片选择,ene_2旋转敌机图片选择int px[2] ,condition=0;//condition判断无敌状态,px用于地图移动void image(IMAGE* map1, Role* minePlan){loadimage(&map[0], "feng.jpg", WIDTH, HEIGHT);//封面图片loadimage(&mine[0], "mp.JPG", 50, 50);//自身飞机loadimage(&minebit[0], "mpbit.jpg", 50, 50);loadimage(&minebit[1], "minePlan22.png");//二号飞机loadimage(&mine[1], "minePlan2.png");loadimage(map1, "map1.jpg", 600, 700);//地图1loadimage(&map[1], "map22.jpg", 600, 700);loadimage(&map[2], "gameEnd.jpg", 600, 700);loadimage(&map[3], "map3.jpg", 600, 1140);loadimage(&map[4], "map3.jpg", 600, 1140);loadimage(&map[5], "型号.png");loadimage(&map[6], "jilu.jpg");loadimage(&zidan, "zidan1.png",40,50);//子弹loadimage(&enemybul, "enemyBul.png", 20, 50);//敌军子弹loadimage(&enemy[0], "enemy1.jpg", 60, 60);//敌机掩码图loadimage(&enemy[1], "enemy1_1.jpg", 60, 60);loadimage(&enemy[2], "diji2.png", 70, 50);loadimage(&enemy[3], "diji22.png", 70, 50);//敌机掩码loadimage(&enemy[4], "diji1.png", 200, 150);//bossloadimage(&enemy[5], "diji11.png", 200, 150);//boss掩码loadimage(&enemy[6], "diji4.png", 60, 60);//炸弹loadimage(&bomb[0], "enemy\\paodan1.png");loadimage(&bomb[1], "enemy\\paodan11.png");loadimage(&img_developBul[0], "updata11.png", 20, 60);//升级子弹掩码loadimage(&img_developBul[1], "updata.png", 20, 60);//暂停提示图片loadimage(&cue[0], "zanting.png",600,700);//获取图标loadimage(&tubiao[0], "fanhui11.png", 50, 50);//掩码图,返回图标loadimage(&tubiao[1], "fanhui.png", 50, 50);loadimage(&tubiao[2], "12531.png", 50, 30);//掩码,升级图标loadimage(&tubiao[3], "1253.png", 50, 30);loadimage(&relive, "tishi.png");loadimage(&tubiao[6], "enemy\\weixian11.png", 50, 50);//危险图标掩码loadimage(&tubiao[7], "enemy\\weixian1.png", 50, 50);//护盾loadimage(&hudun, "didang.png", 90, 90);//技能效果for (int i = 0; i < 6; i++)//这种方式可以获取多张图片,减少代码量{char str[50] = "";sprintf_s(str, "texiao\\dian%d.jpg", i + 1);loadimage(&war[i], str, 60, 700);sprintf_s(str, "texiao\\dian1%d.jpg", i + 1);loadimage(&waryanma[i], str, 60, 700);}//敌人2loadimage(&enemy2yanma[0], "enemy\\speed_enemy11.png");loadimage(&enemy2[0], "enemy\\speed_enemy.png");loadimage(&blood[0], "blood1.png", 300, 20);//boss血量loadimage(&blood[1], "blood2.png", 300, 20);//获取数字loadimage(&shuzi[0], "shuzi.png");loadimage(&shuziyama[0], "shuzi11.png");loadimage(&tubiao[4], "kaishi.png", 70, 30);loadimage(&tubiao[5], "kaishi11.png", 70, 30);//爆炸图片for (int i = 0; i < 11; i++){char str[50] = "";sprintf_s(str, "texiao\\bbb%d.png", i + 1);loadimage(&boom[i], str, 100, 100);sprintf_s(str, "texiao\\bbby%d.png", i + 1);loadimage(&boomyanma[i], str, 100, 100);}//爆炸2loadimage(&boom2[0], "texiao\\爆炸11.png", 600, 600);//boss爆炸loadimage(&boom2yanma[0], "texiao\\爆炸111.png", 600, 600);loadimage(&boom2[1], "texiao\\爆炸11.png");//我方飞机爆炸loadimage(&boom2yanma[1], "texiao\\爆炸111.png");loadimage(&jineng[0], "jineng.png", 40, 30);//技能loadimage(&jineng[1], "hudun.png", 70, 70);BloodWidth = -10;//初始图标不存在ico[0].live = 0;//初始化自身位置minePlan->x = WIDTH/2;minePlan->y = 500;minePlan->live = 1;minePlan->type = 1;//子弹种类minePlan->score = 0;//初始化一部分数据time[0]=-1;time[1] = 0;time[2] = 0;time[3] = 0;show = 1;//初始化升级图标出现的时候num_death_enemy = 0;//击杀敌方飞机数量fen = score / 2;m = 160;//boss移动count = 0;//初始化存数字的数组下标condition = 0;//初始护盾不存在//初始化炮弹数据shell.live = 0;//初始炮弹不存在shell.shot = 0;shell.y = 0;//初始化子弹数据for (int i = 0; i < N; i++){developBul[i].live = 0;//表示没有子弹bullet[i].live = 0;//表示没有子弹}//初始化敌军子弹for (int i = 0; i < N; i++){enemyBult[i].live = 2;//给所有子弹上塘,所有敌军共用一个子弹库enemyBult[i].y = -50;enemyBult[i].x = 0;}//多个敌军是,可以单独写个函数,传递参数i,根据概率产生敌军的种类,默认越厉害,概率越低for (int i = 0; i < NUM; i++){enemyPlan[i].live = 0;//所有不存活enemyPlan[i].HP = 1;enemyPlan[i].shot = 'N';//表示敌机未曾发射过子弹;}//初始化boss数据;boss[s].HP = 100;boss[s].type = 3;boss[s].live = 1;boss[s].x =50;boss[s].y = 0;//初始boss子弹库for (int i = 0; i < BOSSBUL; i++)BossBul[i].live = 1;//表示有子弹,2表示子弹已发射}//创建线程执行的代码函数 // CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)BOOM, NULL, NULL, 0);//调用线程DWORD WINAPI BOOM(LPVOID arg)//爆炸音效线程 //DWORD是无符号整,相当于C中的数据类型//一个返回DWORD 的API函数//{mciSendString("close boom", 0, 0, 0);mciSendString("open Bomb.wav alias boom", 0, 0, 0);mciSendString("play boom", 0, 0, 0);return 0;}DWORD WINAPI tttt(LPVOID arg)//大招音效释放线程{mciSendString("open dazao123.mp3 alias jineng", 0, 0, 0);mciSendString("play jineng ", 0, 0, 0);return 0;}//多线程爆炸动画,有闪烁的问题,暂未使用DWORD WINAPI planBoom(LPVOID arg)//爆炸效果线程{while (x<11){putimage(enemy_x, enemy_y, &boomyanma[x], NOTSRCERASE);putimage(enemy_x, enemy_y, &boom[x], SRCINVERT);FlushBatchDraw();Sleep(200);x++;if (x == 11){x = 7;break;}}return 0;}//图标升级void up(){ico[0].x = enemy_x;//图标的位置等于爆炸的飞机的坐标ico[0].y = enemy_y;ico[0].live = 1;}int Datadir(){FILE* fp;if ((fp = fopen("GameData\\data.text", "r")) == NULL){return -1;}char str[10];fgets(str,9, fp);//获取历史记录int num_str;num_str = atoi(str);//将字符串转为整型fclose(fp);return num_str;}void showEnemy2(int enemyPlan_x,int enemyPlan_y)//打印旋转敌机{switch (ene_2){case 0:putimage(enemyPlan_x, enemyPlan_y, 47, 58, &enemy2yanma[0], 2, 0, NOTSRCERASE);putimage(enemyPlan_x, enemyPlan_y, 47, 58, &enemy2[0], 2, 0, SRCINVERT);break;case 1:putimage(enemyPlan_x, enemyPlan_y, 38, 58, &enemy2yanma[0], 49, 0, NOTSRCERASE);putimage(enemyPlan_x, enemyPlan_y, 38, 58, &enemy2[0], 49, 0, SRCINVERT);break;case 2:putimage(enemyPlan_x, enemyPlan_y, 20, 58, &enemy2yanma[0], 88, 0, NOTSRCERASE);putimage(enemyPlan_x, enemyPlan_y, 20, 58, &enemy2[0], 88, 0, SRCINVERT);break;case 3:putimage(enemyPlan_x, enemyPlan_y, 20, 58, &enemy2yanma[0], 108, 0, NOTSRCERASE);putimage(enemyPlan_x, enemyPlan_y, 20, 58, &enemy2[0], 108, 0, SRCINVERT);break;case 4:putimage(enemyPlan_x, enemyPlan_y, 40, 58, &enemy2yanma[0], 128, 0, NOTSRCERASE);putimage(enemyPlan_x, enemyPlan_y, 40, 58, &enemy2[0], 128, 0, SRCINVERT);break;}}void showMyPlan(int my_x, int my_y)//自身飞机二号{switch (my_2){case 0:putimage(my_x, my_y, 53, 87, &minebit[1], 0, 0, NOTSRCERASE);putimage(my_x, my_y, 53, 87, &mine[1], 0, 0, SRCINVERT);break;case 1:putimage(my_x, my_y, 65, 87, &minebit[1], 53 ,0, NOTSRCERASE);putimage(my_x, my_y, 65, 87, &mine[1], 53, 0, SRCINVERT);break;case 2:putimage(my_x, my_y, 78, 87, &minebit[1], 118, 0, NOTSRCERASE);putimage(my_x, my_y, 78, 87, &mine[1], 118, 0, SRCINVERT);break;case 3:putimage(my_x, my_y, 67, 87, &minebit[1], 196, 0, NOTSRCERASE);putimage(my_x, my_y, 67, 87, &mine[1], 196, 0, SRCINVERT);break;case 4:putimage(my_x, my_y, 55, 87, &minebit[1], 263, 0, NOTSRCERASE);putimage(my_x, my_y, 55, 87, &mine[1], 263, 0, SRCINVERT);break;}}//创建子弹,给子弹补给void createbullet(){//循环给子弹赋值,及充满子弹if (time[0] >= 5000 || time[0] == -1)//当技能释放完打印子弹,或者未释放技能时{for (int i = 0; i < N; i++){if (bullet[i].live == 0){bullet[i].live = 1;//表示有子弹,未发射;每调用一次只会产生一个子弹//获取当前飞机的位置,把值赋值给子弹if (minePlan.kind == 1)//飞机1bullet[i].x = minePlan.x + 6;else//飞机2bullet[i].x = minePlan.x + 20;bullet[i].y = minePlan.y;break;//一次只发射一颗子弹;所以break结束循环}}if (minePlan.type == 2){if (time[3] == 40){for (int i = 0; i < N; i += 2)//创建副武器子弹{if (developBul[i].live == 0 && i + 2 <= 15)//子弹不存在,{developBul[i].live = 1;developBul[i + 1].live = 1;developBul[i].x = minePlan.x - 20;developBul[i].y = minePlan.y;if (minePlan.kind == 2)developBul[i + 1].x = minePlan.x + 70;elsedevelopBul[i + 1].x = minePlan.x + 50;developBul[i + 1].y = minePlan.y;break;}}}time[3] += 20;if(time[3] > 40){time[3] = 0;}}}//实时获取存在的敌军的位置,将位置赋值给敌军子弹//先创建子弹,及敌军还未产生,所有子弹均为1;而当产生第一架敌机,所有的for (int i = 0; i < NUM; i++){if (enemyPlan[i].live == 1&&enemyPlan[i].shot=='N'){for (int j = 0; j < N; j++){if (enemyBult[j].live == 2)//若果子弹库还有子弹。给改存活的敌军发射一颗子弹,每架飞机只发射一个{enemyBult[j].x = enemyPlan[i].x + 15;enemyBult[j].y = enemyPlan[i].y + 45;enemyBult[j].live = 1;enemyPlan[i].shot = 'Y';break;}}}}//补充敌军子弹库for (int i = 0; i < N; i++){if (enemyBult[i].y > HEIGHT){enemyBult[i].live = 2;}}//产生boss子弹if (num_death_enemy>= score)//当大于100时进行子弹的填充{for (int i = 0; i < BOSSBUL; i = i + 4){if (BossBul[i].live == 1){BossBul[i].live = 2;BossBul[i + 1].live = 2;BossBul[i + 2].live = 2;BossBul[i + 3].live = 2;BossBul[i].y = boss[s].y + 100;//当前boss[s].y=50,所以加上100才是飞机的顶端BossBul[i + 1].y = boss[s].y + 100;//将最新的飞机坐标给子弹BossBul[i + 2].y = boss[s].y + 100;BossBul[i + 3].y = boss[s].y + 100;BossBul[i].x = boss[s].x+60;BossBul[i + 1].x = boss[s].x+80;BossBul[i + 2].x = boss[s].x+100;BossBul[i + 3].x = boss[s].x+120;break;}}}//创建炮弹if (rand() % 10 < 1&&shell.live==0&&num_death_enemy>=10){shell.live = 1;shell.shot = 0;shell.y = -150;//防止在出现危险警告时,导弹在屏幕上未显示,但存在,使飞机碰到死亡}}//产生敌机void createEnemy(){if (num_death_enemy >= score)//boss出现{for (int i = 0; i < NUM; i++)//将所有敌军变为0;{if (enemyPlan[i].live == 1){enemyPlan[i].live = 0;}}}else {for (int i = 0; i < NUM; i++){//第一个敌机一定能产生出来if (enemyPlan[0].live == 0){enemyPlan[0].live = 1;//将敌机创造出来enemyPlan[0].x = rand() % (WIDTH - 70);//x位置随机在0-530、width=600enemyPlan[0].y = 0;enemyPlan[0].HP = 1;enemyPlan[0].type = 1;break;}//当第一个敌机存在时,开始判断下一个敌机else if (enemyPlan[i + 1].live == 0 && (i + 1) < NUM && (rand() % 10 < 7))//(i+1)<NUM不让行索超过最大值,当下一个没有产生敌军时,就结束循环{if (rand() % 10 < 4)//创造成功的概率只创建一个敌机,种类一{enemyPlan[i + 1].live = 1;//将敌机创造出来enemyPlan[i + 1].x = rand() % (WIDTH - 70);enemyPlan[i + 1].y = 0;enemyPlan[i + 1].HP = 1;enemyPlan[i + 1].type = 1;break;}else if (rand() % 10 < 2)//敌机种类二{enemyPlan[i + 1].live = 1;//将敌机创造出来enemyPlan[i + 1].x = rand() % (WIDTH - 70);//x坐标enemyPlan[i + 1].y = 0;enemyPlan[i + 1].HP = 5;enemyPlan[i + 1].type = 2;break;}else if (rand() % 10 < 5)//第三种敌机{enemyPlan[i + 1].live = 1;//将敌机创造出来enemyPlan[i + 1].x = rand() % (WIDTH - 70);//x坐标enemyPlan[i + 1].y = 0;enemyPlan[i + 1].HP = 3;enemyPlan[i + 1].type = 3;break;}break;}}}}void enemyMove(int speed) {//boss的移动if(num_death_enemy >= score){//进行自由的左右来回移动。先想右移动一段距离,再向左移动同样的距离实现,来回移动if (boss[s].y < 50){boss[s].y += 2;}if (m>0&&m<=160)//m代表移动的次数,向左移动{boss[s].x += 2;m--;}if(m<=0)//向右移动。{boss[s].x -= 2;m--;if (m == -160)//当移动了与左移动相同的距离,再变回右移动的条件m = 160;}}else{for (int i = 0; i < NUM; i++){if (enemyPlan[i].live == 1)//遍历数组,寻找存活的敌军{if (enemyPlan[i].type == 1) //判断类型,改变不同的速度{enemyPlan[i].y += speed;//只需要垂直移动}else if (enemyPlan[i].type == 2){enemyPlan[i].y += speed + 2;}else if (enemyPlan[i].type == 3){enemyPlan[i].y += speed + 1;}if (enemyPlan[i].y > HEIGHT)//当敌机超过地图时,将live变为0,在创造时,就可以继续使用{enemyPlan[i].live = 0;enemyPlan[i].shot = 'N';//是否发射子弹}}}}}//子弹发射原理,定义数组,给数组的第一个开始赋予子弹,每按一次,给一颗。通过判定数组是否有子弹进行移动,每个子弹的位置都不一样void bulletMove(int speed)//speed为子弹的移动速度 {for (int i = 0; i < N; i++)//我方子弹移动{if (bullet[i].live == 1)//子弹存在 一次只有一个子弹有,只移动一次{bullet[i].y -= speed;//子弹坐标的移动if (bullet[i].y <= 0)//当子弹超出范围时又将其值设置为0,补充我军子弹{bullet[i].live = 0;}}if (developBul[i].live == 1)//副武器{developBul[i].y -= 8;if (developBul[i].y <= 0)//超出屏幕回收{developBul[i].live = 0;}}}if (num_death_enemy < score)//boss未出现{//敌军子弹的移动,每次移动10个像素for (int i = 0; i < N; i++){if (enemyBult[i].live == 1){enemyBult[i].y += 10;}}}//boss子弹的移动for (int i = 0; i < BOSSBUL; i++){if (BossBul[i].live == 2){BossBul[i].y += 7;}if (BossBul[i].y > HEIGHT)//超过屏幕将子弹回收{BossBul[i].live = 1;}}//当飞机吃到图标时if (ico[0].live == 1){if ((minePlan.kind == 1 && ico[0].x - minePlan.x > -20 && ico[0].x - minePlan.x < 40 && ico[0].y - minePlan.y<25 && ico[0].y - minePlan.y>-40)|| (minePlan.kind == 2 && ico[0].y > minePlan.y + 20 && ico[0].y < minePlan.y + 50 && ico[0].x<minePlan.x + 60 && ico[0].x > minePlan.x)){//当飞机1号吃到图标,图标消失,飞机子弹增加副武器ico[0].live = 0;minePlan.type = 2;}}//图标的移动if (ico[0].live == 1){ico[0].x += speedx;//移动慢一点ico[0].y += speedy;//移动慢一点if (ico[0].x <= 0 || ico[0].x >= 570)speedx = -speedx;if (ico[0].y >= 670 || ico[0].y <= 0)speedy = -speedy;}//炮弹移动if (shell.live == 1&&shell.shot==1)//存在且发射出去才移动{shell.y +=15;if (shell.y > 700){shell.live = 0;shell.shot = 0;shell.y = -150;}}}int minePlayDeath(){mciSendString("pause mymusic", NULL, 0, NULL);//暂停背景音乐PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)BOOM, NULL, NULL, 0);//播放爆炸mciSendString("close death ", NULL, 0, NULL);//死亡音效mciSendString("open 死亡.mp3 alias death", NULL, 0, NULL);mciSendString("play death ", NULL, 0, NULL);minePlan.live = 0;//飞机死亡for (int i = 0;i<4; i++)//通过二维数组来实现爆炸效果{for (int j = 0;j<4; j++){drowGame();putimage(minePlan.x, minePlan.y, 64, 64, &boom2yanma[1], j * 64, i * 64,NOTSRCERASE);putimage(minePlan.x, minePlan.y, 64, 64, &boom2[1], j * 64, i * 64, SRCINVERT);FlushBatchDraw();Sleep(100);}}putimage(126,312,&relive, SRCPAINT);FlushBatchDraw();system("pause");while (1)//选择死亡后是否复活{if (_getch() == 'x')//按下键复活{mciSendString("resume mymusic", NULL, 0, NULL);minePlan.x = WIDTH / 2;minePlan.y = 500;minePlan.live = 1;condition = 1;return 1;}else{minePlan.live = 0;return 0;}}//return 0;}int bossDeath(){boss[s].live = 0;for (int i = 0; i < BOSSBUL; i++){BossBul[i].live = 0;}PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//关闭子弹音效CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)BOOM, NULL, NULL,0);//播放爆炸mciSendString("close victory ", NULL, 0, NULL);//胜利音效mciSendString("open 胜利.mp3 alias victory", NULL, 0, NULL);mciSendString("play victory ", NULL, 0, NULL);for (int i = 0; i < 4; i++)//通过二维数组来实现爆炸效果{for (int j = 0; j < 4; j++){drowGame();//刷新地图中的其他图片putimage(boss[s].x, boss[s].y, 150, 150, &boom2yanma[0], j * 150, i * 150, NOTSRCERASE);putimage(boss[s].x, boss[s].y, 150, 150, &boom2[0], j * 150, i * 150, SRCINVERT);FlushBatchDraw();Sleep(150);}}return 0;}void Score(int i){CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)BOOM, NULL, NULL, 0);//敌机爆炸音效线程enemy_x = enemyPlan[i].x;//记录敌机爆炸的位置,给敌机爆炸效果定位enemy_y = enemyPlan[i].y;enemyPlan[i].shot = 'N';enemyPlan[i].live = 0;//敌人死亡num_death_enemy++;//统计死亡敌机数if (enemyPlan[i].type == 1)//判断敌机类型增加分数minePlan.score += 10;else if (enemyPlan[i].type == 2)minePlan.score += 30;else if (enemyPlan[i].type == 3)minePlan.score += 20;}int deadth()//判断死亡{if (num_death_enemy >= score)//boss出现{//打中boss的判断for (int i = 0; i < N; i++){if (bullet[i].live == 1)//表示已发射的子弹{if (bullet[i].x - boss[s].x > 0 && bullet[i].x - boss[s].x < 170 && bullet[i].y - boss[s].y < 130 && bullet[i].y - boss[s].y>5){bullet[i].live = 0;boss[s].HP -= 1;BloodWidth -= 3;//boss血量条图片的宽度减少if (boss[s].HP <= 0)//boss血量为小于0时{return bossDeath();}}}//副武器判断if (developBul[i].live == 1){if (developBul[i].x - boss[s].x > 50 && developBul[i].x - boss[s].x < 170 && developBul[i].y - boss[s].y < 130 && developBul[i].y - boss[s].y>5){boss[s].HP -= 2;BloodWidth -= 6;developBul[i].live = 0;if (boss[s].HP <= 0)//boss血量为0时return bossDeath();}}}//boss子弹击中我方if (condition != 1)//为1飞机处于无敌状态{for (int i = 0; i < BOSSBUL; i++){if (BossBul[i].live == 2)//已发射的子弹{if ((minePlan.kind == 1 && BossBul[i].x - minePlan.x > -5 && BossBul[i].x - minePlan.x < 45 && BossBul[i].y - minePlan.y>5 && BossBul[i].y - minePlan.y < 50)|| (minePlan.kind == 2 && BossBul[i].x - minePlan.x > -5 && BossBul[i].x - minePlan.x < 65 && BossBul[i].y - minePlan.y>15 && BossBul[i].y - minePlan.y < 70))//被boss子弹击中{return minePlayDeath();}}}}//我方与boss碰撞if ((minePlan.kind == 1 && boss[s].x < minePlan.x -20 && boss[s].x+200 > minePlan.x-50 && boss[s].y +100> minePlan.y && boss[s].y+20< minePlan.y)|| (minePlan.kind == 2 && boss[s].x < minePlan.x - 30 && boss[s].x + 200 > minePlan.x - 50 && boss[s].y + 100 > minePlan.y&& boss[s].y + 20 < minePlan.y))//被boss子弹击中){return minePlayDeath();}}else//boss未出现{for (int i = 0; i < NUM; i++){if (enemyPlan[i].live == 1)//寻找存活的敌机{for (int j = 0; j < N; j++)//遍历子弹,判断子弹是否命中该存活敌机{//子弹击中敌机,子弹归0,PH=0敌机死亡;if (bullet[j].live == 1)//若果子弹已发射{if (bullet[j].x - enemyPlan[i].x > -15 && bullet[j].x - enemyPlan[i].x < 40 && bullet[j].y - enemyPlan[i].y < 45 && bullet[j].y - enemyPlan[i].y>5){enemyPlan[i].HP = enemyPlan[i].HP - 1;bullet[j].live = 0;if (enemyPlan[i].HP <= 0){Score(i);//播放敌机爆炸音效并记录分数}}}}for (int j = 0; j < N; j++)//副武器打中敌机{if (developBul[j].live == 1)//已发射的子弹{if (developBul[j].x - enemyPlan[i].x > -5 && developBul[j].x - enemyPlan[i].x < 45 && developBul[j].y - enemyPlan[i].y>5 && developBul[j].y - enemyPlan[i].y < 45)//被boss子弹击中{enemyPlan[i].HP = enemyPlan[i].HP - 2;developBul[j].live = 0;if (enemyPlan[i].HP <= 0){Score(i);}}}}if (condition != 1){//当己方飞机碰到敌方飞机时死亡if ((minePlan.kind == 1 && abs(minePlan.x - enemyPlan[i].x) < 40 && abs(minePlan.y - enemyPlan[i].y) < 40)|| (minePlan.kind == 2 && enemyPlan[i].y > minePlan.y&& enemyPlan[i].y < minePlan.y + 60 && enemyPlan[i].x > minePlan.x - 20 && enemyPlan[i].x < minePlan.x + 65))//abs取整数绝对值{//outtextxy(minePlan.x, minePlan.y, "双击x复活,按z结束游戏")return minePlayDeath();}}}}//我方被敌方子弹击中死亡if (condition != 1){for (int i = 0; i < N; i++)//遍历敌方子弹判断是否存活{if (enemyBult[i].live == 1){if ((minePlan.kind == 1 && enemyBult[i].x - minePlan.x > 5 && enemyBult[i].x - minePlan.x < 30 && enemyBult[i].y - minePlan.y>5 && enemyBult[i].y < minePlan.y + 40)|| (minePlan.kind == 2 && enemyBult[i].x - minePlan.x > -5 && enemyBult[i].x - minePlan.x < 65 && enemyBult[i].y - minePlan.y>15 && enemyBult[i].y - minePlan.y < 70)){//子弹击中我方时//enemyBult[i].live = 0;//enemyBult[i].y = -50;return minePlayDeath();}}}}}if (time[0] < 5000 && time[0] >= 0)//技能正在释放的时候{for (int i = 0; i < NUM; i++)//判断敌机是否有存活的{if (enemyPlan[i].live == 1){if (minePlan.x - enemyPlan[i].x < 40 && minePlan.x - enemyPlan[i].x > -50&&minePlan.y>enemyPlan[i].y )//技能击中敌机{enemyPlan[i].HP -= 3;//血量减三if (enemyPlan[i].HP <= 0){Score(i);}}}}if (num_death_enemy >= score){if (minePlan.x - boss[s].x < 175 && minePlan.x - boss[s].x > -75 && minePlan.y > boss[s].y)//技能击中敌机{boss[s].HP -= 1;BloodWidth -= 3;//boss血量条图片的宽度减少if (boss[s].HP <= 0)//boss血量为0时{return bossDeath();}}}}if (num_death_enemy == fen)//当敌机死亡数达到指定时 //调用产生图标的函数{up();fen -= 1;//若果不减,并且敌机死亡数不增加,则图标不会移动}//炮弹撞上飞机if (condition != 1){if ((minePlan.kind == 1 && shell.x > minePlan.x - 50 && shell.x<minePlan.x + 30 && shell.y>minePlan.y - 110 && shell.y < minePlan.y + 20)|| (minePlan.kind == 2 && shell.x > minePlan.x - 50 && shell.x<minePlan.x + 45 && shell.y > minePlan.y - 110 && shell.y < minePlan.y + 60)){return minePlayDeath();}}return 1;}char GameOver()//游戏结束后{PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//停止子弹音乐mciSendString("pause mymusic", NULL, 0, NULL);//停止背景音乐count = 0;//数组下标初始化为零putimage(0, 0, &map[2]);//打印图片img_x = 210;img_y = 275;OutScore(minePlan.score);//输出分数img_x = 210;img_y = 155;OutScore(num_death_enemy);//输出击杀数量FlushBatchDraw();MOUSEMSG end_mouse;while (1){end_mouse = GetMouseMsg();if (end_mouse.uMsg == WM_LBUTTONDOWN)//左键点下{if (end_mouse.x > 146 && end_mouse.x < 435 && end_mouse.y < 626 && end_mouse.y>550)//返回主菜单{return 'D';}if (end_mouse.x > 146 && end_mouse.x < 435 && end_mouse.y < 466 && end_mouse.y>390)//重新开始游戏{return 'R';}}}return 0;}int timeout()//暂停{//putimage(140, 165, &cue[0]);putimage(0, 0, &cue[0]);FlushBatchDraw();mciSendString("pause mymusic", NULL, 0, NULL);//暂停背景音乐PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//暂停子弹音效MOUSEMSG n;//定义鼠标变量while (1){while (MouseHit()){n = GetMouseMsg();if (n.uMsg == WM_LBUTTONDOWN){if (n.x > 190 && n.x < 410 && n.y> 243 && n.y < 320)//点击继续{mciSendString("resume mymusic", NULL, 0, NULL);return 0;}else if (n.x > 190 && n.x < 410 && n.y> 400 && n.y < 481 )//点击退出,返回主菜单{return 1;}}}}}//保存游戏数据,保存数据并退出void DataConserve(){FILE* fp1;FILE* fp;//定义文件指针char str[10];int num_str;if ((fp1 = fopen("GameData\\data.text", "r")) == NULL);else{fgets(str, 9, fp1);//获取历史记录num_str = atoi(str);//将字符串转为整型}fclose(fp1);if ((fp = fopen("GameData\\data.text", "w+")) == NULL)//打开或创建文件失败时,fopen会返回NULL,成功则返回文件的首地址{exit(1);//退出程序}_itoa_s(minePlan.score>num_str?minePlan.score:num_str, str, 10);//后面的10是装换的进制数,不能跨平台,跨平台需使用sprintf_s();fputs(str, fp);//将数据保存fclose(fp);//关闭文件指针}void OutScore(int number)//在指定地方输出数字图片{if (number / 10 != 0)//不是个位数{OutScore(number / 10);Num[count++] = number % 10;}else//是各位数,每次输出只会执行一次,开始为个位数或者分解到最后运行一次,{Num[count++] = number;}putimage(img_x, img_y, 17, 22, &shuziyama[0], Num[count-1] * 17, 0, NOTSRCERASE);putimage(img_x, img_y, 17, 22, &shuzi[0], Num[count - 1] * 17, 0, SRCINVERT);img_x += 17;//改变图片的x坐标}//画出游戏图片void drowGame(){putimage(0, 0, &map1);//打印出地图//putimage(0, 0, 600, 700, &map[3], 0, px[0]++);//动态地图//if (px[0] >= 440)// = 0;//putimage(0, 700 - (px[0] - 400), 600, 700, &map[3], 0, 0);if (minePlan.kind == 1&&minePlan.live==1)//判断飞机类型打印相应的图片{putimage(minePlan.x, minePlan.y, &minebit[0], NOTSRCERASE);putimage(minePlan.x, minePlan.y, &mine[0], SRCINVERT);}else if(minePlan.kind == 2 && minePlan.live == 1){if (GetKeyState(VK_LEFT) < 0 )//判断移动的方向打印图片my_2 = 3;else if (GetKeyState(VK_RIGHT) < 0 )my_2 = 1;elsemy_2 = 2;showMyPlan(minePlan.x, minePlan.y);//飞机2号}//打印子弹if (time[0] >= 5000 || time[0] == -1)//当技能释放完打印子弹,或者未释放技能时{if (time[1] >= 1500 || time[1] == 0)//{for (int i = 0; i < N; i++){if (bullet[i].live == 1){putimage(bullet[i].x, bullet[i].y, &zidan, SRCPAINT);}}}}//打印分数//char k[15];//_itoa_s(minePlan.score, k, 10);//将数字转为字符串//outtextxy(400, 50, k );//打印int类型有问题,打印字符串没问题count = 0;img_x = 456;img_y = 20;OutScore(minePlan.score);if (num_death_enemy >= score&&boss[s].live==1)//打印boss,和boss子弹{//BloodWidth = BloodWidth + 20;putimage(boss[s].x, boss[s].y, &enemy[5], NOTSRCERASE);putimage(boss[s].x, boss[s].y, &enemy[4], SRCINVERT);for (int i = 0; i < BOSSBUL; i++){if (BossBul[i].live == 2){putimage(BossBul[i].x , BossBul[i].y, &enemybul, SRCPAINT);putimage(BossBul[i].x , BossBul[i].y, &enemybul, SRCPAINT);putimage(BossBul[i].x , BossBul[i].y, &enemybul, SRCPAINT);putimage(BossBul[i].x , BossBul[i].y, &enemybul, SRCPAINT);}}putimage(-10, 20, &blood[0], SRCPAINT);putimage(BloodWidth, 20, &blood[1], SRCPAINT);}else{//打印敌机for (int i = 0; i < NUM; i++){//遍历敌机数组,判断哪些为存活就输出if (enemyPlan[i].live == 1){if (enemyPlan[i].type == 1){putimage(enemyPlan[i].x, enemyPlan[i].y, &enemy[0], NOTSRCERASE);//掩码图putimage(enemyPlan[i].x, enemyPlan[i].y, &enemy[1], SRCINVERT);}else if (enemyPlan[i].type == 2){putimage(enemyPlan[i].x, enemyPlan[i].y, &enemy[3], NOTSRCERASE);;//掩码图putimage(enemyPlan[i].x, enemyPlan[i].y, &enemy[2], SRCINVERT);}else if (enemyPlan[i].type == 3){showEnemy2(enemyPlan[i].x,enemyPlan[i].y);time[4] += 20;if (time[4] > 100){ene_2 += 1;time[4] = 0;}if (ene_2 >= 5)ene_2 = 0;}}}//打印敌机子弹int num = 0;for (int i = 0; i < N; i++){//子弹发射后,live值变为1;表示以发射if (enemyBult[i].live == 1){putimage(enemyBult[i].x, enemyBult[i].y, &enemybul, SRCPAINT);}}}//time[0]用于计算技能释放的时间,time[1]用于计算道具冷却的时间,show用于判断道具是否使用及显示//技能释放动画if (time[0] < 5000 && time[0] >= 0)//按下技能键,释放技能的时间5秒{if (t7 - t8 > 50)//多久切换一张图片{t8 = t7;//t7为当前最新的时间jj++;if (jj >=6)//当图片输完时,变成第一张循环绘制{jj = 0;}}t7 = GetTickCount();if (minePlan.kind == 1)//判断飞机的种类,计算技能释放的位置{putimage(minePlan.x - 7, minePlan.y - 700, &waryanma[0], NOTSRCERASE);putimage(minePlan.x - 7, minePlan.y - 700, &war[jj], SRCINVERT);}else{putimage(minePlan.x+8, minePlan.y - 700, &waryanma[0], NOTSRCERASE);putimage(minePlan.x+8, minePlan.y - 700, &war[jj], SRCINVERT);}FlushBatchDraw();time[0] += 20;//计算技能释放的时间;time[1] += 20;//计算技能能却的时间}else if (time[0] >= 5000 && time[0] < 15000)//技能冷却的时间10秒{time[1] += 20;//计算恢复的时间}if (time[1] > 15000)//技能冷却完成{time[1] = 0;time[0] = -1;show = 1;}if(show==1)//展示技能图标{putimage(10, 500, &jineng[0], SRCPAINT);}//武器升级1for (int i = 0; i < N; i++){if (developBul[i].live == 1)//子弹存在才发射{putimage(developBul[i].x, developBul[i].y, &img_developBul[0], NOTSRCERASE);//掩码putimage(developBul[i].x, developBul[i].y, &img_developBul[1], SRCINVERT);}}//敌机爆炸效果动画if (enemy_x >= 0){putimage(enemy_x, enemy_y, &boomyanma[x], NOTSRCERASE);putimage(enemy_x, enemy_y, &boom[x], SRCINVERT);}//控制图片切换的时间if (t5 - t6>50){t6 = t5;x++;if (x >= 11)//到最后一张后循环{x = 7;enemy_x = -1;//初始坐标为负值enemy_x = -1;}}t5= GetTickCount();//显示升级图标if (ico[0].live == 1){putimage(ico[0].x, ico[0].y, &tubiao[2], NOTSRCERASE);putimage(ico[0].x, ico[0].y, &tubiao[3], SRCINVERT);}//画出危险图标if (shell.live == 1&&shell.shot==0){putimage(minePlan.x, 0, &tubiao[6], NOTSRCERASE);putimage(minePlan.x, 0, &tubiao[7], SRCINVERT);time[5] += 20;if (time[5] >= 2000)//控制危险图标持续的时间{time[5] = 0;shell.shot = 1;shell.x = minePlan.x;}}//画出炸弹if (shell.shot == 1)//判断导弹是否发射{putimage(shell.x, shell.y, &bomb[1],NOTSRCERASE);putimage(shell.x, shell.y, &bomb[0], SRCINVERT);}//打印护盾if (condition == 1){if (minePlan.kind == 1)putimage(minePlan.x-20, minePlan.y-20, &hudun, SRCPAINT);else if(minePlan.kind == 2)putimage(minePlan.x-7, minePlan.y, &hudun, SRCPAINT);time[6] += 20;if (time[6] > 5000){condition = 0;time[6] = 0;}}}int keyDown(IMAGE* map1,int speed)//操作按键判断{//a = GetKeyState(VK_UP);//该函数通过获取虚键来判断键盘是否按下srand(GetTickCount());//随机数种子if (GetKeyState(VK_UP)< 0&&minePlan.y>0)//minePlan.y>0,限制飞机的移动范围{minePlan.y -= speed;}else if (GetKeyState(VK_LEFT)<0&&minePlan.x>-15){minePlan.x -= speed;}else if (GetKeyState(VK_RIGHT) < 0&&minePlan.x <WIDTH-36){minePlan.x += speed;}else if (GetKeyState(VK_DOWN) < 0 && minePlan.y < HEIGHT-50){minePlan.y += speed;}else if(GetKeyState(VK_ESCAPE) < 0){return 1;}else if (GetKeyState(VK_SPACE) < 0){return 2;}else if (GetKeyState('H') < 0&& show == 1)//按下H键释放技能{show = 0;//表示技能使用了,技能图标不再显示time[0] = 0;}if ((t4 - t3) > (rand() % 500 + 800))//控制敌机产生的时间 间隔{createEnemy();t3 = t4;}t4 = GetTickCount();enemyMove(3);//敌机的产生和移动,同样每次只产生一个通过循环使用移动函数,实现移动if (t2-t1>200)//后面为判定多久时间发射一枚子弹获取当前系统的运行时间GetKeyState(VK_CONTROL) < 0{t1 = t2; createbullet();//当按下攻击键时,给子弹填充一个,下面的bulletMove()函数才会有效果//播放子弹发射的音效,播放之后需要关掉,才能重新播放//mciSendString("close gun", 0, 0, 0);//mciSendString("open ./Beam.wav alias gun", 0, 0, 0);//mciSendString("play gun", 0, 0, 0);//time[3] += 20;if ( time[0] >= 5000 || time[0] == -1){PlaySound(TEXT("Beam.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);}else//当释放技能时不播放子弹的声音{PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_PURGE);PlaySound(TEXT("baozou.wav"), NULL, SND_FILENAME | SND_ASYNC);//PlaySound(TEXT("laser shot.mp3"), NULL, SND_FILENAME | SND_ASYNC);CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tttt, NULL, NULL, 0);//调用线程,被其他什么东西占用了,暂停时可以播放完整的}}t2 = GetTickCount();bulletMove(10); //发射子弹 //重复执行该函数if (deadth() == 0)return 3;return 0;}

这个小游戏代码超过1300行,分为了3个文件。其中AirGame.cpp文件中将多种功能合并在一个函数之中,读者可根据需求将各种功能分成多个函数,而不是小编这样合并在一起。代码的注释已经足够详细。读者可以借鉴一下,根据自己的思考将部分功能以自己的逻辑实现。

新手学习中…

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。