原神风格怪物战斗系统大纲
- 核心设计理念
基于原神的怪物掉落和战斗机制
结合角色成长和冒险等级系统
实现回合制战斗与暴击机制
- 核心枚举类型
MonsterLevel:怪物等级(LEVEL1=15, LEVEL2=35)
PlayerLevel:玩家冒险等阶(LEVEL1=20, LEVEL2=30)
- 核心类结构
3.1 掉落物品系统
DropItem(抽象基类)
属性:物品ID、名称、数量
方法:生成掉落物品(根据怪物等级)
具体掉落物品类
Slimelingye(史莱姆凝液)
HilichurlDropItem(丘丘人掉落物)
3.2 怪物系统
Monster(抽象基类)
属性:怪物ID、名称、等级、掉落物品列表
方法:生成掉落物品(根据玩家等级)
具体怪物类
HydroSlime(水史莱姆)
Hilichurl(丘丘人)
HilichurlAtk(丘丘人战斗状态)
扩展属性:生命值、攻击力
战斗状态计算方法
3.3 玩家系统
Paly(玩家基本信息)
属性:角色ID、名称、等级
Palyupdate(玩家状态更新)
根据等级计算生命值和攻击力
palyATk(玩家战斗状态)
扩展战斗属性和方法
3.4 战斗机制
CritRateMonsteratk(暴击率调节器)
实现暴击率计算
暴击后提升攻击力
cloplator(战斗模拟器)
回合制战斗实现
连击系统(1-5段攻击)
暴击伤害计算
反击机制
- 核心战斗流程
初始化
创建怪物和玩家对象
设置初始等级和状态
掉落物品生成
根据怪物等级生成掉落物品
显示掉落物品信息
战斗模拟
玩家攻击阶段
计算暴击率
执行连击(1-5段)
计算伤害
怪物反击阶段
怪物攻击玩家
更新玩家状态
状态更新
生命值更新
攻击力变化
战斗结果
胜利:怪物生命值≤0
失败:玩家生命值≤0(坠入深渊)
- 特色机制
连击系统
5段攻击,每段伤害倍率递增
1.0 → 1.2 → 2.4 → 2.6 → 2.8
暴击机制
基础暴击率5%
受攻击力影响
暴击后提升攻击力(10-20%)
成长系统
玩家和怪物属性随等级提升
冒险等级影响掉落物品
动态战斗
实时状态显示
交互式战斗过程
- 扩展性设计
可扩展的掉落系统
通过继承DropItem添加新物品
支持多种掉落规则
模块化战斗机制
暴击率计算器可独立使用
战斗模拟器可适配不同怪物
等级成长体系
清晰的等级划分
属性计算公式可调整
- 示例输出
怪物名称: 丘丘人, 等级: 15
掉落物品ID: 201, 名称: 丘丘人之牙
玩家生命值:2000, 玩家攻击力: 50, 丘丘人生命值: 2000, 丘丘人攻击力: 100
第 1 次攻击,暴击率: 15%
普通攻击! 造成伤害: 50
丘丘人剩余生命值: 1950
丘丘人反击!
造成伤害: 100
玩家剩余生命值: 1900
第 2 次攻击,暴击率: 65%
暴击成功! 造成伤害: 180
丘丘人剩余生命值: 1770
…
这个大纲概括了程序的整体结构和核心机制,突出了原神风格的游戏元素,包括怪物掉落、等级成长、战斗系统和特色机制。
#include<iostream>
#include<string>
#include<vector>
using namespace std;
// 简单怪物掉落副产物设计,收集
// 1.掉落物品有id,名称,类型 和数量 (按照玩家的冒险等阶提升掉落物品的等阶)随机掉落摩拉
// 击败魔物可掉落摩拉 和经验
//怪物等级
enum class MonsterLevel {
LEVEL1 = 15,
LEVEL2=35
};
//玩家等级
enum class PlayerLevel {
LEVEL1 = 20,
LEVEL2 = 30,
};
MonsterLevel MonsterLevels= MonsterLevel::LEVEL1;
PlayerLevel PlayerLevels = PlayerLevel::LEVEL1;
//首先 设计怪物掉落物品类
class DropItem {
public:
DropItem() {};
~DropItem() {};
//get set 方法
void setId(int id) { this->id = id; }
int getId() { return id; }
void setName(string name) { this->name = name; }
string getName() { return name; }
// 获取怪物等级生成怪物掉落物品
virtual void generateDropItems(MonsterLevel level) = 0;
protected:
int id; //物品id
string name; //物品名称
//按照世界等级划分物品类型
int num; //物品数量
};
//怪物类
class Monster {
public:
Monster() {};
~Monster() {};
//怪物id
int getId() { return id; }
//怪物名称
string getName() { return name; }
//怪物等级
MonsterLevel getLevel() { return level; }
//获取怪物掉落物品`
vector<DropItem*> getDropItems() { return dropItems; }
//按照世界等级划分物生成怪物掉落物品
virtual void generateDropItems(PlayerLevel plevel) = 0;
protected:
int id; //怪物id
string name; //怪物名称
MonsterLevel level; //怪物等级
vector<DropItem*> dropItems; //怪物掉落物品
};
//史莱姆凝液
class Slimelingye :public DropItem {
public:
Slimelingye() {
id = 101;
name = "史莱姆凝液";
num = 1;
}
// 获取怪物等级生成怪物掉落物品
virtual void generateDropItems(MonsterLevel level) {
if (level == MonsterLevel::LEVEL1) {
num = 1;
}
else if (level == MonsterLevel::LEVEL2) {
num = 2;
}
}
~Slimelingye() {}
};
// 水史莱姆
class HydroSlime :public Monster {
public:
HydroSlime() {
id = 1;
name = "水史莱姆";
level = MonsterLevel::LEVEL1;
}
~HydroSlime() {
for (auto item : dropItems) {
delete item;
}
dropItems.clear();
}
virtual void generateDropItems(PlayerLevel plevel) override {
dropItems.clear();
if (plevel == PlayerLevel::LEVEL1) {
DropItem* item1 = new Slimelingye();
dropItems.push_back(item1);
}
}
};
class HilichurlDropItem;
// 新增 HilichurlDropItem 类,解决 DropItem 抽象类不能实例化问题
class HilichurlDropItem :public DropItem {
public:
HilichurlDropItem(int id, const string& name) {
setId(id);
setName(name);
num = 1;
}
virtual void generateDropItems(MonsterLevel level) override {
// 可根据怪物等级调整数量
if (level == MonsterLevel::LEVEL1) num = 1;
else if (level == MonsterLevel::LEVEL2) num = 2;
}
~HilichurlDropItem() {}
};
//丘丘人
class Hilichurl :public Monster {
public:
Hilichurl() {
id = 2;
name = "丘丘人";
level = MonsterLevel::LEVEL1;
}
~Hilichurl() {
for (auto item : dropItems) {
delete item;
}
dropItems.clear();
}
virtual void generateDropItems(PlayerLevel plevel) override {
dropItems.clear();
if (plevel == PlayerLevel::LEVEL1) {
DropItem* item1 = new HilichurlDropItem(201, "丘丘人之牙");
dropItems.push_back(item1);
}
else if (plevel == PlayerLevel::LEVEL2) {
DropItem* item1 = new HilichurlDropItem(202, "丘丘人之爪");
dropItems.push_back(item1);
}
}
void setlevel(MonsterLevel level) {
this->level = level;
}
};
class cloMonsteratk;
//丘丘人攻击状态
class HilichurlAtk :public Hilichurl {
public:
HilichurlAtk(Hilichurl& h) {
int current_level = (int)h.getLevel();
this->id = h.getId();
this->name = h.getName();
this->level = h.getLevel();
//生命值 随着冒险等级提升
//假设 冒险等级1-20 生命值100*2*10
//假设 冒险等级21-40 生命值100*3*10
if (h.getLevel() == MonsterLevel::LEVEL1) {
hp = 50 * (current_level/2)*5 ; // 2000
}
else if (h.getLevel() == MonsterLevel::LEVEL2) {
hp = 100 * (current_level / 2) * 5; // 3000
}
//攻击力 随着冒险等级提升
if (h.getLevel() == MonsterLevel::LEVEL1) {
atkpwo = (5*hp)/ current_level ;
}
else if (h.getLevel() == MonsterLevel::LEVEL2) {
atkpwo = (10 * hp) / current_level;
}
}
~HilichurlAtk() {}
//攻击力
int getAtkPwo() { return atkpwo; }
void setAtkPwo(int atkpwo) { this->atkpwo = atkpwo; }
//生命值
int getHp() { return hp; }
void setHp(int hp) {
if (hp<0)
{
hp = 0;
}
this->hp = hp; }
private:
int hp; //生命值
int atkpwo; //攻击力
};
//丘丘人攻击状态 暴击率调节器
class CritRateMonsteratk{
public:
CritRateMonsteratk() {}
~CritRateMonsteratk() {}
// 返回暴击率值,并在暴击时提升攻击力
double operator()(HilichurlAtk& hilichurl) {
// 基础暴击率5%
const int baseCritRate = 5;
// 随机值影响暴击率 (0-15%)
const int randomBonus = rand() % 16;
// 总暴击率
double critRate = baseCritRate + randomBonus;
// 获取当前攻击力
int currentAtk = hilichurl.getAtkPwo();
// 检查是否暴击
int Ret = (rand() % 50);
// 暴击伤害倍率 (1.5倍)
const double critMultiplier = 1.5;
// 计算暴击伤害
int critDamage = static_cast<int>(currentAtk * critMultiplier);
cout << "原攻击力:" << currentAtk << endl;
// 暴击后提升攻击力 (10-20%)
int atkBoost = 10 + (rand() % 11); // 10%到20%
int newAtk = currentAtk + (currentAtk * atkBoost) / 100;
cout << "暴击! (" << critRate << "%) "
<< "造成伤害: " << critDamage
<< ", 攻击力提升至: " << newAtk
<< " (+" << atkBoost << "%)" << endl;
cout << "**************************************************************" << endl;
if (Ret < critRate) {
// 计算暴击伤害
int critDamage = static_cast<int>(currentAtk * critMultiplier);
// 暴击后提升攻击力 (10-20%)
int atkBoost = 10 + (rand() % 11); // 10%到20%
int newAtk = currentAtk + (currentAtk * atkBoost) / 100;
hilichurl.setAtkPwo(newAtk);
cout << "暴击! (" << critRate << "%) "
<< "造成伤害: " << critDamage
<< ", 攻击力提升至: " << newAtk
<< " (+" << atkBoost << "%)" << endl;
}
else {
// 普通攻击伤害
cout << "普通攻击! (" << critRate << "%) "
<< "造成伤害: " << currentAtk << endl;
}
return critRate; // 返回计算的暴击率值
}
double operator()(HilichurlAtk& hilichurl, int atk) {
// 计算暴击率
// 加点随机值
// 稳定暴击率 5% + (攻击力/10)%
// 百分比 计算
int satk = rand() % 100 +1; // 100
int baseCritRate = 5; // 基础暴击率5%]
//暴击伤害
int critDmg = 50; // 基础暴击伤害50%
int hilichurlAtk = hilichurl.getAtkPwo();
double critRate = baseCritRate + (hilichurlAtk/ 100.0) * satk; // atkpwo为攻击力
critRate = critRate/10.0> 100.0 ? (critRate / 10.0) : critRate/10.0; // 暴击率最高100%
int increaseAtk = (int)(hilichurlAtk * ((critDmg + critRate) / critDmg)); // 提高50%攻击
if (critRate<50.0) {
hilichurl.setAtkPwo(increaseAtk * (critRate * 0.01)); // 提高攻击力
}
else
{
hilichurl.setAtkPwo(increaseAtk * (critRate* 0.02)); // 提高攻击力
}
// if (critRate > 100.0) critRate = 100; // 暴击率最高100%
cout << "丘丘人攻击力: " << hilichurl.getAtkPwo() << ", 计算后的暴击率: " << critRate << "%" << endl;
return static_cast<double>(critRate); // 显式类型转换,避免丢失数据警告
}
};
//玩家类
class Paly {
public:
Paly() {}
Paly(int id, string name, int level=1) {
this->id = id;
this->name = name;
this->level = level;
}
~Paly() {}
//角色id
int Id() { return id; }
//角色名称
string Name() { return name; }
int getLevel() { return level; }
private:
int id; //角色id
string name; //角色名称
int level; //角色等级
};
//玩家更新等级状态
class Palyupdate {
public:
Palyupdate(Paly& p) {
int current_level = p.getLevel();
this->id = p.Id();
this->name = p.Name();
this->level = p.getLevel();
//生命值 随着冒险等级提升
//假设 冒险等级1-20 生命值100*2*10
//假设 冒险等级21-40 生命值100*3*10
if (p.getLevel() <= 20) {
hp = 100 * (current_level / 2) * 10; // 2000
}
else if (p.getLevel() > 20 && p.getLevel() <= 40) {
hp = 100 * (current_level / 2) * 10; // 3000
}
//攻击力 随着冒险等级提升
if (p.getLevel() <= 20) {
atkpwo = 10 * (current_level / 2);
}
else if (p.getLevel() > 20 && p.getLevel() <= 40) {
atkpwo = 20 * (current_level / 2);
}
}
protected:
int id; //角色id
string name; //角色名称
int level; //角色等级
int hp; //生命值
int atkpwo; //攻击力
};
class palyATk :public Palyupdate {
public:
palyATk(Paly& p) :Palyupdate(p) {}
int getAtkPwo() {
return atkpwo;
}
void setAtkPwo(int atkpwo) { this->atkpwo = atkpwo; }
int gethp() {
return hp;
}
void sethp(int hp) {
if (hp < 0) {
hp = 0;
}
this->hp = hp;
}
};
//模拟 玩家攻击怪物
class cloplator
{
public:
cloplator() {}
~cloplator() {}
// 检查是否战斗状态 攻击次数 角色的攻击力
void operator()(HilichurlAtk& hilichurl, palyATk& atk, int attackCount) {
// 假设角色攻击力 atkPower = 50
// attackCount 表示攻击次数
int atkPower = atk.getAtkPwo(); // 角色攻击力
int hilichurlHp = hilichurl.getHp();
int Hp = atk.gethp();
int critCount = 0;
int hilichurlAtk = hilichurl.getAtkPwo();
cout <<"玩家生命值:" <<Hp<< ", 玩家攻击力: " << atkPower << ", 丘丘人生命值: " << hilichurlHp << ", 丘丘人攻击力: " << hilichurlAtk << endl;
if (hilichurlHp > 0) {
if (atkPower > 0 && attackCount > 0) {
// 模拟多次攻击
for (int i = 0; i < attackCount; i++) {
if (hilichurlHp > 0) {
// 统计暴击次数
int randomValue = rand() % 100 + 1; // 生成随机值 1-100
int critRate = 5 + (atkPower * 10)/ randomValue; // 计算暴击率
if (critRate > 100) critRate = 100; // 限制暴击率最大为 100%
cout << "第 " << (i + 1) << " 次攻击,暴击率: " << critRate << "%" << endl << endl;
cout << "玩家生命值:" << Hp << ", 玩家攻击力: " << atkPower << ", 丘丘人生命值: " << hilichurlHp << ", 丘丘人攻击力: " << hilichurlAtk << endl;
if (critRate>50) {
cout << "暴击成功!" << endl;
critCount++;
}
else {
cout << "未触发暴击。" << endl;
}
int current_Atk = atkPower;
switch (i + 1) {
case 1:
current_Atk = atkPower*1.0;
break;
case 2:
current_Atk = atkPower * 1.2;
break;
case 3:
current_Atk = atkPower * 2.4;
break;
case 4:
current_Atk = atkPower * 2.6;
break;
case 5:
current_Atk = atkPower * 2.8;
break;
}
randomValue = rand() % 2;
double critRatenum =(critRate*0.1);
critRatenum /=10.0;
cout << "第 " << (i + 1) << " 段攻击,暴击率: " << critRate << "%" << endl;
cout << "是否触发暴击伤害(1 or 0) :" << randomValue << endl;
cout << "第 " << (i + 1) << " 次攻击,概率触发 ,暴击伤害: " << current_Atk * critRatenum << "%" << endl;
current_Atk += (critCount > 0) && randomValue ? current_Atk * critRatenum : 0;// 暴击伤害提升50%
if (hilichurlHp -= current_Atk) {
cout << "造成伤害: " << current_Atk << ", 丘丘人剩余生命值: " << (hilichurlHp > 0 ? hilichurlHp : 0) << endl;
// 丘丘人攻击
randomValue = rand() % 100;
double current_Atknum = (randomValue / 100.0);
int hilichurlAtk_prev = hilichurlAtk;
int hilichurlAtk_Next = hilichurlAtk;
if (randomValue<50){
hilichurlAtk_Next += ( hilichurlAtk * current_Atknum);
}else {
hilichurlAtk_Next+= (hilichurlAtk * current_Atknum);
}
if (hilichurlAtk_Next >hilichurlAtk_prev) {
hilichurlAtk += hilichurlAtk_Next * 0.01;
}
else
{
hilichurlAtk += hilichurlAtk_Next * 0.01;
}
Hp -= hilichurlAtk;
if (Hp<0){
cout << "角色已坠入深渊" << endl;
return;
}
else {
atk.sethp(Hp);
//atk.setAtkPwo(atkPower - (hilichurlAtk * 0.1)); // 反击降低10%攻击力
cout << "丘丘人反击,玩家剩余生命值: " << atk.gethp() << endl;
hilichurl.setHp(hilichurlHp);// 更新丘丘人生命值
// 丘丘人进攻
}
}
}
cout << "总攻击次数: " << attackCount-i << ",暴击次数: " << critCount << endl;
}
}
}
hilichurlHp = hilichurl.getHp();
}
private:
};
/*
模拟 玩家攻击怪物
class cloplator
{
public:
cloplator() {} // 默认构造函数
~cloplator() {} // 析构函数
// 战斗模拟器:模拟玩家与丘丘人的战斗
// 参数:
// hilichurl - 丘丘人对象
// atk - 玩家对象
// attackCount - 玩家攻击次数
void operator()(HilichurlAtk& hilichurl, palyATk& atk, int attackCount) {
// 获取玩家和丘丘人的初始状态
int atkPower = atk.getAtkPwo(); // 角色攻击力
int hilichurlHp = hilichurl.getHp(); // 丘丘人生命值
int Hp = atk.gethp(); // 玩家生命值
int critCount = 0; // 暴击次数计数器
int hilichurlAtk = hilichurl.getAtkPwo(); // 丘丘人攻击力
// 输出初始状态
cout <<"玩家生命值:" <<Hp<< ", 玩家攻击力: " << atkPower << ", 丘丘人生命值: " << hilichurlHp << ", 丘丘人攻击力: " << hilichurlAtk << endl;
// 检查丘丘人是否存活
if (hilichurlHp > 0) {
// 检查玩家攻击力和攻击次数是否有效
if (atkPower > 0 && attackCount > 0) {
// 模拟多次攻击
for (int i = 0; i < attackCount; i++) {
// 检查丘丘人是否存活
if (hilichurlHp > 0) {
// 计算暴击率
int randomValue = rand() % 100 + 1; // 生成随机值 1-100
int critRate = 5 + (atkPower * 10)/ randomValue; // 计算暴击率(基础5% + 攻击力影响)
// 限制暴击率最大为100%
if (critRate > 100) critRate = 100;
// 输出当前攻击信息
cout << "第 " << (i + 1) << " 次攻击,暴击率: " << critRate << "%" << endl << endl;
cout << "玩家生命值:" << Hp << ", 玩家攻击力: " << atkPower << ", 丘丘人生命值: " << hilichurlHp << ", 丘丘人攻击力: " << hilichurlAtk << endl;
// 检查是否暴击(暴击率大于50%即视为暴击)
if (critRate > 50) {
cout << "暴击成功!" << endl;
critCount++; // 增加暴击计数
}
else {
cout << "未触发暴击。" << endl;
}
// 根据攻击段数计算当前攻击力(连击系统)
int current_Atk = atkPower;
switch (i + 1) {
case 1:
current_Atk = atkPower * 1.0; // 第一段攻击
break;
case 2:
current_Atk = atkPower * 1.2; // 第二段攻击(120%)
break;
case 3:
current_Atk = atkPower * 2.4; // 第三段攻击(240%)
break;
case 4:
current_Atk = atkPower * 2.6; // 第四段攻击(260%)
break;
case 5:
current_Atk = atkPower * 2.8; // 第五段攻击(280%)
break;
}
// 随机决定是否触发暴击伤害
randomValue = rand() % 2; // 0或1
// 计算暴击伤害倍率
double critRatenum = (critRate * 0.1) * 0.50;
critRatenum /= 10.0;
// 输出暴击相关信息
cout << "第 " << (i + 1) << " 段攻击,暴击率: " << critRate << "%" << endl;
cout << "是否触发暴击伤害(1 or 0) :" << randomValue << endl;
cout << "第 " << (i + 1) << " 次攻击,概率触发 ,暴击伤害: " << current_Atk * critRatenum << "%" << endl;
// 如果暴击且随机值允许,增加暴击伤害
current_Atk += (critCount > 0) && randomValue ? current_Atk * critRatenum : 0;
// 丘丘人受到伤害
hilichurlHp -= current_Atk;
// 输出伤害结果
cout << "造成伤害: " << current_Atk << ", 丘丘人剩余生命值: " << (hilichurlHp > 0 ? hilichurlHp : 0) << endl;
// 丘丘人反击(如果还活着)
if (hilichurlHp > 0) {
// 生成随机值用于丘丘人攻击计算
randomValue = rand() % 100;
double current_Atknum = (randomValue / 100.0);
int hilichurlAtk_prev = hilichurlAtk;
int hilichurlAtk_Next = hilichurlAtk;
// 根据随机值决定丘丘人攻击方式
if (randomValue < 50) {
hilichurlAtk_Next += (hilichurlAtk * current_Atknum);
} else {
hilichurlAtk_Next += (hilichurlAtk * current_Atknum);
}
// 更新丘丘人攻击力(无论攻击方式如何都增加1%)
if (hilichurlAtk_Next > hilichurlAtk_prev) {
hilichurlAtk += hilichurlAtk_Next * 0.01;
} else {
hilichurlAtk += hilichurlAtk_Next * 0.01;
}
// 玩家受到丘丘人攻击
Hp -= hilichurlAtk;
// 检查玩家是否死亡
if (Hp < 0) {
cout << "角色已坠入深渊" << endl;
return; // 玩家死亡,结束战斗
} else {
// 更新玩家生命值
atk.sethp(Hp);
// 输出反击结果
cout << "丘丘人反击,玩家剩余生命值: " << atk.gethp() << endl;
// 更新丘丘人生命值
hilichurl.setHp(hilichurlHp);
}
}
}
// 输出当前攻击统计
cout << "总攻击次数: " << attackCount - i << ",暴击次数: " << critCount << endl;
}
}
}
// 更新丘丘人生命值(可能是多余的,因为已经在循环中更新)
hilichurlHp = hilichurl.getHp();
}
private:
// 无私有成员变量
};
*/
// 修复 Slimelingye::generateDropItems 方法参数错误
// 修正 Slimelingye 类定义和 generateDropItems 方法参数错误,去除重复定义
//class Slimelingye :public DropItem {
//public:
// Slimelingye() {
// id = 101;
// name = "史莱姆凝液";
// num = 1;
// }
// // 获取怪物等级生成怪物掉落物品
// virtual void generateDropItems(MonsterLevel level) override {
// if (level == MonsterLevel::LEVEL1) {
// num = 1;
// }
// else if (level == MonsterLevel::LEVEL2) {
// num = 2;
// }
// }
// ~Slimelingye() {}
//};
int main(void) {
//创建一个丘丘人
PlayerLevels = PlayerLevel::LEVEL1;
srand((unsigned)time(NULL));
Hilichurl h1;
h1.setlevel(MonsterLevels);
h1.generateDropItems(PlayerLevels);
cout << "怪物名称: " << h1.getName() << ", 等级: " << (int)h1.getLevel() << endl;
auto items = h1.getDropItems();
for (auto item : items) {
cout << "掉落物品ID: " << item->getId() << ", 名称: " << item->getName() << endl;
}
cout << endl;
Paly p1(1,"荧",40);
palyATk atk(p1);
//模拟丘丘人攻击状态
HilichurlAtk hAtk(h1);
//for (size_t i = 0; i < 10; i++)
//{
// CritRateMonsteratk clo;
// cout << "攻击" << i + 1 << " 暴击率 :" << clo(hAtk) << " "<<"\n";
//}
//模拟玩家攻击丘丘人
cloplator clop;
clop(hAtk, atk, 5);
cout << endl;
clop(hAtk, atk, 5);
cout << endl;
return 0;
}
4742

被折叠的 条评论
为什么被折叠?



