佛山网站建设公司哪家便宜,域名过期的网站怎么看,威海优化公司立找2火星,做网站是前端还是后端前言#xff1a;
飞机大作战游戏是一种非常受欢迎的射击类游戏#xff0c;玩家需要控制一架战斗机在屏幕上移动#xff0c;击落敌机以获得分数。本游戏使用C语言编写#xff0c;旨在帮助初学者了解游戏开发的基本概念和技巧。
在开始编写代码之前#xff0c;我们需要先了…前言
飞机大作战游戏是一种非常受欢迎的射击类游戏玩家需要控制一架战斗机在屏幕上移动击落敌机以获得分数。本游戏使用C语言编写旨在帮助初学者了解游戏开发的基本概念和技巧。
在开始编写代码之前我们需要先了解一下游戏的基本规则和功能 游戏界面游戏界面是一个矩形区域玩家可以在这个区域内控制战斗机移动和射击。 战斗机玩家控制的战斗机可以在游戏界面内自由移动按下特定键可以发射子弹和开启技能击落敌机。 敌机敌机会从屏幕的一侧出现并沿着直线路径向另一侧移动。玩家需要击落敌机以获得分数。 分数玩家每击落一架敌机分数会增加。 游戏结束当玩家飞机被敌机撞到到或者得分为0时游戏结束。
接下来我们将通过以下几个步骤来实现这个游戏 初始化游戏界面和战斗机。 处理键盘输入实现战斗机的移动和射击。 生成敌机并控制其移动。 检测战斗机与敌机之间的碰撞更新分数和技能充能值。 判断游戏是否结束。
通过学习这个游戏的开发过程初学者将能够掌握C语言编程的基本技巧。
1. 打印菜单
void menu()
{printf(--------------飞机大作战--------------\n);printf(| |\n);printf(| 1.开始游戏 |\n);printf(| 0.退出游戏 |\n);printf(| W/A/S/D移动 |\n);printf(| 空格射击 E/R技能 |\n);printf(| |\n);printf(--------------------------------------\n);
}
int main()
{system(color b);int input 0;menu();printf(请选择:);scanf(%d, input);switch (input){case 1:game();break;case 0:printf(退出游戏\n);break;default:printf(输入有误请重新输入:\n);break;}return 0;
}
2. 写一个存放信息的数组 int arr[Col][Row] { 0 };3. 写一个打印数组信息的函数
飞机大作战的要素无非就是路、围墙、玩家飞机、敌机、子弹这五个元素要想在打印出这几个元素我们只需在写一个函数在二维数组中存放这个五个元素的信息用0-4代替然后再写一个打印信息的函数分别出二维数组中对应的信息。
void DisPlay(int arr[Col][Row])
{gotoxy(0, 0);for(int i0;iCol;i){for (int j 0; j Row; j){if (arr[i][j] 0){printf( );}if (arr[i][j] 1){printf(█);}if (arr[i][j] 2){printf(*);}if (arr[i][j] 3){printf($);}if (arr[i][j] 4){printf(|);}}printf(\n);}printf(得分%d , score);printf(EnemySleep%d , EnemySleep);printf(skill1(20)%d , skill1);printf(skill2(5)%d , skill2);Sleep(20);
}
4. 写一个函数来初始化数组的信息
void InSet(int arr[Col][Row])
{//路--0//墙--1//玩家飞机--2//敌机--3//子弹--4
}
5. 初始化围墙
数组最边边的位置我们都让它等于1这样就可以把游戏界面围起来了。
//墙--1
for (int i 0; i Col; i)
{arr[i][0] 1;arr[i][Row - 1] 1;
}
for (int i 0; i Row; i)
{arr[0][i] 1;arr[Col - 1][i] 1;
} 6. 初始化玩家飞机
玩家飞机刚开始应该出现在下侧的中央位置所以将这个位置的坐标对应的值初始化为2。
//玩家飞机--2
arr[PlayerPlane_y][PlayerPlane_x] 2;
7. 玩家操作飞机 通过按下A/W/S/D键来控制飞机的移动空格键来控制飞机发射子弹要想实现这个功能我们需要用到getch函数这个函数用于从标准输入通常是键盘获取一个字符而不需要用户按下回车键。这个函数在Windows操作系统下的conio.h头文件中定义而在Unix/Linux系统下通常使用termios.h和unistd.h头文件中的函数来实现类似的功能。 char ch getch();
if (ch w arr[PlayerPlane_y - 1][PlayerPlane_x] 0)
{arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_y--;arr[PlayerPlane_y][PlayerPlane_x] 2;
}
if (ch a arr[PlayerPlane_y][PlayerPlane_x - 1] 0)
{arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_x--;arr[PlayerPlane_y][PlayerPlane_x] 2;
}
if (ch s arr[PlayerPlane_y 1][PlayerPlane_x] 0)
{arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_y;arr[PlayerPlane_y][PlayerPlane_x] 2;
}
if (ch d arr[PlayerPlane_y][PlayerPlane_x 1] 0)
{arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_x;arr[PlayerPlane_y][PlayerPlane_x] 2;
}
if (ch )
{Bullet_y PlayerPlane_y - 1;Bullet_x PlayerPlane_x;arr[Bullet_y][Bullet_x] 4;
}
}
8. 子弹上移
子弹上移一格就调用一次DisPlay函次arr[][]二维数打印一数组的内容这样就实现了子弹上移的效果这时使用到我们的while循环来循环子弹上移的函数和打印的函数而子弹是由玩家按键产生的所以这个while还需要循环上玩家操作飞机的函数但是getch会让while停止下来玩家按键后才会继续导致玩家按一次键盘按键子弹才会上移一次这样就子弹就出现不了的连续上移的效果了所以我们需要在玩家操作的函数加上if(_kbhit())的判断语句函数它会判断是否有按键按下来如果没有就不执行getch函数继续循环。 _kbhit() 是一个C语言中的函数用于检测键盘是否有按键被按下。它通常在Windows操作系统下的conio.h头文件中定义。该函数不接受任何参数并返回一个整数值。如果键盘上有按键被按下则返回非零值通常是1否则返回0。 while (1)
{//玩家操作PlayerPlay(arr);//打印棋盘DisPlay(arr);//子弹与敌机的操作BulletEnemy(arr);
}
在循环打印的时候它会框框打印根本就看不清游戏界面所以在这里还需要使用到光标的知识 在C语言中光标通常指的是控制台或终端中的文本输入位置指示器。它显示了用户当前输入或输出的位置。在编写C程序时有时需要对光标的显示和位置进行控制以便创建更复杂的用户界面或处理特定的输入输出需求。 在Windows操作系统下可以使用conio.h头文件中提供的函数来控制光标。 因为它会在光标的位置输出信息所以我们在每次打印前将光标的位置置为0,0就可以了。
但是光标还会在那框框的闪非常的碍眼所以我们还需要使用函数将光标隐藏。
void HideCursor()
{CONSOLE_CURSOR_INFO cursor_info { 1,0 }; //第二个值为0表示隐藏光标SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), cursor_info);
}
9. 初始化敌机
在这里我们需要随机生成5架敌机出现在游戏界面的上侧1-3格的位置所以需要使用一个大小为5的数组接受随机数的值。
//敌机--3
for (int i 0; i Count; i)
{Enemy_y[i] rand() % 3 1;Enemy_x[i] rand() % Row 1;//防止敌机生成在围墙上if (Enemy_x[i] Row - 1)Enemy_x[i] - 2;arr[Enemy_y[i]][Enemy_x[i]] 3;
}
10. 敌机的下移
如果敌机也像子弹一样直接进去循环的话那么敌机会移动得非常快所以我们需要定义两个全局变量sleep和EnemySleep来控制敌机的移动速度例如给EnemySleep赋值一个20然后sleep赋值一个0随后sleep在while循环中循环一次就加1当sleep等于EnemySleep时我们才给敌机进行一次下移的操作这样就相当于while每循环20次敌机才下移一次。
在敌机下的过程中我们可能无法打中敌机而使敌机下降到了最下侧这时就得让敌机在触碰到围墙前一格消失然后重新在上侧生成新的敌机。
在敌机下移的过程中可能会碰到玩家的飞机这时游戏就得结束了然后告诉玩家游戏结束。控制游戏结束需要用到system(pause)和exit这两个函数。 system(pause)的作用是在Windows系统的命令行窗口中暂停程序的执行等待用户按下任意键后继续执行。这通常用于调试程序时以便查看程序运行过程中的输出结果。 exit(0);是C/C语言中用于终止程序执行的语句。其中参数0表示程序正常退出非零值表示程序异常退出。在程序执行到该语句时程序会立即停止运行并返回给操作系统一个退出状态码。 //控制敌机的速度
if (sleep EnemySleep)
{sleep;
}
else if (sleep EnemySleep)
{sleep 0;
}
for (int i 0; i Count; i)
{//敌机击中玩家飞机的处理if (PlayerPlane_y Enemy_y[i] PlayerPlane_x Enemy_x[i] || score 0){printf( /\\_/\\ \n);printf( ( o.o ) \n);printf( ^ \n);printf(游戏失败\n);printf(\a);system(pause);exit(0);}//敌机到达最底面的处理if (Enemy_y[i] Col - 2){score - 100;arr[Enemy_y[i]][Enemy_x[i]] 0;Enemy_y[i] rand() % 3 1;Enemy_x[i] rand() % Row 1;if (Enemy_x[i] Row - 1)Enemy_x[i] - 2;arr[Enemy_y[i]][Enemy_x[i]] 3;}//敌机下移的处理if (sleep EnemySleep){for (int j 0; j Count; j){arr[Enemy_y[j]][Enemy_x[j]] 0;sleep 0;Enemy_y[j];arr[Enemy_y[j]][Enemy_x[j]] 3;}}
} 11. 游戏数值的设定
1敌机加速的分数阈值
当玩家得分达到 2000 分时敌机的移动速度增加 2当玩家得分再次增加 2000 分即达到 4000 分时敌机的移动速度再增加 2以此类推每当玩家得分增加 2000 分敌机的速度增加 2。
2打爆一架敌机的得分
打爆一架普通敌机玩家得到 100 分。
3一架敌机到底部消失的失分
如果一架敌机到达屏幕底部而未被击落玩家失去 100 分。
12. 游戏的优化
为了使游戏更具可玩性我们可以给玩家飞机加上一些技能在这里的我设定了E/R是释放技能的指令这个加在玩家操作飞机哪里就可以了这两个都是技能可发射范围更广的子弹当然了这几技能也不是无线释放的我们可以设定一个变量来存放技能的充能值打爆一架敌机我们就给充能值加1当这个值达到一定的我们所规定的值时才能接受释放技能的指令。
//技能指令
if (ch r)
{if (skill1 20){for (int i 1; i Row - 1; i){skill1 0;Bullet_y PlayerPlane_y - 1;Bullet_x i;arr[Bullet_y][Bullet_x] 4;}}
}
if (ch e)
{int left PlayerPlane_x - 3;int right PlayerPlane_x 3;if (skill2 5){for (int i left; i right; i){if (i 0 i Row - 1){skill2 0;Bullet_y PlayerPlane_y - 1;Bullet_x i;arr[Bullet_y][Bullet_x] 4;}}}
}
源码
#define _CRT_SECURE_NO_WARNINGS 1
#includestdio.h
#includestdlib.h
#includeconio.h
#includeWindows.h
#includetime.h
#define Count 5
#define Col 40//列
#define Row 40//行
//玩家飞机坐标
int PlayerPlane_y Col - 2;
int PlayerPlane_x Row / 2 - 1;
//子弹坐标
int Bullet_y;
int Bullet_x;
//敌机坐标
int Enemy_y[Count] { 0 };
int Enemy_x[Count] { 0 };
//敌机的移动速度
int EnemySleep 20;
int sleep 0;
//分数
int score 0;
//技能充能
int skill1 20;
int skill2 5;
void menu()
{printf(--------------飞机大作战--------------\n);printf(| |\n);printf(| 1.开始游戏 |\n);printf(| 0.退出游戏 |\n);printf(| W/A/S/D移动 |\n);printf(| 空格射击 E/R技能 |\n);printf(| |\n);printf(--------------------------------------\n);
}//隐藏光标
void HideCursor()
{CONSOLE_CURSOR_INFO cursor_info { 1,0 }; //第二个值为0表示隐藏光标SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), cursor_info);
}// 光标移到(X, Y)位置
void gotoxy(int x, int y)
{HANDLE handle GetStdHandle(STD_OUTPUT_HANDLE);COORD pos;pos.X x;pos.Y y;SetConsoleCursorPosition(handle, pos);
}void DisPlay(int arr[Col][Row])
{gotoxy(0, 0);for(int i0;iCol;i){for (int j 0; j Row; j){if (arr[i][j] 0){printf( );}if (arr[i][j] 1){printf(█);}if (arr[i][j] 2){printf(*);}if (arr[i][j] 3){printf($);}if (arr[i][j] 4){printf(|);}}printf(\n);}printf(得分%d , score);printf(EnemySleep%d , EnemySleep);printf(skill1(20)%d , skill1);printf(skill2(5)%d , skill2);Sleep(20);
}void InSet(int arr[Col][Row])
{srand(time(NULL));//路--0//墙--1for (int i 0; i Col; i){arr[i][0] 1;arr[i][Row - 1] 1;}for (int i 0; i Row; i){arr[0][i] 1;arr[Col - 1][i] 1;}//玩家飞机--2arr[PlayerPlane_y][PlayerPlane_x] 2;//敌机--3for (int i 0; i Count; i){Enemy_y[i] rand() % 3 1;Enemy_x[i] rand() % Row 1;if (Enemy_x[i] Row - 1)Enemy_x[i] - 2;arr[Enemy_y[i]][Enemy_x[i]] 3;}//子弹--4
}
void PlayerPlay(int arr[Col][Row])
{if (_kbhit())//判断是否有按键按下{char ch getch();if (ch w arr[PlayerPlane_y - 1][PlayerPlane_x] 0){arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_y--;arr[PlayerPlane_y][PlayerPlane_x] 2;}if (ch a arr[PlayerPlane_y][PlayerPlane_x - 1] 0){arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_x--;arr[PlayerPlane_y][PlayerPlane_x] 2;}if (ch s arr[PlayerPlane_y 1][PlayerPlane_x] 0){arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_y;arr[PlayerPlane_y][PlayerPlane_x] 2;}if (ch d arr[PlayerPlane_y][PlayerPlane_x 1] 0){arr[PlayerPlane_y][PlayerPlane_x] 0;PlayerPlane_x;arr[PlayerPlane_y][PlayerPlane_x] 2;}if (ch ){Bullet_y PlayerPlane_y - 1;Bullet_x PlayerPlane_x;arr[Bullet_y][Bullet_x] 4;}if (ch r){if (skill1 20){for (int i 1; i Row - 1; i){skill1 0;Bullet_y PlayerPlane_y - 1;Bullet_x i;arr[Bullet_y][Bullet_x] 4;}}}if (ch e){int left PlayerPlane_x - 3;int right PlayerPlane_x 3;if (skill2 5){for (int i left; i right; i){if (i 0 i Row - 1){skill2 0;Bullet_y PlayerPlane_y - 1;Bullet_x i;arr[Bullet_y][Bullet_x] 4;}}}}}
}
void BulletEnemy(int arr[Col][Row])
{for (int i 0; i Col; i){for (int j 0; j Row; j){if (arr[i][j] 4){for (int k 0; k Count; k){//子弹击中敌机的处理if (i Enemy_y[k] j Enemy_x[k]){if (skill1 20){skill1;}if (skill2 5){skill2;}score 100;arr[Enemy_y[k]][Enemy_x[k]] 0;Enemy_y[k] rand() % 3 1;Enemy_x[k] rand() % Row 1;if (Enemy_x[k] Row - 1)Enemy_x[k] - 2;arr[Enemy_y[k]][Enemy_x[k]] 3;//每2000分敌机加速if (score % 2000 0 EnemySleep 4){EnemySleep - 2;}}}//子弹的移动if (arr[i][j] 4){arr[i][j] 0;if (i 1){arr[i - 1][j] 4;}}}}}//敌机的移动if (sleep EnemySleep){sleep;}else if (sleep EnemySleep){sleep 0;}for (int i 0; i Count; i){if (PlayerPlane_y Enemy_y[i] PlayerPlane_x Enemy_x[i] || score 0){printf( /\\_/\\ \n);//敌机击中玩家飞机的处理printf( ( o.o ) \n);printf( ^ \n);printf(游戏失败\n);printf(\a);system(pause);exit(0);}//敌机到达最底面的处理if (Enemy_y[i] Col - 2){score - 100;arr[Enemy_y[i]][Enemy_x[i]] 0;Enemy_y[i] rand() % 3 1;Enemy_x[i] rand() % Row 1;if (Enemy_x[i] Row - 1)Enemy_x[i] - 2;arr[Enemy_y[i]][Enemy_x[i]] 3;}//敌机下移的处理if (sleep EnemySleep){for (int j 0; j Count; j){arr[Enemy_y[j]][Enemy_x[j]] 0;sleep 0;Enemy_y[j];arr[Enemy_y[j]][Enemy_x[j]] 3;}}}}void game()
{//设置一个存放信息的数组int arr[Col][Row] { 0 };//隐藏光标HideCursor();//放置信息InSet(arr);//打印游戏界面DisPlay(arr);//玩家移动while (1){//玩家操作PlayerPlay(arr);//打印棋盘DisPlay(arr);//子弹与敌机的操作BulletEnemy(arr);}
}
int main()
{system(color b);int input 0;menu();printf(请选择:);scanf(%d, input);switch (input){case 1:game();break;case 0:printf(退出游戏\n);break;default:printf(输入有误请重新输入:\n);break;}return 0;
}
最终效果 飞机大作战