#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include <random>
#include <conio.h>
#include <windows.h>
#include <algorithm>
#include <string>
#include <atomic>
#include <mutex>
#include <condition_variable>
using namespace std;
// ====================== 游戏常量 ======================
const int SCREEN_WIDTH = 80;
const int SCREEN_HEIGHT = 24;
const int PLAYER_WIDTH = 3;
const int PLAYER_HEIGHT = 2;
const int ENEMY_WIDTH = 3;
const int ENEMY_HEIGHT = 2;
const int BULLET_SPEED = 2;
const int ENEMY_SPEED = 1;
const int MAX_ENEMIES = 5; // 减少最大敌人数
const int MAX_BULLETS = 25; // 减少最大子弹数
const int MAX_POWERUPS = 3; // 减少最大道具数
const int GAME_TICK_MS = 33;
// ====================== 游戏状态 ======================
atomic<bool> gameRunning(true);
mutex gameMutex;
condition_variable gameCV;
// ====================== 游戏对象 ======================
struct GameObject {
int x, y;
int width, height;
bool active;
const char* sprite; // 改为指针减少拷贝
};
struct Player : public GameObject {
int lives;
int health;
int maxHealth;
int score;
int powerLevel;
int powerUpTimer;
int invincibleTimer;
Player() {
x = SCREEN_WIDTH / 2;
y = SCREEN_HEIGHT - PLAYER_HEIGHT - 1;
width = PLAYER_WIDTH;
height = PLAYER_HEIGHT;
active = true;
lives = 3;
health = 10;
maxHealth = 10;
score = 0;
powerLevel = 1;
powerUpTimer = 0;
invincibleTimer = 0;
sprite = " ^ \n/ \\";
}
bool isInvincible() const {
return invincibleTimer > 0;
}
};
struct Bullet : public GameObject {
bool isPlayerBullet;
int damage;
Bullet(int x, int y, bool playerBullet, int dmg = 1) {
this->x = x;
this->y = y;
width = 1;
height = 1;
active = true;
isPlayerBullet = playerBullet;
damage = dmg;
sprite = playerBullet ? "o" : "x";
}
};
struct Enemy : public GameObject {
int health;
int maxHealth;
int movePattern;
int moveTimer;
int scoreValue;
Enemy() {
width = ENEMY_WIDTH;
height = ENEMY_HEIGHT;
active = true;
health = 2 + rand() % 4; // 减少敌人血量
maxHealth = health;
movePattern = rand() % 3;
moveTimer = 0;
scoreValue = health * 30; // 调整分数
sprite = "\\ /\n V ";
}
};
struct PowerUp : public GameObject {
int type;
PowerUp() {
width = 1;
height = 1;
active = true;
type = rand() % 4 + 1;
sprite = type == 1 ? "H" : (type == 2 ? "P" : (type == 3 ? "B" : "S"));
}
};
// ====================== 游戏引擎 ======================
class GameEngine {
private:
Player player;
vector<Bullet> bullets;
vector<Enemy> enemies;
vector<PowerUp> powerUps;
vector<string> screenBuffer;
chrono::time_point<chrono::steady_clock> lastUpdate;
random_device rd;
mt19937 gen;
uniform_int_distribution<> disX;
uniform_int_distribution<> disY;
uniform_int_distribution<> disPattern;
// 预计算UI元素
string scoreText;
string livesText;
string powerText;
string invincibleText;
public:
GameEngine() : gen(rd()), disX(0, SCREEN_WIDTH - ENEMY_WIDTH),
disY(0, SCREEN_HEIGHT / 3), disPattern(0, 100) {
screenBuffer.resize(SCREEN_HEIGHT, string(SCREEN_WIDTH, ' '));
lastUpdate = chrono::steady_clock::now();
// 预初始化UI文本
scoreText.reserve(20);
livesText.reserve(20);
powerText.reserve(30);
invincibleText = "INVINCIBLE!";
}
void init() {
player = Player();
bullets.clear();
bullets.reserve(MAX_BULLETS); // 预分配内存
enemies.clear();
enemies.reserve(MAX_ENEMIES);
powerUps.clear();
powerUps.reserve(MAX_POWERUPS);
// 初始生成少量敌人
for (int i = 0; i < 3; ++i) {
spawnEnemy();
}
}
void spawnEnemy() {
if (enemies.size() >= MAX_ENEMIES) return;
Enemy enemy;
enemy.x = disX(gen);
enemy.y = disY(gen);
enemies.push_back(enemy);
}
void spawnPowerUp(int x, int y) {
if (powerUps.size() >= MAX_POWERUPS) return;
PowerUp pu;
pu.x = x;
pu.y = y;
powerUps.push_back(pu);
}
void update() {
auto now = chrono::steady_clock::now();
auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - lastUpdate).count();
if (elapsed < GAME_TICK_MS) {
this_thread::sleep_for(chrono::milliseconds(1));
return;
}
lastUpdate = now;
// 处理输入
handleInput();
// 更新玩家状态
updatePlayer();
// 更新子弹
updateBullets();
// 更新敌人
updateEnemies();
// 更新道具
updatePowerUps();
// 碰撞检测
checkCollisions();
// 渲染准备
prepareRender();
}
void updatePlayer() {
if (player.powerUpTimer > 0) {
if (--player.powerUpTimer == 0) {
player.powerLevel = max(1, player.powerLevel - 1);
}
}
if (player.invincibleTimer > 0) {
player.invincibleTimer--;
}
}
void updateBullets() {
for (auto it = bullets.begin(); it != bullets.end(); ) {
if (it->isPlayerBullet) {
it->y -= BULLET_SPEED;
} else {
it->y += BULLET_SPEED;
}
if (it->y < 0 || it->y >= SCREEN_HEIGHT) {
it = bullets.erase(it); // 原地删除
} else {
++it;
}
}
}
void updateEnemies() {
// 敌人移动和生成逻辑
int activeEnemies = 0;
for (auto it = enemies.begin(); it != enemies.end(); ) {
if (!it->active) {
it = enemies.erase(it);
continue;
}
activeEnemies++;
it->moveTimer++;
// 简化移动模式
switch (it->movePattern) {
case 0: it->y += ENEMY_SPEED; break;
case 1:
it->y += ENEMY_SPEED / 2;
it->x += (it->moveTimer % 20 < 10) ? 1 : -1;
break;
case 2:
if (it->moveTimer % 10 == 0) {
it->x += rand() % 3 - 1;
}
it->y += ENEMY_SPEED / 3;
break;
}
// 边界检查
it->x = max(0, min(SCREEN_WIDTH - it->width, it->x));
// 敌人射击 - 降低频率
if (rand() % 120 < 2) {
fireBullet(it->x + it->width / 2, it->y + it->height, false, 1);
}
// 检查是否到达底部
if (it->y >= SCREEN_HEIGHT - 1) {
it->active = false;
if (!player.isInvincible()) {
player.health -= 2;
}
it = enemies.erase(it);
} else {
++it;
}
}
// 动态调整敌人生成率
if (activeEnemies < MAX_ENEMIES / 2 && rand() % 100 < 3) {
spawnEnemy();
}
}
void updatePowerUps() {
for (auto it = powerUps.begin(); it != powerUps.end(); ) {
it->y += 1;
if (it->y >= SCREEN_HEIGHT || !it->active) {
it = powerUps.erase(it);
} else {
++it;
}
}
}
void handleInput() {
if (_kbhit()) {
char ch = _getch();
lock_guard<mutex> lock(gameMutex);
switch (ch) {
case 'a': case 'A':
player.x = max(0, player.x - 2);
break;
case 'd': case 'D':
player.x = min(SCREEN_WIDTH - player.width, player.x + 2);
break;
case ' ':
fireBullet(player.x + player.width / 2, player.y, true, player.powerLevel);
break;
case 'q': case 'Q':
gameRunning = false;
gameCV.notify_all();
break;
}
}
}
void fireBullet(int x, int y, bool isPlayer, int damage = 1) {
if (isPlayer) {
if (bullets.size() >= MAX_BULLETS) return;
bullets.emplace_back(x, y, true, damage);
// 简化武器升级效果
if (player.powerLevel > 1) {
bullets.emplace_back(x - 2, y, true, damage);
if (player.powerLevel > 2) {
bullets.emplace_back(x + 2, y, true, damage);
}
}
} else {
if (bullets.size() < MAX_BULLETS) {
bullets.emplace_back(x, y, false, 1);
}
}
}
void checkCollisions() {
// 玩家子弹与敌人碰撞
for (auto& bullet : bullets) {
if (!bullet.isPlayerBullet || !bullet.active) continue;
for (auto& enemy : enemies) {
if (!enemy.active) continue;
if (checkCollision(bullet, enemy)) {
bullet.active = false;
enemy.health -= bullet.damage;
if (enemy.health <= 0) {
enemy.active = false;
player.score += enemy.scoreValue;
// 降低道具掉落率
if (rand() % 100 < 15) {
spawnPowerUp(enemy.x + enemy.width / 2, enemy.y + enemy.height);
}
}
break; // 一颗子弹只能击中一个敌人
}
}
}
// 敌人子弹与玩家碰撞
for (auto& bullet : bullets) {
if (bullet.isPlayerBullet || !bullet.active || player.isInvincible()) continue;
if (checkCollision(bullet, player)) {
bullet.active = false;
player.health -= bullet.damage;
if (player.health <= 0) {
player.lives--;
player.health = player.maxHealth;
player.invincibleTimer = 50;
}
break;
}
}
// 玩家与敌人碰撞
for (auto& enemy : enemies) {
if (!enemy.active || player.isInvincible()) continue;
if (checkCollision(player, enemy)) {
enemy.active = false;
player.health -= 2;
if (player.health <= 0) {
player.lives--;
player.health = player.maxHealth;
player.invincibleTimer = 50;
}
break;
}
}
// 玩家与道具碰撞
for (auto& pu : powerUps) {
if (!pu.active) continue;
if (checkCollision(player, pu)) {
pu.active = false;
switch (pu.type) {
case 1: player.health = min(player.maxHealth, player.health + 3); break;
case 2:
player.powerLevel = min(3, player.powerLevel + 1);
player.powerUpTimer = 300; // 缩短强化时间
break;
case 3:
for (auto& enemy : enemies) {
enemy.active = false;
player.score += 30; // 减少炸弹奖励
}
break;
case 4: player.invincibleTimer = 80; break; // 缩短无敌时间
}
}
}
// 检查游戏结束
if (player.lives <= 0) {
gameRunning = false;
gameCV.notify_all();
}
}
bool checkCollision(const GameObject& obj1, const GameObject& obj2) {
return obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y;
}
void drawObject(const GameObject& obj) {
if (!obj.active) return;
int spriteX = 0;
int spriteY = 0;
for (const char* p = obj.sprite; *p != '\0'; ++p) {
if (*p == '\n') {
spriteY++;
spriteX = 0;
continue;
}
int screenX = obj.x + spriteX;
int screenY = obj.y + spriteY;
if (screenX >= 0 && screenX < SCREEN_WIDTH &&
screenY >= 0 && screenY < SCREEN_HEIGHT) {
screenBuffer[screenY][screenX] = *p;
}
spriteX++;
}
}
void drawHealthBar(int x, int y, int current, int max) {
float ratio = static_cast<float>(current) / max;
int bars = static_cast<int>(20 * ratio);
string bar = "[";
for (int i = 0; i < 20; ++i) {
bar += (i < bars) ? "=" : " ";
}
bar += "] " + to_string(current) + "/" + to_string(max);
for (int i = 0; i < bar.size() && x + i < SCREEN_WIDTH; ++i) {
screenBuffer[y][x + i] = bar[i];
}
}
void prepareRender() {
// 清空屏幕缓冲区
for (auto& line : screenBuffer) {
fill(line.begin(), line.end(), ' ');
}
// 绘制游戏对象
drawObject(player);
for (const auto& bullet : bullets) {
drawObject(bullet);
}
for (const auto& enemy : enemies) {
drawObject(enemy);
drawHealthBar(enemy.x, enemy.y - 1, enemy.health, enemy.maxHealth);
}
for (const auto& pu : powerUps) {
drawObject(pu);
}
// 绘制UI
drawUI();
}
void drawUI() {
// 预生成UI文本减少字符串操作
scoreText = "Score: " + to_string(player.score);
copy(scoreText.begin(), scoreText.end(), screenBuffer[0].begin());
livesText = "Lives: " + to_string(player.lives);
copy(livesText.rbegin(), livesText.rend(), screenBuffer[0].rbegin());
// 玩家血条
drawHealthBar(0, 1, player.health, player.maxHealth);
// 武器状态
powerText = "Weapon: Lv." + to_string(player.powerLevel);
if (player.powerUpTimer > 0) {
powerText += " (" + to_string(player.powerUpTimer / 20) + ")";
}
copy(powerText.begin(), powerText.end(), screenBuffer[2].begin());
// 无敌状态
if (player.isInvincible()) {
int pos = (SCREEN_WIDTH - invincibleText.size()) / 2;
copy(invincibleText.begin(), invincibleText.end(), screenBuffer[SCREEN_HEIGHT-1].begin() + pos);
}
}
void render() {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord = {0, 0};
SetConsoleCursorPosition(hConsole, coord);
// 使用单个cout输出提高性能
string output;
output.reserve(SCREEN_WIDTH * SCREEN_HEIGHT * 2);
for (const auto& line : screenBuffer) {
output += line + "\n";
}
cout << output;
}
void gameLoop() {
init();
while (gameRunning) {
update();
render();
}
// 游戏结束画面
system("cls");
cout << "==================================" << endl;
cout << " GAME OVER " << endl;
cout << "==================================" << endl;
cout << " Final Score: " << player.score << endl;
cout << "==================================" << endl;
cout << " Press any key to exit..." << endl;
_getch();
}
};
void inputThread() {
while (gameRunning) {
if (_kbhit()) {
unique_lock<mutex> lock(gameMutex);
gameCV.wait(lock, []{ return !gameRunning; });
break;
}
this_thread::sleep_for(chrono::milliseconds(10));
}
}
int main() {
// 设置控制台窗口
HWND console = GetConsoleWindow();
RECT r;
GetWindowRect(console, &r);
MoveWindow(console, r.left, r.top, 800, 600, TRUE);
// 隐藏光标
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(out, &cursorInfo);
cursorInfo.bVisible = false;
SetConsoleCursorInfo(out, &cursorInfo);
// 设置控制台字体
CONSOLE_FONT_INFOEX cfi;
cfi.cbSize = sizeof(cfi);
cfi.nFont = 0;
cfi.dwFontSize.X = 8;
cfi.dwFontSize.Y = 12;
cfi.FontFamily = FF_DONTCARE;
cfi.FontWeight = FW_NORMAL;
wcscpy_s(cfi.FaceName, L"Consolas");
SetCurrentConsoleFontEx(out, FALSE, &cfi);
// 启动游戏
GameEngine game;
thread input(inputThread);
game.gameLoop();
if (input.joinable()) {
input.join();
}
return 0;
}