提示:新人入坑,采用的新手模板草草写就,望谅解
前言
在做课下的游戏设计作业时,因为一时乐趣加入了一些功能,最后的完成代码可玩性不错,于是决定分享出来。
提示:以下是本篇文章正文内容
一、代码原理和功能
代码采用了数组的方式,像一张无数格子(长宽相乘)组成的地图来存储每一格元素,并用数字赋值,以在打印时对应输出边框,飞机,子弹,敌机这些元素。若有用户输入,则对应改变格子的赋值,以及将之前的格子赋值为空白(移动的位置更新,即新的位置赋值元素,旧的位置将元素清除)。 同时为了扩展玩法,加入了难度选择,增强我方实力,RGB炫彩光效界面等功能,详情请阅读代码,如进入游戏界面按下y则开启RGB,按下l可以增强实力等等。 注释较多,应当容易看懂,当然,在程序员眼里,别人的代码都是(粗鄙之言)。 以下直接附上源代码:
二、成果展示
1.源代码
代码如下(示例):
#include <stdio.h>
#include<iostream>
#include <conio.h>
#include <stdlib.h>
#include <windows.h>
using namespace std;
#pragma warning(disable:4996)//屏蔽了4996的错误
#define High 30 // 游戏画面尺寸
#define Width 50
//#define BadNum 1 // 敌机个数
int BadNum = 1; // 敌机个数
// 全局变量
int defu = 0; //德芙巧克力!
int life = 0; //生命值 高难度下赋值为1,在分数达到落败分后加分续上一命
int MaxSpeed = 3; //敌机最大速度
int MaxWidth = 2; //最大弹幕数 即两边增加的弹幕数
int RGB = 7, on = 0;//rgb颜色参数,开关 通过改变RGB数值输出不同的符号颜色
int Plane_x, Plane_y; // 飞机位置
//int enemy_x[BadNum], enemy_y[BadNum]; // 敌机位置
int enemy_x[30], enemy_y[30]; //敌机最大数量
int map[High][Width] = { 0 }; // 二维数组存储游戏画布中对应的元素
// 0为空格,1为飞机*,2为子弹|,3为敌机@,4为 |,5为-
int score; // 得分
int FireWidth; // 子弹宽度
int EnemySpeed = 10; // 敌机移动速度
void HideCursor()//用于隐藏光标 //这两个函数无脑写上并加到打印里就可以解决刷新的闪烁问题
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };//第二个值为0表示隐藏光标
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void gotoxy(int x, int y) //光标移动到(x,y)位置
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
void start() // 数据初始化
{
Plane_x = High - 2;
Plane_y = Width / 2;
map[Plane_x][Plane_y] = 1;
int j, k;
for (k = 0; k < High; k++) {//初始化边框
for (j = 0; j < Width; j++) {
if (j == 0 || j == Width - 1) map[k][j] = 4;//竖向
if (k == 0 || k == High - 1) map[k][j] = 5;//横向
}
}
for (k = 0; k < BadNum; k++)//敌机初始化
{
enemy_x[k] = rand() % 2 + 1;
enemy_y[k] = rand() % (Width - 2) + 1;
map[enemy_x[k]][enemy_y[k]] = 3;
}
score = 0;//初始分数
FireWidth = 0;//子弹未强化
}
void die() {//失败效果
system("cls");
cout << "\n\n\n\n\n\n\t\t\t游戏结束!\n" << endl;
cout << "\n\n\t\t\t你失败了!\n" << endl;
Sleep(2000);
exit(0);
}
void win() {//胜利效果
system("cls");
while (1) {
HideCursor();//隐藏光标
gotoxy(0, 0); // 光标移动到原点位置,以下重画清屏
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RGB);//改变颜色为背景黑色,字符青色
if (RGB < 11) {
RGB++;
}
else {
RGB = 1;
}
cout << "\n\n\n\n\n\n\t\t\t游戏胜利!\n" << endl;
cout << "\n\n\t\t\t666!\n" << endl;
if (BadNum >= 10) {//如果战胜硬汉及以上难度显示
cout << "\n\n\t\t\tyyds!\n" << endl;
}
}
Sleep(2000);
exit(0);
}
void updateAuto() {//非按键输入的更新
int i, j, k;
for (i = 0; i < High; i++)//遍历每一个元素
{
for (j = 0; j < Width; j++)
{
if (map[i][j] == 2)
{
for (k = 0; k < BadNum; k++)
{
if ((i == enemy_x[k]) && (j == enemy_y[k])) // 子弹击中敌机
{
score++; // 分数加1
if (!defu) {//非德芙模式30分获胜
if (score >= 30)
win();
}
else {//德芙模式加分太快,则500
if (score >= 500)
win();
}
if (score % 5 == 0 && EnemySpeed > MaxSpeed) // 达到一定积分后,敌机变快
EnemySpeed--;
if (score % 3 == 0 && FireWidth < MaxWidth) // 达到一定积分后,子弹变厉害
FireWidth++;
map[enemy_x[k]][enemy_y[k]] = 0;
enemy_x[k] = rand() % (2) + 1; // 产生新的飞机
enemy_y[k] = rand() % (Width - 2) + 1;
map[enemy_x[k]][enemy_y[k]] = 3;
map[i][j] = 0; // 子弹消失
}
}
// 子弹向上移动
map[i][j] = 0;
if (i > 0)
map[i - 1][j] = 2;
if (i <= 1)
map[0][j] = 5;
}
}
}
static int speed = 0;
if (speed < EnemySpeed)
speed++;
for (k = 0; k < BadNum; k++)
{
if ((Plane_x == enemy_x[k]) && (Plane_y == enemy_y[k])) // 敌机撞到我机
{
die();
}
if (enemy_x[k] > High - 3) // 敌机跑出显示屏幕
{
map[enemy_x[k]][enemy_y[k]] = 0;
enemy_x[k] = rand() % (3) + 1; // 产生新的飞机
enemy_y[k] = rand() % (Width - 2) + 1;
map[enemy_x[k]][enemy_y[k]] = 3;
score--; // 减分
if (score < -10 && life == 0)//普通模式没有濒死buff
die();
if (score < -10 && life > 0) {//获得濒死buff,分数加15拥有新的机会
life = 0;//只发生一次
score += 15;
}
}
if (speed == EnemySpeed)
{
// 敌机下落
for (k = 0; k < BadNum; k++)
{
map[enemy_x[k]][enemy_y[k]] = 0;
enemy_x[k]++;
speed = 0;
map[enemy_x[k]][enemy_y[k]] = 3;
}
}
}
}
void strong() {//增强玩家实力 //德芙模式下没有意义了,你不需要变强了
system("cls");
printf("\n\n\n\t\t嘿!你是否觉得难度太高? \n\n");
printf("\t\t(=‘ W ’=) \n\n");
printf("\t\t那就给你些力量吧! \n\n");
printf("\t\t请选择强化方式! \n\n");
printf("\t\t1.狂 暴 弹 幕 m\n\n");
printf("\t\t2.时 间 掌 控 n\n\n");
char a = ' ';
a = _getch();
if (a == 'm') {
system("cls");
printf("\n\n\n\t\t解放力量会释放更加强大的弹幕! \n\n");
printf("\t\t强大的弹幕会破坏左右墙壁! \n\n");
printf("\t\t请选择强化等级!(按等级对应字母) \n\n");
printf("\t\t1.一级 i\n\n");
printf("\t\t1.二级 o\n\n");
printf("\t\t1.超级 p\n\n");
char a = ' ';
a = _getch();//增加子弹宽度和上限
if (a == 'i')
MaxWidth++;
else if (a == 'o')
MaxWidth += 2, FireWidth++;
else if (a == 'p')
MaxWidth += 12, FireWidth += 12;
}
else if (a == 'n') {
system("cls");
printf("\n\n\n\t\t控制时间使敌人前进速度更慢! \n\n");
printf("\t\t请选择强化等级!(按等级对应字母) \n\n");
printf("\t\t1.一级 i\n\n");
printf("\t\t1.二级 o\n\n");
char a = ' ';
a = _getch();//减小敌人峰值速度,对高难度无作用
if (a == 'i')
MaxSpeed += 2;
else if (a == 'o')
MaxSpeed += 4;
}
}
void update() {//德芙模式下的操作
int m, n;
m = Plane_x, n = Plane_y;
if ((GetAsyncKeyState(0x41) & 0x8000) && Plane_y > 1 + FireWidth)//FireWidth用于限制移动,子弹能够到的地方人物就不必要过去了
{
Plane_y--; // 位置左移
}
else if ((GetAsyncKeyState(0x44) & 0x8000) && Plane_y < Width - 2 - FireWidth)
{
Plane_y++; // 位置右移
}
else if ((GetAsyncKeyState(0x57) & 0x8000) && Plane_x > 1)
{
Plane_x--; // 位置上移
}
else if ((GetAsyncKeyState(0x53) & 0x8000) && Plane_x < High - 2)
{
Plane_x++; // 位置下移
}
else if (GetAsyncKeyState(0x59) & 0x8000)
{
on = on == 0 ? 1 : 0;//按y开启RGB
if (on == 0) RGB = 7;
}
map[m][n] = 0;
map[Plane_x][Plane_y] = 1;
if (GetAsyncKeyState(0x20) & 0x8000)//开火 空格
{
int left = Plane_y - FireWidth;
int right = Plane_y + FireWidth;
if (left < 0)
left = 0;
if (right > Width - 1)
right = Width - 1;
int k;
for (k = left; k <= right; k++) // 发射闪弹
map[Plane_x - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方
}
}
void updateGetchar() {//普通模式下的操作
char input;
int m, n;
if (kbhit()) // 判断是否有输入
{
m = Plane_x, n = Plane_y;
input = getch(); // 根据用户的不同输入来移动,不必输入回车
if (input == 'a' && Plane_y > 1 + FireWidth)
{
Plane_y--; // 位置左移
}
else if (input == 'd' && Plane_y < Width - 2 - FireWidth)
{
Plane_y++; // 位置右移
}
else if (input == 'w' && Plane_x > 1)
{
Plane_x--; // 位置上移
}
else if (input == 's' && Plane_x < High - 2)
{
Plane_x++; // 位置下移
}
else if (input == 'y')//开启RGB灯效
{
on = on == 0 ? 1 : 0;
if (on == 0) RGB = 7;
}
else if (input == 'l')//变得更强(买挂)
{
strong();
}
else if (input == 'z')//吃下德芙,不可逆
{
defu = defu == 0 ? 1 : 0;
}
else if (input == ' ') // 发射子弹
{
int left = Plane_y - FireWidth;
int right = Plane_y + FireWidth;
if (left < 0)
left = 0;
if (right > Width - 1)
right = Width - 1;
int k;
for (k = left; k <= right; k++) // 发射闪弹
map[Plane_x - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方
}
map[m][n] = 0;
map[Plane_x][Plane_y] = 1;
}
}
void show() // 显示画面
{
HideCursor();//隐藏光标
gotoxy(0, 0); // 光标移动到原点位置,以下重画清屏
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RGB);//改变颜色为RGB数字
if (RGB < 11 && on == 1) {//颜色变换
RGB++;
}
else {//重置
if (on == 1)
RGB = 1;
}
int i, j;
for (i = 0; i < High; i++)
{
for (j = 0; j < Width; j++)
{
if (map[i][j] == 0)
printf(" "); // 输出空格
else if (map[i][j] == 1)
printf("*"); // 输出飞机*
else if (map[i][j] == 2)
printf("|"); // 输出子弹|
else if (map[i][j] == 3)
printf("@"); // 输出敌机@
else if (map[i][j] == 4)
printf("|"); // 输出围墙纵
else if (map[i][j] == 5)
printf("-"); // 输出围墙横
}
printf("\n");
}//一众状态栏
printf("\n得分:%d \n", score);
if (on == 1)
printf("RGB:开启 \n");
else
printf("RGB:关闭 \n");
printf("敌人速度(越小越快):%d \n", EnemySpeed);
if (!defu) {
printf("按l获得力量! \n");
printf("按z大哥吃德芙! \n");
}
else {
printf("德芙,纵享丝滑! \n");
printf("吃掉德芙的你已经天下无敌了,享受游戏吧! \n");
}
printf("随机刷新精英怪,拥有护盾! \n");
if (life > 0) {
printf("获得免疫一次死亡的机会(撞到不算)!\n");
}
}
void choice() {//难度选择
printf("\n\n\n\t\t欢迎来到飞机大战! \n\n");
printf("\t\t请选择难度!(按难度对应字母,默认普通) \n\n");
printf("\t\t1.普通 u\n");
printf("\t\t2.困难 i\n");
printf("\t\t3.大师 o\n");
printf("\t\t4.硬汉 p\n");
printf("\t\t5.神谕 l\n");
printf("\t\t6.人类一败涂地 h\n");
printf("\t\t7.开挂吧 b\n");
char a = ' ';
a = _getch();
if (a == 'u')
; //默认模式
else if (a == 'i')
BadNum = 2; //敌人加一
else if (a == 'o')
BadNum = 4; //敌人为四
else if (a == 'p')
BadNum = 10; //敌人为十
else if (a == 'l') {//敌人为十以及初始速度更快
BadNum = 10;
EnemySpeed = 6;
life = 1;
} // 输出敌机@
else if (a == 'h') {//更多敌人和更快速度
BadNum = 15;
EnemySpeed = 3;
life = 1;
}// 输出敌机@
else if (a == 'b') {//超级多敌人
BadNum = 30;
EnemySpeed = 3;
life = 1;
}//
system("cls");
}
int main()
{
choice();
start(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateAuto(); // 与用户输入无关的更新
if (!defu)
updateGetchar(); // 与用户输入有关的更新
else
update();//德芙方向及开火操作系统
}
return 0;
}
总结
因为原来的控制方式在while的每次循环中只能接收一个字符并发生相应改变,控制操作自然很生硬,所以我在后来加入了新的控制方式,按下z则进入,流畅度大大提升,值得一试。不过因为每次循环可以接收很多字符,键盘的一次按下和抬起速度如果不够快就会产生多个同样字符,仅仅只影响流畅模式下的RGB效果开启。 为何保留了两个操作方法是因为在流畅模式下难度根本没有意义,随便按按就通过了。 以上。
|