c++实现简单制作飞机大战

知识点

结构体,循环,函数,随机数,数组,数据读取。

玩法

1.通过控制w,s,a,d来实现飞机的移动,或者上下左右。

2.每过一定时间会出现敌机。

3.按空格键进行射击。

创作历程

Block.h:

#pragma once
struct SBlock
{
	int nRow;
	int nCol;
};

Bullet.h:

#pragma once
struct SBullet
{
	SBullet(int nInRow, int nInCol);
	//子弹移动的函数
	void move();
	int nRow;
	int nCol;
};


Bullet.cpp:

#include "stdafx.h"
#include "Bullet.h"

SBullet::SBullet(int nInRow, int nInCol)
{
	nRow = nInRow;
	nCol = nInCol;
}

void SBullet::move()
{
	nRow--;
}


BulletMgr.h:

#pragma once
#include "Bullet.h"
#include <vector>
using namespace std;
//管理所有子弹
struct SBulletMgr
{
	//添加子弹:位置参数
	void addBullet(int nInRow,int nInCol);
	//函数获取某个位置的子弹
	bool isExist(int nInRow, int nInCol);
	void update();
	//容器:存子弹
	vector<SBullet> vecBullets;
};


BulletMgr.cpp:

#include "stdafx.h"
#include "BulletMgr.h"

void SBulletMgr::addBullet(int nInRow, int nInCol)
{
	//把子弹创建出来
	SBullet bullet(nInRow, nInCol);
	//存起来
	vecBullets.push_back(bullet);
}

bool SBulletMgr::isExist(int nInRow, int nInCol)
{
	for (int i = 0; i < vecBullets.size(); i++)
	{
		if (vecBullets[i].nRow == nInRow && vecBullets[i].nCol == nInCol)
		{
			return true;
		}
	}
	return false;
}

void SBulletMgr::update()
{
	//遍历所有子弹,执行子弹的移动函数
	for (int i = 0; i < vecBullets.size(); i++)
	{
		vecBullets[i].move();
	}
}


DataMgr.h:

#pragma once
#include "DataStruct.h"
struct SDataMgr
{
	SDataMgr();
	SMapDtMgr mapDtMgr;
	SEnemyDtMgr enemyDtMgr;
};


DataMgr.cpp:

#include "stdafx.h"
#include "DataMgr.h"

SDataMgr::SDataMgr()
{
	//读数据
	mapDtMgr.loadFile("./datas/mapDt.txt");
	enemyDtMgr.loadFile("./datas/enemyDt.txt");
}


DataStruct.h:

#pragma once
#include <vector>
#include <string>
using namespace std;
//需要有个结构体捆绑整份地图数据
struct SMapDt
{
	SMapDt()
	{
		nId = 0;
		strName = "";
		nRowCount = 0;
		nColCount = 0;
		nInitRow = 0;
		nInitCol = 0;
	}
	int nId;
	string strName;
	int nRowCount;
	int nColCount;
	int nInitRow;
	int nInitCol;
	int arrMap[100][100];
};

struct SMapDtMgr
{
	//需要有个函数,这个函数用于读取数据
	void loadFile(string strPath);
	//获取某一条数据的方法
	SMapDt getDataById(int nId);
	vector<SMapDt> vecDatas;
};

struct SEnemyDt
{
	SEnemyDt()
	{
		nId = 0;
		strName = "";
		nHp = 0;
		nAtk = 0;
		strPic = "";
	}
	int nId;
	string strName;
	int nHp;
	int nAtk;
	string strPic;
};

struct SEnemyDtMgr
{
	//需要有个函数,这个函数用于读取数据
	void loadFile(string strPath);
	//获取某一条数据的方法
	SEnemyDt getDataById(int nId);
	vector<SEnemyDt> vecDatas;
};


DataStruct.cpp:

#include "stdafx.h"
#include "DataStruct.h"
#include <fstream>

