格斗游戏
2026-08-14 14:26:02
发布于:广东
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <string>
#include <sstream>
#include <cmath>
// ================= 常量设置 =================
const int SCREEN_WIDTH = 70;
const int SCREEN_HEIGHT = 18;
const int GROUND_Y = 15;
const int MAX_HP = 100;
const int GRAVITY = 1;
// 枚举定义
enum ItemType { WEP_SWORD, WEP_SPEAR, WEP_GUN, ARM_IRON, POT_HEALTH, BOMB };
enum SkillType { SKILL_BLINK, SKILL_SHIELD, SKILL_STOMP, SKILL_NONE };
enum EntityType { ENT_PLAYER, ENT_CPU };
// ================= 基础结构体 =================
struct Item {
int x, y; ItemType type; char symbol; bool active;
};
struct Obstacle {
int x, y, w, h; // x,y是左上角,w,h是宽高
};
struct Projectile {
int x, y, vx; // vx: 速度方向 (-1 或 1)
int owner; // 0:P1, 1:P2
bool active;
};
// ================= 玩家类 =================
class Fighter {
public:
int x, y; // 中心坐标,y是脚底
int velY; // Y轴速度 (用于跳跃)
int hp, maxHp;
bool isAttacking, isJumping, isSliding;
int attackTimer, slideTimer;
bool facingRight;
int baseAttack, bonusAttack, armor;
int attackRange, moveSpeed;
int ammo; // 远程弹药
// 技能系统
SkillType skill;
int skillCD; // 当前冷却
int skillMaxCD; // 最大冷却
int shieldTimer; // 护盾持续时间
Fighter() { reset(10, true); }
void reset(int startX, bool faceRight) {
x = startX; y = GROUND_Y; velY = 0;
maxHp = MAX_HP; hp = maxHp;
isAttacking = isJumping = isSliding = false;
attackTimer = slideTimer = 0;
facingRight = faceRight;
baseAttack = 5; bonusAttack = 0; armor = 0;
attackRange = 2; moveSpeed = 1; ammo = 0;
skill = SKILL_NONE; skillCD = 0; skillMaxCD = 0; shieldTimer = 0;
}
void setSkill(SkillType s) {
skill = s;
if (s == SKILL_BLINK) skillMaxCD = 120; // 4秒
else if (s == SKILL_SHIELD) skillMaxCD = 240; // 8秒
else if (s == SKILL_STOMP) skillMaxCD = 180; // 6秒
skillCD = 0;
}
void moveLeft() {
int step = isSliding ? 3 : moveSpeed;
for(int i=0; i<step; ++i) { if (x > 2 && !checkObstacleCollision(x-1, y)) x--; }
facingRight = false;
}
void moveRight() {
int step = isSliding ? 3 : moveSpeed;
for(int i=0; i<step; ++i) { if (x < SCREEN_WIDTH - 3 && !checkObstacleCollision(x+1, y)) x++; }
facingRight = true;
}
void jump() {
if (!isJumping && y >= GROUND_Y) {
velY = -3; // 初始向上速度
isJumping = true;
}
}
void slide() {
if (!isSliding && !isJumping) {
isSliding = true;
slideTimer = 12; // 滑铲持续12帧
}
}
void attack() {
if (!isAttacking) {
isAttacking = true;
attackTimer = 8;
}
}
void useSkill(Fighter& opponent) {
if (skillCD > 0 || skill == SKILL_NONE) return;
if (skill == SKILL_BLINK) {
int dir = facingRight ? 6 : -6;
if (!checkObstacleCollision(x + dir, y)) x += dir;
else x += (dir > 0 ? 3 : -3); // 碰壁则短距离瞬移
}
else if (skill == SKILL_SHIELD) {
shieldTimer = 90; // 护盾持续3秒
}
else if (skill == SKILL_STOMP) {
if (abs(x - opponent.x) <= 4 && abs(y - opponent.y) <= 2) {
int dmg = std::max(5, 20 - opponent.armor);
opponent.hp -= dmg;
}
}
skillCD = skillMaxCD;
}
void update() {
// 物理与重力
if (isJumping || y < GROUND_Y) {
y += velY;
velY += GRAVITY;
if (y >= GROUND_Y) {
y = GROUND_Y;
velY = 0;
isJumping = false;
}
}
// 状态计时器
if (isAttacking) { if (--attackTimer <= 0) isAttacking = false; }
if (isSliding) { if (--slideTimer <= 0) isSliding = false; }
if (shieldTimer > 0) shieldTimer--;
if (skillCD > 0) skillCD--;
}
void pickUpItem(Item& item, Fighter& opponent) {
switch(item.type) {
case WEP_SWORD: bonusAttack += 5; break;
case WEP_SPEAR: bonusAttack += 4; attackRange = 3; break;
case WEP_GUN: ammo += 5; break;
case ARM_IRON: armor += 5; break;
case POT_HEALTH: hp = std::min(maxHp, hp + 40); break;
case BOMB: opponent.hp -= 20; break;
}
item.active = false;
}
// 碰撞检测辅助 (需在外部实现,这里声明)
bool checkObstacleCollision(int nextX, int nextY);
// 渲染
void drawToScreen(char screen[][SCREEN_WIDTH]) {
if (isSliding) {
// 滑铲姿势 (变矮,躲避子弹)
setChar(screen, x, y, '@');
setChar(screen, x + (facingRight ? 1 : -1), y, '=');
} else {
// 正常/跳跃姿势
setChar(screen, x, y - 2, '@'); // 头
setChar(screen, x - 1, y, '/'); // 左腿
setChar(screen, x + 1, y, '\\');// 右腿
setChar(screen, x, y - 1, '|'); // 身体
if (isAttacking) {
if (facingRight) {
setChar(screen, x + 1, y - 1, '-');
setChar(screen, x + 2, y - 1, '>');
} else {
setChar(screen, x - 1, y - 1, '-');
setChar(screen, x - 2, y - 1, '<');
}
} else {
setChar(screen, x - 1, y - 1, '/');
setChar(screen, x + 1, y - 1, '\\');
}
}
// 护盾特效
if (shieldTimer > 0) {
setChar(screen, x - 1, y - 2, '(');
setChar(screen, x + 1, y - 2, ')');
}
}
private:
void setChar(char screen[][SCREEN_WIDTH], int cx, int cy, char c) {
if (cx >= 0 && cx < SCREEN_WIDTH && cy >= 0 && cy < SCREEN_HEIGHT) {
screen[cy][cx] = c;
}
}
};
// ================= 全局变量 =================
Fighter p1, p2;
stdvector<Item> items;
stdvector<Obstacle> obstacles;
stdvector<Projectile> bullets;
bool gameOver = false;
stdstring winner = "";
int frameCount = 0;
int aiCooldown = 0;
bool isPvEMode = false;
// ================= 辅助函数 =================
stdstring intToString(int val) { stdostringstream oss; oss << val; return oss.str(); }
void printLine(const stdstring& text) {
stdcout << text;
if (text.length() < SCREEN_WIDTH) stdcout << stdstring(SCREEN_WIDTH - text.length(), ' ');
std::cout << "\n";
}
void gotoxy(int x, int y) {
COORD coord; coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void hideCursor() {
CONSOLE_CURSOR_INFO info; GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
info.bVisible = false; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
}
void clearScreen() { system("cls"); }
// 全局障碍物碰撞检测实现
bool Fighter::checkObstacleCollision(int nextX, int nextY) {
for (size_t i = 0; i < obstacles.size(); ++i) {
int ox = obstacles[i].x, oy = obstacles[i].y;
int ow = obstacles[i].w, oh = obstacles[i].h;
// 玩家碰撞箱简化为 宽3 高3 (x-1 到 x+1, y-2 到 y)
if (nextX + 1 >= ox && nextX - 1 <= ox + ow - 1 &&
nextY >= oy && nextY - 2 <= oy + oh - 1) {
return true;
}
}
return false;
}
// ================= 菜单与初始化 =================
int showMainMenu() {
clearScreen();
gotoxy(20, 3); stdcout << "================================" << stdendl;
gotoxy(20, 4); stdcout << " C++ PLATFORM FIGHTER v3.0 " << stdendl;
gotoxy(20, 5); stdcout << "================================" << stdendl;
gotoxy(23, 8); stdcout << "1. Player vs Player (PvP)" << stdendl;
gotoxy(23, 10); stdcout << "2. Player vs CPU (PvE)" << stdendl;
gotoxy(23, 12); stdcout << "3. Exit Game" << stdendl;
gotoxy(20, 16); std::cout << "Select (1-3): ";
while (true) {
if (_kbhit()) {
char key = _getch();
if (key == '1') return 1;
if (key == '2') return 2;
if (key == '3') return 3;
}
Sleep(50);
}
}
SkillType selectSkillMenu(const stdstring& playerName) {
clearScreen();
gotoxy(15, 3); stdcout << "=== Select Skill for " << playerName << " ===" << stdendl;
gotoxy(15, 6); stdcout << "1. Blink (Teleport short distance, CD 4s)" << stdendl;
gotoxy(15, 8); stdcout << "2. Shield (50% Damage reduction for 3s, CD 8s)" << stdendl;
gotoxy(15, 10); stdcout << "3. Stomp (AOE damage around you, CD 6s)" << stdendl;
gotoxy(15, 14); stdcout << "Choose (1-3): ";
while (true) {
if (_kbhit()) {
char key = _getch();
if (key == '1') return SKILL_BLINK;
if (key == '2') return SKILL_SHIELD;
if (key == '3') return SKILL_STOMP;
}
Sleep(50);
}
}
void generateTerrain() {
obstacles.clear();
// 随机生成 2-4 个障碍物
int numObs = 2 + rand() % 3;
for (int i = 0; i < numObs; ++i) {
Obstacle obs;
obs.w = 2; obs.h = 2; // 2x2 的箱子
obs.x = 10 + rand() % (SCREEN_WIDTH - 20);
obs.y = GROUND_Y - obs.h + 1; // 放在地上
// 避免生成在玩家初始位置
if (abs(obs.x - 15) < 5 || abs(obs.x - 55) < 5) {
obs.x += 10;
}
obstacles.push_back(obs);
}
}
void resetGame() {
p1.reset(15, true);
p2.reset(55, false);
items.clear(); bullets.clear();
gameOver = false; winner = ""; frameCount = 0; aiCooldown = 0;
generateTerrain();
}
// ================= 游戏核心逻辑 =================
void spawnItem() {
if (items.size() < 3 && frameCount % 150 == 0) {
Item newItem;
newItem.x = 5 + rand() % (SCREEN_WIDTH - 10);
newItem.y = GROUND_Y;
int r = rand() % 6;
if (r == 0) { newItem.type = WEP_SWORD; newItem.symbol = 's'; }
else if (r == 1) { newItem.type = WEP_SPEAR; newItem.symbol = 'p'; }
else if (r == 2) { newItem.type = WEP_GUN; newItem.symbol = 'g'; }
else if (r == 3) { newItem.type = ARM_IRON; newItem.symbol = 'i'; }
else if (r == 4) { newItem.type = POT_HEALTH; newItem.symbol = 'h'; }
else { newItem.type = BOMB; newItem.symbol = 'b'; }
newItem.active = true; items.push_back(newItem);
}
}
void updateAI(Fighter& cpu, Fighter& player) {
if (aiCooldown > 0) { aiCooldown--; return; }
aiCooldown = 8 + rand() % 12;
int dist = abs(cpu.x - player.x);
// 1. 技能使用逻辑
if (cpu.skillCD == 0 && cpu.skill != SKILL_NONE) {
if (cpu.skill == SKILL_STOMP && dist <= 4) cpu.useSkill(player);
else if (cpu.skill == SKILL_SHIELD && cpu.hp < 40) cpu.useSkill(player);
else if (cpu.skill == SKILL_BLINK && dist > 10 && rand() % 2 == 0) cpu.useSkill(player);
}
// 2. 远程武器逻辑
if (cpu.ammo > 0 && dist > 5 && dist < 20 && rand() % 3 == 0) {
cpu.attack(); return;
}
// 3. 移动与战斗
if (dist > cpu.attackRange + 2) {
if (player.x < cpu.x) cpu.moveLeft(); else cpu.moveRight();
if (rand() % 5 == 0 && !cpu.isJumping) cpu.jump(); // 随机跳跃
} else if (dist <= cpu.attackRange) {
int action = rand() % 100;
if (action < 60) cpu.attack();
else if (action < 80) {
if (rand() % 2 == 0) cpu.slide(); // 滑铲躲避
else { if (player.x < cpu.x) cpu.moveRight(); else cpu.moveLeft(); }
}
}
}
void handleInput() {
if (_kbhit()) {
int key = _getch();
if (key == 224 || key == 0) { // 方向键
key = _getch();
if (!gameOver && !isPvEMode) {
switch (key) {
case 75: p2.moveLeft(); break; // Left
case 77: p2.moveRight(); break; // Right
case 72: p2.jump(); break; // Up
case 80: p2.slide(); break; // Down
}
}
} else {
if (key == 27) exit(0); // ESC
if (!gameOver) {
// P1 控制: A/D, W, S, J, K
switch (key) {
case 'a': case 'A': p1.moveLeft(); break;
case 'd': case 'D': p1.moveRight(); break;
case 'w': case 'W': p1.jump(); break;
case 's': case 'S': p1.slide(); break;
case 'j': case 'J': p1.attack(); break;
case 'k': case 'K': p1.useSkill(p2); break;
}
// P2 控制: 1(攻击), 2(技能)
if (!isPvEMode) {
if (key == '1') p2.attack();
if (key == '2') p2.useSkill(p1);
}
}
}
}
}
void updateGame() {
if (gameOver) return;
frameCount++;
p1.update(); p2.update();
if (isPvEMode) updateAI(p2, p1);
// 道具碰撞
for (size_t i = 0; i < items.size(); ++i) {
if (items[i].active) {
if (abs(p1.x - items[i].x) <= 1 && p1.y == items[i].y) p1.pickUpItem(items[i], p2);
if (abs(p2.x - items[i].x) <= 1 && p2.y == items[i].y) p2.pickUpItem(items[i], p1);
}
}
for (std::vector<Item>::iterator it = items.begin(); it != items.end(); ) {
if (!it->active) it = items.erase(it); else ++it;
}
// 子弹更新
for (size_t i = 0; i < bullets.size(); ++i) {
if (bullets[i].active) {
bullets[i].x += bullets[i].vx;
// 出界销毁
if (bullets[i].x < 0 || bullets[i].x >= SCREEN_WIDTH) bullets[i].active = false;
// 碰障碍物销毁
for (size_t j = 0; j < obstacles.size(); ++j) {
if (bullets[i].x >= obstacles[j].x && bullets[i].x < obstacles[j].x + obstacles[j].w &&
bullets[i].y >= obstacles[j].y && bullets[i].y < obstacles[j].y + obstacles[j].h) {
bullets[i].active = false; break;
}
}
// 击中判定 (滑铲时 y 坐标判定变严格,可躲避子弹)
Fighter& target = (bullets[i].owner == 0) ? p2 : p1;
int hitY = target.isSliding ? target.y : target.y - 1;
if (abs(bullets[i].x - target.x) <= 1 && bullets[i].y == hitY) {
int dmg = std::max(1, 15 - target.armor);
if (target.shieldTimer > 0) dmg /= 2;
target.hp -= dmg;
bullets[i].active = false;
}
}
}
for (std::vector<Projectile>::iterator it = bullets.begin(); it != bullets.end(); ) {
if (!it->active) it = bullets.erase(it); else ++it;
}
// 近战攻击判定
int distance = abs(p1.x - p2.x);
// P1 攻击
if (p1.isAttacking && p1.attackTimer == 7) {
if (p1.ammo > 0) { // 发射子弹
Projectile b; b.x = p1.x; b.y = p1.y - 1; b.vx = p1.facingRight ? 2 : -2; b.owner = 0; b.active = true;
bullets.push_back(b); p1.ammo--;
} else if (distance <= p1.attackRange && abs(p1.y - p2.y) <= 2) { // 近战
int dmg = std::max(1, (p1.baseAttack + p1.bonusAttack) - p2.armor);
if (p2.shieldTimer > 0) dmg /= 2;
if (!p2.isSliding) p2.hp -= dmg; // 滑铲无敌
}
}
// P2 攻击
if (p2.isAttacking && p2.attackTimer == 7) {
if (p2.ammo > 0) {
Projectile b; b.x = p2.x; b.y = p2.y - 1; b.vx = p2.facingRight ? 2 : -2; b.owner = 1; b.active = true;
bullets.push_back(b); p2.ammo--;
} else if (distance <= p2.attackRange && abs(p1.y - p2.y) <= 2) {
int dmg = std::max(1, (p2.baseAttack + p2.bonusAttack) - p1.armor);
if (p1.shieldTimer > 0) dmg /= 2;
if (!p1.isSliding) p1.hp -= dmg;
}
}
// 胜负
if (p1.hp <= 0) { p1.hp = 0; gameOver = true; winner = isPvEMode ? "CPU" : "PLAYER 2"; }
else if (p2.hp <= 0) { p2.hp = 0; gameOver = true; winner = "PLAYER 1"; }
}
void draw() {
gotoxy(0, 0);
std::string title = isPvEMode ? "=== PLATFORM FIGHTER (PvE) =" : "= PLATFORM FIGHTER (PvP) ===";
printLine(title);
// UI 状态
std::string p1SkillStr = (p1.skillCD > 0) ? "CD:" + intToString(p1.skillCD/30) + "s" : "READY";
std::string p1Status = "P1 HP:[";
for (int i = 0; i < p1.hp / 2; i++) p1Status += "#";
for (int i = 0; i < (p1.maxHp - p1.hp) / 2; i++) p1Status += " ";
p1Status += "] " + intToString(p1.hp) + " | Ammo:" + intToString(p1.ammo) + " | Skill:" + p1SkillStr;
printLine(p1Status);
std::string p2Name = isPvEMode ? "CPU" : "P2";
std::string p2SkillStr = (p2.skillCD > 0) ? "CD:" + intToString(p2.skillCD/30) + "s" : "READY";
std::string p2Status = p2Name + " HP:[";
for (int i = 0; i < p2.hp / 2; i++) p2Status += "#";
for (int i = 0; i < (p2.maxHp - p2.hp) / 2; i++) p2Status += " ";
p2Status += "] " + intToString(p2.hp) + " | Ammo:" + intToString(p2.ammo) + " | Skill:" + p2SkillStr;
printLine(p2Status);
printLine("----------------------------------------------------------------------");
// 缓冲区
char screen[SCREEN_HEIGHT][SCREEN_WIDTH];
for(int i=0; i<SCREEN_HEIGHT; i++) for(int j=0; j<SCREEN_WIDTH; j++) screen[i][j] = ' ';
// 边界
for(int i=0; i<SCREEN_HEIGHT; i++) { screen[i][0] = '|'; screen[i][SCREEN_WIDTH-1] = '|'; }
// 地面
for(int j=1; j<SCREEN_WIDTH-1; j++) screen[GROUND_Y + 1][j] = '_';
// 障碍物
for (size_t i = 0; i < obstacles.size(); ++i) {
for (int dy = 0; dy < obstacles[i].h; ++dy) {
for (int dx = 0; dx < obstacles[i].w; ++dx) {
if (obstacles[i].y + dy < SCREEN_HEIGHT && obstacles[i].x + dx < SCREEN_WIDTH)
screen[obstacles[i].y + dy][obstacles[i].x + dx] = '#';
}
}
}
// 道具
for (size_t i = 0; i < items.size(); ++i) if (items[i].active) screen[items[i].y][items[i].x] = items[i].symbol;
// 子弹
for (size_t i = 0; i < bullets.size(); ++i) if (bullets[i].active) screen[bullets[i].y][bullets[i].x] = '*';
// 玩家
p2.drawToScreen(screen);
p1.drawToScreen(screen);
// 输出
for(int i=0; i<SCREEN_HEIGHT; i++) {
for(int j=0; j<SCREEN_WIDTH; j++) std::cout << screen[i][j];
std::cout << "\n";
}
// 提示
if (isPvEMode) printLine("P1: A/D(移) W(跳) S(铲) J(攻) K(技) | CPU: Auto");
else printLine("P1: A/D W S J K | P2: Arrows(移/跳/铲) 1(攻) 2(技)");
printLine("Items: s(Sword) p(Spear) g(Gun) i(Armor) h(HP) b(Bomb)");
if (gameOver) {
printLine("*** GAME OVER! " + winner + " WINS! ***");
printLine("Press any key to return to Main Menu...");
}
}
void startGame(bool pve) {
isPvEMode = pve;
resetGame();
// 技能选择
p1.setSkill(selectSkillMenu("PLAYER 1"));
if (pve) {
p2.setSkill((SkillType)(rand() % 3)); // CPU 随机技能
} else {
p2.setSkill(selectSkillMenu("PLAYER 2"));
}
clearScreen(); hideCursor();
spawnItem(); spawnItem();
while (true) {
handleInput(); updateGame(); spawnItem(); draw();
if (gameOver) { while (!_kbhit()) Sleep(50); _getch(); break; }
Sleep(30);
}
}
int main() {
srand(static_cast<unsigned int>(time(0)));
hideCursor();
while (true) {
int choice = showMainMenu();
if (choice == 1) startGame(false);
else if (choice == 2) startGame(true);
else if (choice == 3) { clearScreen(); std::cout << "Goodbye!\n"; break; }
}
MessageBoxA(NULL, "正版光荣,盗版可耻,改编跟作者说一声", "防伪标签",MB_ICONWARNING);
return 0;
}
英文版的,单词不懂自己搜,此处省略78字





这里空空如也




















有帮助,赞一个