求助,我本来是想写一个基于easyx的游戏的,结果卡了bug 求助
#include <graphics.h>
#include <conio.h>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <string>
#include <vector>
#include <memory>
#include <sstream>
#include <fstream>
// 定义游戏窗口尺寸
const int WIDTH = 800;
const int HEIGHT = 600;
// 游戏状态枚举
enum class GameState {
MAIN_MENU,
IN_GAME,
GAME_OVER,
LEVEL_COMPLETED
};
// 全局变量,用于记录当前游戏状态
GameState gameState = GameState::MAIN_MENU;
// 全局变量,用于记录当前关卡数
int currentLevel = 0;
// 玩家结构体,代表游戏中的人物
struct Player {
int x;
int y;
int speed;
int health;
int score;
};
// 定义一个全局的玩家对象
Player player;
// 定义一个结构体用于存储不同枪械的外观绘制相关信息(比如绘制的坐标、尺寸等)
struct GunAppearance {
int drawX;
int drawY;
int width;
int height;
};
// 子弹结构体
struct Bullet {
int x;
int y;
int directionX;
int directionY;
bool active;
};
// 游戏关卡结构体,记录每个关卡的相关信息
struct Level {
int levelNumber;
int numEnemies;
std::vector<int> enemyTypes;
};
// 全局数组,用于存储所有关卡信息
Level levels[15];
// 枪械类,封装枪械相关属性和操作
class Gun {
public:
Gun(int type);
std::string getName() const;
int getFireRate() const;
int getBulletSpeed() const;
int getDamage() const;
int getMagazineCapacity() const;
int getCurrentBullets() const;
void fire(Bullet bullets[], int &bulletCount);
void reload();
void draw(GunAppearance appearance);
private:
int type;
std::string name;
int fireRate;
int bulletSpeed;
int damage;
int magazineCapacity;
int currentBullets;
};
// 全局的枪械对象,用于游戏中的枪械操作
Gun currentGun(1);
// 敌人基类
class Enemy {
public:
Enemy(int x, int y);
virtual ~Enemy() {}
virtual void draw() = 0;
virtual int getSpeed() const = 0;
virtual int getHealth() const = 0;
void takeDamage(int damage);
virtual bool isAlive() const;
virtual void update(Player player) = 0;
virtual bool checkCollision(Bullet bullet) const = 0;
virtual bool checkPlayerCollision(Player player) const = 0;
protected:
int x;
int y;
int health;
bool alive;
};
// Enemy类中takeDamage函数的默认实现
void Enemy::takeDamage(int damage) {
health -= damage;
if (health <= 0) {
alive = false;
}
}
// 具体敌人类型1
class EnemyType1 : public Enemy {
public:
EnemyType1(int x, int y);
void draw() override;
int getSpeed() const override;
int getHealth() const override;
void takeDamage(int damage);
bool isAlive() const override;
void update(Player player) override;
bool checkCollision(Bullet bullet) const override;
bool checkPlayerCollision(Player player) const override;
private:
int speed;
int attackCooldown;
};
// 具体敌人类型2
class EnemyType2 : public Enemy {
public:
EnemyType2(int x, int y);
void draw() override;
int getSpeed() const override;
int getHealth() const override;
void takeDamage(int damage);
bool isAlive() const override;
void update(Player player) override;
bool checkCollision(Bullet bullet) const override;
bool checkPlayerCollision(Player player) const override;
private:
int speed;
int moveDirectionX;
int moveDirectionY;
int attackCooldown;
};
// 加载图像资源函数,使用智能指针管理内存,避免内存泄漏
std::unique_ptr<IMAGE> loadImage(const std::string& fileName) {
std::unique_ptr<IMAGE> img = std::make_unique<IMAGE>();
loadImage(img.get(), fileName.c_str());
return img;
}
// 初始化游戏,创建窗口等
void initGame() {
initgraph(WIDTH, HEIGHT);
setbkcolor(WHITE);
cleardevice();
}
// 绘制玩家(使用加载的图片),这里暂未完善具体绘制逻辑,只是示意如何放置图片
void drawPlayer(Player player, std::unique_ptr<IMAGE>& playerImg) {
putimage(player.x - playerImg->getwidth() / 2, player.y - playerImg->getheight() / 2, playerImg.get());
}
// 处理玩家移动
void handlePlayerMovement(Player &player) {
if (_kbhit()) {
char key = _getch();
switch (key) {
case 'w':
player.y -= player.speed;
if (player.y < 0) player.y = 0;
break;
case 's':
player.y += player.speed;
if (player.y > HEIGHT) player.y = HEIGHT;
break;
case 'a':
player.x -= player.speed;
if (player.x < 0) player.x = 0;
break;
case 'd':
player.x += player.speed;
if (player.x > WIDTH) player.x = WIDTH;
break;
}
}
}
// 初始化敌人,根据关卡信息生成不同类型敌人
void initEnemies(Level level, std::vector<std::unique_ptr<Enemy>>& enemies) {
for (int i = 0; i < level.numEnemies; i++) {
int enemyType = level.enemyTypes[i];
switch (enemyType) {
case 1:
enemies.push_back(std::make_unique<EnemyType1>(rand() % WIDTH, rand() % HEIGHT));
break;
case 2:
enemies.push_back(std::make_unique<EnemyType2>(rand() % WIDTH, rand() % HEIGHT));
break;
default:
break;
}
}
}
// 绘制所有敌人,通过智能指针容器遍历,这里暂未完善具体绘制逻辑,只是调用虚函数让派生类去实现绘制
void drawEnemies(const std::vector<std::unique_ptr<Enemy>>& enemies) {
for (const auto& enemy : enemies) {
enemy->draw();
}
}
// 检查子弹与单个敌人是否碰撞的辅助函数
bool checkBulletEnemyCollision(Bullet bullet, const std::unique_ptr<Enemy>& enemy) {
return enemy->isAlive() && enemy->checkCollision(bullet);
}
// 检查子弹与所有敌人的碰撞,处理敌人受击逻辑
void checkAllBulletEnemyCollision(Bullet bullets[], int bulletCount, const std::vector<std::unique_ptr<Enemy>>& enemies) {
for (int i = 0; i < bulletCount; i++) {
if (bullets[i].active) {
for (const auto& enemy : enemies) {
if (checkBulletEnemyCollision(bullets[i], enemy)) {
enemy->takeDamage(currentGun.getDamage());
bullets[i].active = false;
if (!enemy->isAlive()) {
std::cout << "敌人被消灭!" << std::endl;
player.score += getScoreForEnemy(enemy.get());
}
}
}
}
}
}
// 根据敌人类型获取消灭该敌人获得的分数
int getScoreForEnemy(const std::unique_ptr<Enemy>& enemy) {
if (dynamic_cast<EnemyType1*>(enemy.get())) return 10;
if (dynamic_cast<EnemyType2*>(enemy.get())) return 15;
return 0;
}
// 检查所有敌人与玩家的碰撞,处理玩家受击逻辑
void checkAllEnemyPlayerCollision(const std::vector<std::unique_ptr<Enemy>>& enemies, Player &player) {
for (const auto& enemy : enemies) {
if (enemy->isAlive() && enemy->checkPlayerCollision(player)) {
player.health -= getDamageFromEnemy(enemy.get());
std::cout << "玩家受到攻击,生命值剩余:" << player.health << std::endl;
if (player.health <= 0) {
std::cout << "玩家死亡,游戏结束!" << std::endl;
closegraph();
exit(0);
}
}
}
}
// 根据敌人类型获取敌人对玩家造成的伤害值
int getDamageFromEnemy(const std::unique_ptr<Enemy>& enemy) {
if (dynamic_cast<EnemyType1*>(enemy.get())) return 5;
if (dynamic_cast<EnemyType2*>(enemy.get())) return 8;
return 0;
}
// 从文件读取关卡配置信息来初始化关卡列表,更灵活可扩展
void initLevelsFromFile(Level levels[]) {
std::ifstream file("levels.txt");
if (file.is_open()) {
std::string line;
int index = 0;
while (std::getline(file, line)) {
std::stringstream ss(line);
int numEnemies;
ss >> numEnemies;
levels[index].levelNumber = index + 1;
levels[index].numEnemies = numEnemies;
int enemyType;
while (ss >> enemyType) {
levels[index].enemyTypes.push_back(enemyType);
}
index++;
}
file.close();
}
else {
std::cerr << "无法打开关卡配置文件!" << std::endl;
}
}
// 显示当前关卡信息(美化显示样式)
void showLevelInfo(Level level) {
SetTextColor(RGB(0,0,0));
SetTextStyle(20, 0, "宋体");
std::string info = "关卡 " + std::to_string(level.levelNumber);
outtextxy(10, 10, info.c_str());
}
// 显示玩家得分和生命值信息(美化显示样式)
void showPlayerInfo(Player player) {
SetTextColor(RGB(0,0,0));
SetTextStyle(20, 0, "宋体");
std::string scoreInfo = "得分: " + std::to_string(player.score);
std::string healthInfo = " 生命值: " + std::to_string(player.health);
outtextxy(10, 40, scoreInfo.c_str());
outtextxy(10, 70, healthInfo.c_str());
}
// 绘制游戏主菜单界面(简单示例,可拓展更多菜单选项等)
void drawMainMenu() {
SetTextColor(RGB(0,0,0));
SetTextStyle(40, 0, "宋体");
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 - 50, "射击游戏");
SetTextStyle(20, 0, "宋体");
outtextxy(WIDTH / 2 - 80, HEIGHT / 2 + 20, "按任意键开始游戏");
}
// 处理游戏主菜单逻辑(等待按键开始游戏)
void handleMainMenu() {
if (_kbhit()) {
gameState = GameState::IN_GAME;
}
}
// 处理关卡完成逻辑(完善了更多操作,如关卡切换、资源释放与初始化等)
void handleLevelCompleted() {
std::cout << "关卡完成!即将进入下一关..." << std::endl;
currentLevel++;
if (currentLevel < 15) {
player.x = WIDTH / 2;
player.y = HEIGHT / 2;
player.health = 100;
player.score = 0;
Level current = levels[currentLevel];
initEnemies(current, enemies);
gameState = GameState::IN_GAME;
}
else {
gameState = GameState::GAME_OVER;
std::cout << "恭喜你通关了!最终得分: " << player.score << std::endl;
}
}
// 处理游戏结束逻辑(释放相关资源等)
void handleGameOver() {
std::cout << "游戏结束!最终得分: " << player.score << std::endl;
closegraph();
}
// 枪械类的构造函数实现,可考虑后续优化数据存储方式(如配置文件等)
Gun::Gun(int type) {
this->type = type;
switch (type) {
case 1:
name = "格洛克17";
fireRate = 10;
bulletSpeed = 10;
damage = 20;
magazineCapacity = 10;
currentBullets = 10;
break;
case 2:
name = "AK-47";
fireRate = 3;
bulletSpeed = 15;
damage = 30;
magazineCapacity = 30;
currentBullets = 30;
break;
case 3:
name = "雷明顿870";
fireRate = 8;
bulletSpeed = 8;
damage = 15;
magazineCapacity = 5;
currentBullets = 5;
break;
case 4:
name = "M4A1";
fireRate = 5;
bulletSpeed = 12;
damage = 25;
magazineCapacity = 20;
currentBullets = 20;
break;
case 5:
name = "沙漠之鹰";
fireRate = 15;
bulletSpeed = 20;
damage = 10;
magazineCapacity = 15;
currentBullets = 15;
break;
case 6:
name = "Uzi";
fireRate = 12;
bulletSpeed = 8;
damage = 12;
magazineCapacity = 25;
currentBullets = 25;
break;
case 7:
name = "MP5";
fireRate = 9;
bulletSpeed = 10;
damage = 18;
magazineCapacity = 30;
currentBullets = 30;
break;
case 48:
name = "FN SCAR";
fireRate = 6;
bulletSpeed = 18;
damage = 35;
magazineCapacity = 8;
currentBullets = 8;
break;
}
}
// Enemy基类的构造函数实现
Enemy::Enemy(int x, int y) : x(x), y(y), health(0), alive(true) {}
// 判断敌人是否存活的函数实现(基类已有默认实现,派生类可按需重写)
bool Enemy::isAlive() const {
return alive;
}
// 具体敌人类型1的构造函数实现
EnemyType1::EnemyType1(int x, int y) : Enemy(x, y), speed(3), attackCooldown(0) {}
// 具体敌人类型1的绘制函数实现(这里只是示例,需根据实际绘图逻辑完善)
void EnemyType1::draw() {
// 假设这里有绘图代码,暂用输出语句替代示意
std::cout << "绘制EnemyType1敌人" << std::endl;
}
// 具体敌人类型1获取速度函数实现
int EnemyType1::getSpeed() const {
return speed;
}
// 具体敌人类型1获取生命值函数实现
int EnemyType1::getHealth() const {
return health;
}
// 具体敌人类型1受到伤害函数实现(这里调用基类默认实现即可)
void EnemyType1::takeDamage(int damage) {
Enemy::takeDamage(damage);
}
// 具体敌人类型1更新状态函数实现(简单追踪玩家示例,需完善逻辑)
void EnemyType1::update(Player player) {
// 简单示例,朝玩家方向移动,这里只是示意,实际可能更复杂
if (x < player.x) {
x += speed;
}
else if (x > player.x) {
x -= speed;
}
if (y < player.y) {
y += speed;
}
else if (y > player.y) {
y -= speed;
}
}
// 具体敌人类型1检查与子弹碰撞函数实现(这里只是示例,需根据实际碰撞