void SMapDtMgr::loadFile(string strPath)
{
	fstream inFile(strPath);
	if (inFile)
	{
		string str = "";
		getline(inFile, str);
		int nCount = 0;
		inFile >> nCount;
		for (int i = 0; i < nCount; i++)
		{
			SMapDt data;
			inFile >> data.nId >> data.strName >> data.nRowCount >> data.nColCount >> data.nInitRow >> data.nInitCol;

			for (int n = 0; n < data.nRowCount; n++)
			{
				for (int m = 0; m < data.nColCount; m++)
				{
					inFile >> data.arrMap[n][m];
				}
			}
			//存储到容器
			vecDatas.push_back(data);
		}
	}
	inFile.close();
}

SMapDt SMapDtMgr::getDataById(int nId)
{
	//遍历所有的数据,比较id是否和传进来是一样的
	//如果是一样这条数据就是外面想拿到的
	for (int i = 0; i < vecDatas.size(); i++)
	{
		if (vecDatas[i].nId == nId)
		{
			return vecDatas[i];
		}
	}
	//返回一条空数据
	SMapDt data;
	return data;
}

void SEnemyDtMgr::loadFile(string strPath)
{
	fstream inFile(strPath);
	if (inFile)
	{
		string str = "";
		getline(inFile, str);
		int nCount = 0;
		inFile >> nCount;
		for (int i = 0; i < nCount; i++)
		{
			SEnemyDt data;
			inFile >> data.nId >> data.strName >> data.nHp >> data.nAtk >> data.strPic;
			vecDatas.push_back(data);
		}
	}
	inFile.close();
}

SEnemyDt SEnemyDtMgr::getDataById(int nId)
{
	for (int i = 0; i < vecDatas.size(); i++)
	{
		if (vecDatas[i].nId == nId)
		{
			return vecDatas[i];
		}
	}

	SEnemyDt data;
	return data;
}


Enemy.h:

#pragma once
#include "Block.h"
//敌人需要有自己的样式
struct SEnemy
{
	//初始化数据的函数
	void initWithData(SEnemyDt data);
	void setPosition(int nInRow,int nInCol);
	//
	bool isExist(int nInRow, int nInCol);
	//移动的函数
	void move();
	SBlock arrPlane[4];
	int nId;
	string strName;
	int nHp;
	int nAtk;
	string strPic;
	//保存敌人当前的行列
	int nRow;
	int nCol;
	//计时
	int nMoveTime;
};


Enemy.cpp:

#include "stdafx.h"
#include "Enemy.h"

void SEnemy::initWithData(SEnemyDt data)
{
	//把传进来的整条数据保存到敌人身上
	nId = data.nId;
	nHp = data.nHp;
	nAtk = data.nAtk;
	strName = data.strName;
	strPic = data.strPic;
	nMoveTime = 0;
}

void SEnemy::setPosition(int nInRow, int nInCol)
{
	nRow = nInRow;
	nCol = nInCol;
	arrPlane[0].nRow = nInRow;
	arrPlane[0].nCol = nInCol;
	arrPlane[1].nRow = nInRow;
	arrPlane[1].nCol = nInCol - 1;
	arrPlane[2].nRow = nInRow + 1;
	arrPlane[2].nCol = nInCol;
	arrPlane[3].nRow = nInRow;
	arrPlane[3].nCol = nInCol + 1;
}

bool SEnemy::isExist(int nInRow, int nInCol)
{
	for (int i = 0; i < 4; i++)
	{
		if (arrPlane[i].nRow == nInRow && arrPlane[i].nCol == nInCol)
		{
			return true;
		}
	}
	return false;
}

void SEnemy::move()
{
	nMoveTime++;
	if (nMoveTime > 5)
	{
		nMoveTime = 0;
		nRow++;
		//重新调用设置位置的函数
		setPosition(nRow, nCol);
	}
	
}


EnemyMgr.h:

