看了知乎上的一个C语言做的打飞机游戏(控制台)https://zhuanlan.zhihu.com/p/24798125
决定自己做一个C++版的。
先说一下原来游戏的思路。
首先主函数: 先初始化,然后再一个循环里不断地
显示-->更新与用户无关数据-->用户输入、根据输入更新。
显示是通过一个二维数组canvas (画布)来实现的,通过一个二层循环来在画布上进行绘制(输出字符)
字符的形状代表是 飞机或子弹或者空气。
更新与用户无关数据是按照一个规律:敌机往下飞,子弹往上飞,这样更新的。
根据输入更新 是根据用户输入的'a' 'd'或空格 来设置自己的位置和发射子弹。
int main() { startup(); // 数据初始化 while (1) // 游戏循环执行 { show(); // 显示画面 updateWithoutInput(); // 与用户输入无关的更新 updateWithInput(); // 与用户输入有关的更新 } return 0; }
下面具体地操作。
那么既然要用C++,飞机就可以做成一个基类了。
然后从飞机 派生出两个类 一个是自己,一个是敌机。
自己和敌机有什么不同? 在这里为了简化,敌机不发射子弹,只是简单地往下移动。 自己是可以发射子弹的。
class Plane { private: int x; int y; int MoveSpeed; public: Plane() :x(0), y(0) {}; Plane(int x, int y) :x(x), y(y) {} ~Plane(){} int getX() { return x; } int getY() { return y; } int getMoveSpeed(){ return MoveSpeed; } void setX(int x) { this->x =x; } void setY(int y) { this->y = y; } void setMoveSpeed(int speed){ MoveSpeed = speed; } }; class MyPlane : public Plane { private: int BulletWidth; public: int getBulletWidth() { return BulletWidth; } void setBulletWidth(int width) { this->BulletWidth = width; } }; class EnemyPlane : public Plane { };
除了飞机,其他的基本根据原来的改写,因为图像的显示主要依靠画布,所以如果画布不改动的话,其余的基本改变不大。
改写时为了方便,我将原来的长函数分解成短函数,看起来更容易。
最后的代码:
main.cpp
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #include"plane.h" #include"updateFunction.h" const int High = 15;// 游戏画面尺寸 const int Width = 25; const int EnemyNum = 5;// 敌机个数 // 全局变量 MyPlane myPlane; // 飞机 EnemyPlane enemyPlane[EnemyNum]; // 敌机 int canvas[High+1][Width+1] = { 0 }; // 二维数组存储游戏画布中对应的元素 // 0为空格,1为飞机*,2为子弹|,3为敌机@ int score; // 得分 //光标移动到(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 startup() // 数据初始化 { //下面的两行用于隐藏光标,防止乱闪 CONSOLE_CURSOR_INFO cursor_info = { 1,0 }; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); //设自己置飞机位置 startupMyPlane(); //设置敌机位置 startupEnemyPlane(); score = 0; } void startupMyPlane() { myPlane.setX(High - 1); myPlane.setY(Width - 2); myPlane.setBulletWidth(0); } void startupEnemyPlane() { for (int k = 0; k < EnemyNum; k++) { enemyPlane[k].setX(rand() % 2); enemyPlane[k].setY(rand() % Width); enemyPlane[k].setMoveSpeed(20); } } // 显示画面 void show() { gotoxy(0, 0); // 光标移动到原点位置,以下重画清屏 for (int i = 0; i < High; i++) { for (int j = 0; j < Width; j++) { if (canvas[i][j] == 0) printf(" "); // 输出空格 else if (canvas[i][j] == 1) printf("*"); // 输出飞机* else if (canvas[i][j] == 2) printf("|"); // 输出子弹| else if (canvas[i][j] == 3) printf("@"); // 输出飞机@ } printf("\n"); } printf("得分:%d\n", score); Sleep(20); } // 与用户输入无关的更新 void updateWithoutInput() { //更新子弹位置 for (int i = 0; i < High; i++) { for (int j = 0; j < Width; j++) { if (canvas[i][j] == 2) { updateBullet(i, j); } } } static int speed = 0; if (speed < enemyPlane[0].getMoveSpeed()) speed++; updatePlane(speed ); } void updateBullet(int i,int j) { for (int k = 0; k < EnemyNum; k++) { if ((i == enemyPlane[k].getX()) && (j == enemyPlane[k].getY())) // 子弹击中敌机 { score++; // 分数加1 if (score % 5 == 0 && enemyPlane[k].getMoveSpeed() > 3) // 达到一定积分后,敌机变快 enemyPlane[k].setMoveSpeed(enemyPlane[k].getMoveSpeed() - 1); if (score % 5 == 0) // 达到一定积分后,子弹变厉害 myPlane.setBulletWidth(myPlane.getBulletWidth() + 1); canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 0; enemyPlane[k].setX(rand() % 2); // 产生新的飞机 enemyPlane[k].setY(rand() % Width); canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 3; canvas[i][j] = 0; // 子弹消失 } } // 子弹向上移动 canvas[i][j] = 0; if (i > 0) canvas[i - 1][j] = 2; } void updatePlane(int& speed ) { for (int k = 0; k < EnemyNum; k++) { if ((myPlane.getX() == enemyPlane[k].getX()) && (myPlane.getY() == enemyPlane[k].getY())) // 敌机撞到我机 { printf("失败!\n"); Sleep(3000); system("pause"); exit(0); } if (enemyPlane[k].getX() > High) // 敌机跑出显示屏幕 { canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 0; enemyPlane[k].setX(rand() % 2); // 产生新的飞机 enemyPlane[k].setY(rand() % Width); canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 3; score--; // 减分 } if (speed == enemyPlane[0].getMoveSpeed()) { // 敌机下落 for (k = 0; k < EnemyNum; k++) { canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 0; enemyPlane[k].setX(enemyPlane[k].getX() + 1); speed = 0; canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 3; } } } } void updateWithInput() // 与用户输入有关的更新 { char input; if (_kbhit()) // 判断是否有输入 { input = _getch(); // 根据用户的不同输入来移动,不必输入回车 if (input == 'a' && myPlane.getX() > 0) { canvas[myPlane.getX()][myPlane.getY()] = 0; myPlane.setY(myPlane.getY()-1); // 位置左移 canvas[myPlane.getX()][myPlane.getY()] = 1; } else if (input == 'd' && myPlane.getY() < Width - 1) { canvas[myPlane.getX()][myPlane.getY()] = 0; myPlane.setY(myPlane.getY() +1); // 位置右移 canvas[myPlane.getX()][myPlane.getY()] = 1; } else if (input == 'w') { canvas[myPlane.getX()][myPlane.getY()] = 0; myPlane.setX(myPlane.getX() - 1);; // 位置上移 canvas[myPlane.getX()][myPlane.getY()] = 1; } else if (input == 's') { canvas[myPlane.getX()][myPlane.getY()] = 0; myPlane.setX(myPlane.getX() +1);; // 位置上移 canvas[myPlane.getX()][myPlane.getY()] = 1; } else if (input == ' ') // 发射子弹 { int left = myPlane.getY() - myPlane.getBulletWidth() ; int right = myPlane.getY() + myPlane.getBulletWidth(); if (left < 0) left = 0; if (right > Width - 1) right = Width - 1; int k; for (k = left; k <= right; k++) // 发射闪弹 canvas[myPlane.getX() - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方 } } } int main() { startup(); // 数据初始化 while (1) // 游戏循环执行 { show(); // 显示画面 updateWithoutInput(); // 与用户输入无关的更新 updateWithInput(); // 与用户输入有关的更新 } return 0; }
updateFunction.h
#pragma once void startupMyPlane(); void startupEnemyPlane(); void updateBullet(int i, int j); void updatePlane(int& speed);
plane.h
#pragma once class Plane { private: int x; int y; int MoveSpeed; public: Plane() :x(0), y(0) {}; Plane(int x, int y) :x(x), y(y) {} ~Plane(){} int getX() { return x; } int getY() { return y; } int getMoveSpeed(){ return MoveSpeed; } void setX(int x) { this->x =x; } void setY(int y) { this->y = y; } void setMoveSpeed(int speed){ MoveSpeed = speed; } int condition; }; class MyPlane : public Plane { private: int BulletWidth; public: MyPlane(){ Plane(); condition = 1; }; MyPlane(int x, int y) :Plane(x, y) { condition = 1; } ~MyPlane() {} int getBulletWidth() { return BulletWidth; } void setBulletWidth(int width) { this->BulletWidth = width; } }; class EnemyPlane : public Plane { public: static int num; public: EnemyPlane() { Plane(); condition = 3; }; EnemyPlane(int x, int y) : Plane(x, y) { condition = 3; } ~EnemyPlane() {} };