#pragma once
#include "Enemy.h"
#include <vector>
using namespace std;
//创建敌人并且将所有敌人管理起来(存起来)
struct SEnemyMgr
{
	SEnemyMgr();
	void update();
	//创建敌人的函数
	void createEnemy();
	//判断某个敌人是否存在某行某列
	SEnemy isExist(int nInRow, int nInCol);
	vector<SEnemy> vecEnemys;
	//需要有一个变量,用于统计时间
	int nCreateTime;
};


EnemyMgr.cpp:

#include "stdafx.h"
#include "EnemyMgr.h"
#include "Enemy.h"

SEnemyMgr::SEnemyMgr()
{
	nCreateTime = 0;
}

void SEnemyMgr::update()
{
	nCreateTime++;
	if (nCreateTime > 20)
	{
		nCreateTime = 0;
		//创建敌人
		createEnemy();
	}
	//找到所有敌人->执行敌人的移动函数
	for (int i = 0; i < vecEnemys.size(); i++)
	{
		vecEnemys[i].move();
	}
}

void SEnemyMgr::createEnemy()
{
	SEnemy enemy;
	//随机拿到其中一条数据
	//随机一个从2001 - 2003的Id出来
	int nId = rand() % (2004 - 2001) + 2001;
	SEnemyDt enemyDt = g_dataMgr.enemyDtMgr.getDataById(nId);
	enemy.initWithData(enemyDt);
	int nColCount = g_gameMgr.gameMap.curMapDt.nColCount;
	int nCol = rand() % (nColCount-2 - 2) + 2;
	enemy.setPosition(-2, nCol);

	vecEnemys.push_back(enemy);
}

SEnemy SEnemyMgr::isExist(int nInRow, int nInCol)
{
	for (int i = 0; i < vecEnemys.size(); i++)
	{
		if (vecEnemys[i].isExist(nInRow,nInCol))
		{
			return vecEnemys[i];
		}
	}

	SEnemy enemy;
	return enemy;
}


GameMap.h:

#pragma once
#include "Player.h"
#include "DataStruct.h"
#include "EnemyMgr.h"
#include "BulletMgr.h"
struct SGameMap
{
	SGameMap();
	//数据更新:按键、移动数据
	void update();
	//渲染:显示
	void render();
	//碰撞函数
	void onCollision();

	//保存一条地图数据
	SMapDt curMapDt;
	SPlayer player;
	SEnemyMgr enemyMgr;
	SBulletMgr bulletMgr;
};


GameMap.cpp:

#include "stdafx.h"
#include "GameMap.h"

SGameMap::SGameMap()
{
    srand(time(nullptr));
    int temp = 1001 + rand() % 2;
    //一进入游戏就需要拿到地图数据来用
    curMapDt = g_dataMgr.mapDtMgr.getDataById(temp);
    //创建地图之后先固定玩家的初始位置
    player.setPosition(curMapDt.nInitRow, curMapDt.nInitCol);
    srand(time(nullptr));
    enemyMgr.createEnemy();
}

void SGameMap::update()
{
	if (KEY_DOWN(VK_ESCAPE))
	{
        g_gameMgr.bClear = true;
		g_gameMgr.nGameScene = 0;
	}
    bulletMgr.update();
    player.update();
    enemyMgr.update();
    onCollision();
}

void SGameMap::render()
{
    for (int i = 0; i < curMapDt.nRowCount; i++)//遍历行
    {
        for (int j = 0; j < curMapDt.nColCount; j++)//遍历列
        {
            SEnemy enemy = enemyMgr.isExist(i, j);
            if (1 == curMapDt.arrMap[i][j])
            {
                cout << "■";
            }
            //根据玩家的行列信息画出玩家的形状,如果当前位置画了玩家,不能再画空地
            else if (player.isExist(i,j))
            {
                cout << "▲";
            }
            else if (enemy.nId >= 2001 && enemy.nId <= 2003)
            {
                cout << enemy.strPic;
            }
            else if (bulletMgr.isExist(i, j))
            {
                cout << "●";
            }
            else
            {
                cout << "  ";
            }
        }
        cout << endl;
    }
}

void SGameMap::onCollision()
{
    //&:引用,取别名
    
    //定义变量来保存容器
    vector<SBullet> &vecBullets = bulletMgr.vecBullets;
    vector<SEnemy> &vecEnemys = enemyMgr.vecEnemys;
    //拿到所有子弹、所有敌人
    //判断子弹的位置是否存在敌人
    for (int i = vecBullets.size() - 1; i >= 0 ; i--)
    {
        bool bRemoveEenemy = false;
        for (int j = vecEnemys.size() - 1; j >= 0; j--)
        {
            bool enemy = vecEnemys[j].isExist(vecBullets[i].nRow, vecBullets[i].nCol);
            if (enemy == true)
            {
                bRemoveEenemy = true;
                //子弹碰到了某个敌人了!
                vecEnemys.erase(vecEnemys.begin() + j);
                vecBullets.erase(vecBullets.begin() + i);
                break;
            }
        }
    }
}


GameMenu.h:

#pragma once
struct SGameMenu
{
	SGameMenu();
	//数据更新:按键、移动数据
	void update();
	//渲染:显示
	void render();
	//定义变量
	int nMenuState;
};


GameMenu.cpp:

#include "stdafx.h"
#include "GameMenu.h"

enum
{
    E_MENU_START,
    E_MENU_SET,
    E_MENU_EXIT
};

SGameMenu::SGameMenu()
{
    nMenuState = E_MENU_START;
}

void SGameMenu::update()
{
	if (KEY_DOWN(VK_RETURN))
	{
        if (nMenuState == E_MENU_START)
        {
            g_gameMgr.bClear = true;
            g_gameMgr.nGameScene = 1;
        }
        else if (nMenuState == E_MENU_SET)
        {

        }
        else if (nMenuState == E_MENU_EXIT)
        {
            exit(0);
        }
	}

    if (KEY_DOWN(VK_UP))
    {
        nMenuState--;
        if (nMenuState < E_MENU_START)
        {
            nMenuState = E_MENU_EXIT;
        }
    }
    else if (KEY_DOWN(VK_DOWN))
    {
        nMenuState++;
        if (nMenuState > E_MENU_EXIT)
        {
            nMenuState = E_MENU_START;
        }
    }

}

void SGameMenu::render()
{
    if (E_MENU_START == nMenuState)
    {
        cout << "■■■■■■■■■■■■■" << endl;
        cout << "■                      ■" << endl;
        cout << "■    -> 游戏开始       ■" << endl;
        cout << "■       游戏设置       ■" << endl;
        cout << "■       游戏退出       ■" << endl;
        cout << "■                      ■" << endl;
        cout << "■■■■■■■■■■■■■" << endl;
    }
    else if (E_MENU_SET == nMenuState)
    {
        cout << "■■■■■■■■■■■■■" << endl;
        cout << "■                      ■" << endl;
        cout << "■       游戏开始       ■" << endl;
        cout << "■    -> 游戏设置       ■" << endl;
        cout << "■       游戏退出       ■" << endl;
        cout << "■                      ■" << endl;
        cout << "■■■■■■■■■■■■■" << endl;
    }
    else if (E_MENU_EXIT == nMenuState)
    {
        cout << "■■■■■■■■■■■■■" << endl;
        cout << "■                      ■" << endl;
        cout << "■       游戏开始       ■" << endl;
        cout << "■       游戏设置       ■" << endl;
        cout << "■    -> 游戏退出       ■" << endl;
        cout << "■                      ■" << endl;
        cout << "■■■■■■■■■■■■■" << endl;
    }
}


GameMgr.h:

#pragma once
#include "GameMenu.h"
#include "GameMap.h"
struct SGameMgr
{
	SGameMgr();
	void update();
	void render();
	SGameMenu gameMenu;
	SGameMap gameMap;
	//保存当前运行的场景
	int nGameScene;
	//bool变量代表是否需要清屏
	bool bClear;
};


GameMgr.cpp:

#include "stdafx.h"
#include "GameMgr.h"

SGameMgr::SGameMgr()
{
	nGameScene = 0;
	bClear = false;
}

void SGameMgr::update()
{
	if (0 == nGameScene)
	{
		gameMenu.update();
	}
	else if (1 == nGameScene)
	{
		gameMap.update();
	}
}

void SGameMgr::render()
{
	if (0 == nGameScene)
	{
		gameMenu.render();
	}
	else if (1 == nGameScene)
	{
		gameMap.render();
	}
}


Player.h:

#pragma once
#include "Block.h"

struct SPlayer
{
	//需要有个数据更新,控制玩家的移动...
	void update();
	//判断四个方块是否存在某一个行列的函数
	bool isExist(int nInRow, int nInCol);
	//设置飞机整体的函数
	void setPosition(int nInRow,int nInCol);
	//需要有个数组,长度4:用于存放四个方块
	SBlock arrPlane[4];
	//保存玩家的整个行列
	int nRow;
	int nCol;
	//玩家整体坐标备份(备份参考点)
	int nRowBk;
	int nColBk;
};


Player.cpp:

#include "stdafx.h"
#include "Player.h"

void SPlayer::update()
{
	nRowBk = nRow;
	nColBk = nCol;
	if (KEY_DOWN(VK_UP))
	{
		if (nRow > 2)
		{
			setPosition(nRow - 1, nCol);
		}
	}
	else if (KEY_DOWN(VK_DOWN))
	{
		if (nRow < g_gameMgr.gameMap.curMapDt.nRowCount - 2)
		{
			setPosition(nRow + 1, nCol);
		}
	}
	else if (KEY_DOWN(VK_LEFT))
	{
		if (nCol > 2)
		{
			setPosition(nRow, nCol - 1);
		}
		
	}
	else if (KEY_DOWN(VK_RIGHT))
	{
		if (nCol < g_gameMgr.gameMap.curMapDt.nColCount - 3)
		{
			setPosition(nRow, nCol + 1);
		}
		
	}

	if (KEY_DOWN(VK_SPACE))
	{
		//找子弹管理者添加一颗子弹
		g_gameMgr.gameMap.bulletMgr.addBullet(nRow, nCol);
	}


	//移动之后判断是否撞墙
	//for (int i = 0; i < 4; i++)
	//{
	//	if (g_gameMgr.gameMap.curMapDt.arrMap[arrPlane[i].nRow][arrPlane[i].nCol] == 1)
	//	{
	//		setPosition(nRowBk, nColBk);
	//		break;
	//	}
	//}
}

bool SPlayer::isExist(int nInRow, int nInCol)
{
	for (int i = 0; i < 4; i++)
	{
		if (arrPlane[i].nRow == nInRow && arrPlane[i].nCol == nInCol)
		{
			return true;
		}
	}
	return false;
}

void SPlayer::setPosition(int nInRow, int nInCol)
{
	nRow = nInRow;
	nCol = nInCol;
	arrPlane[0].nRow = nInRow;
	arrPlane[0].nCol = nInCol;
	arrPlane[1].nRow = nInRow;
	arrPlane[1].nCol = nInCol + 1;
	arrPlane[2].nRow = nInRow - 1;
	arrPlane[2].nCol = nInCol;
	arrPlane[3].nRow = nInRow;
	arrPlane[3].nCol = nInCol - 1;
}


stdafx.h:

#pragma once
#include <iostream>
#include <windows.h>
#include <stdlib.h> //设置随机数种子的头文件
#include "DataMgr.h"
#include "GameMgr.h"
using namespace std;

extern SDataMgr g_dataMgr;
extern SGameMgr g_gameMgr;

#define KEY_DOWN(vk_code) GetAsyncKeyState(vk_code) & 0x8000

主函数PlaneWar.cpp:

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include "DataMgr.h"
#include "GameMgr.h"

void gotoxy(int x, int y)
{
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

//保证数据先行原则
SDataMgr g_dataMgr;
SGameMgr g_gameMgr;

int main()
{
    while (true)
    {
        g_gameMgr.update();
        g_gameMgr.render();

        if(g_gameMgr.bClear)
        {
            system("cls");
            g_gameMgr.bClear = false;
        }

        gotoxy(0, 0);

        Sleep(60);
    }
}

数据

在文件管理器中创建名为datas文件夹,再在里面创建两个文本文档,读取地图和敌人数据

enemyDt.txt:

mapDt.txt:

  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
以下是一个简单的基于 C 语言飞机大战游戏代码: ```c #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h> #include <windows.h> #define WIDTH 40 /* 游戏区宽度 */ #define HEIGHT 20 /* 游戏区高度 */ #define PLAYER 'A' /* 玩家飞机形状 */ #define ENEMY '*' /* 敌机形状 */ #define BULLET '|' /* 子弹形状 */ #define SPEED 100 /* 游戏速度 */ #define ENEMY_NUM 10 /* 敌机数量 */ int score = 0; /* 得分 */ int x, y; /* 玩家飞机坐标 */ int bullet_x, bullet_y; /* 子弹坐标 */ int enemy_x[ENEMY_NUM], enemy_y[ENEMY_NUM]; /* 敌机坐标 */ int is_shooting = 0; /* 是否发射子弹 */ void SetCursorPosition(int x, int y) /* 光标移动函数 */ { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(handle, pos); } void DrawPlayer() /* 绘制玩家飞机函数 */ { SetCursorPosition(x, y); printf("%c", PLAYER); } void DrawBullet() /* 绘制子弹函数 */ { SetCursorPosition(bullet_x, bullet_y); printf("%c", BULLET); } void DrawEnemy(int i) /* 绘制敌机函数 */ { SetCursorPosition(enemy_x[i], enemy_y[i]); printf("%c", ENEMY); } void Initialize() /* 游戏初始化函数 */ { x = WIDTH / 2; y = HEIGHT - 1; bullet_y = y - 1; for (int i = 0; i < ENEMY_NUM; i++) { enemy_x[i] = rand() % WIDTH; enemy_y[i] = rand() % (HEIGHT - 5) - HEIGHT; } } void UpdatePlayer() /* 更新玩家飞机位置函数 */ { if (_kbhit()) { switch (_getch()) { case 'a': if (x > 0) x--; break; case 'd': if (x < WIDTH - 1) x++; break; case ' ': if (!is_shooting) { is_shooting = 1; bullet_x = x; } break; } } } void UpdateBullet() /* 更新子弹位置函数 */ { if (is_shooting) { bullet_y--; if (bullet_y == 0) { is_shooting = 0; } } } void UpdateEnemy(int i) /* 更新敌机位置函数 */ { enemy_y[i]++; if (enemy_y[i] == HEIGHT) { enemy_x[i] = rand() % WIDTH; enemy_y[i] = rand() % (HEIGHT - 5) - HEIGHT; score++; } } void CollisionDetection() /* 碰撞检测函数 */ { for (int i = 0; i < ENEMY_NUM; i++) { if ((bullet_x == enemy_x[i]) && (bullet_y == enemy_y[i])) { is_shooting = 0; enemy_x[i] = rand() % WIDTH; enemy_y[i] = rand() % (HEIGHT - 5) - HEIGHT; score += 10; } if ((x == enemy_x[i]) && (y == enemy_y[i])) { printf("\nGame Over!\n"); printf("Your score is %d\n", score); exit(0); } } } int main() { srand((unsigned)time(NULL)); Initialize(); while (1) { SetCursorPosition(0, 0); printf("Score: %d", score); DrawPlayer(); UpdatePlayer(); if (is_shooting) { DrawBullet(); UpdateBullet(); } for (int i = 0; i < ENEMY_NUM; i++) { DrawEnemy(i); UpdateEnemy(i); } CollisionDetection(); Sleep(SPEED); system("cls"); } return 0; } ``` 该代码使用了 Windows.h 库中的一些函数,可能不兼容其他操作系统。你可以在 Windows 操作系统上编译运行该代码,使用 WASD 控制飞机移动,空格键发射子弹,避免与敌机碰撞,得分越高越好!
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值