Skip to content

Makintosh365/AutoBattler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

AutoBattler

Demo

AutoBattler — это консольная пошаговая RPG, где игрок создаёт героя, выбирает класс и наблюдает за автоматическими боями против монстров.
Ты не управляешь сражением напрямую — но именно твои решения при создании персонажа и выборе повышения определяют исход каждой битвы.

Игра написана на C++17, без сторонних игровых движков. Всё отображение выполнено средствами ASCII-графики и управлением курсора в терминале.

⚙️ Сборка и запуск

Требования:

  • CMake 3.20+
  • C++17 (MSVC, GCC, Clang)
  • Поддержка: Windows

Команды:

https://github.com/Makintosh365/AutoBattler.git
cd AutoBattler

mkdir build
cd build
cmake ..
cmake --build .
./autobattler.exe

🧩 Основные особенности

  • Полностью консольный интерфейс с динамической отрисовкой и эффектами вывода.
  • Пошаговые сражения: расчёт попаданий, промахов и урона с учётом характеристик.
  • Система классов: Воин, Разбойник, Варвар — каждый со своими пассивными способностями.
  • Повышение уровня и мультикласс (можно развивать разные ветви).
  • Таблица монстров со своими слабостями и типами урона.
  • Поддержка модульной архитектуры и простого расширения новых типов оружия/событий.

🎮 Демонстрация калибровки терминала процесса

Demo

Ожидание: после нажатия кнопки «ПРОВЕСТИ» на экране появляются 4 прямоугольника:

  1. внешняя рамка экрана,
  2. центральное поле mainBox,
  3. левый блок leftBox,
  4. правый блок rightBox.

Ничто не должно перекрывать рамки и текст, прямоугольники не пересекаются.

🧙‍♂️ Игрок

Класс Здоровье Оружие 1-й уровень 2-й уровень 3-й уровень
Разбойник +4 HP Кинжал +1 к урону при ловкости > цели +1 к ловкости Яд (+1/+2 урон на ход)
Воин +5 HP Меч Двойной урон в первый ход Щит (−3 урона при защите) +1 к силе
Варвар +6 HP Дубина Ярость (+2 урона первые 3 хода) Каменная кожа (−урон по выносливости) +1 к выносливости

👾 Противники

Противник HP Урон Сила Ловкость Выносливность Особенность Награда
Гоблин 5 2 1 1 1 Кинжал
Скелет 10 2 2 2 1 Уязвим к дробящему Дубина
Слайм 8 1 3 1 2 Иммунитет к рубящему Копьё
Призрак 6 3 1 3 1 Скрытая атака (как у разбойника) Меч
Голем 10 1 3 1 3 Каменная кожа (как у варвара) Топор
Дракон 20 4 3 3 3 Каждые 3 хода дыхание огнём (+3 урона) Легендарный меч

⚔️ Таблица оружия

Название Урон Тип урона
Меч 3 Рубящий
Дубина 3 Дробящий
Кинжал 2 Колющий
Топор 4 Рубящий
Копьё 3 Колющий
Легендарный меч 10 Рубящий

⚙️ Расширение и настройка игры

Архитектура игры позволяет легко добавлять новых монстров, классы, способности и типы оружия,
не изменяя основную логику.
Ниже — краткий гайд, как это делается.


🧟 Добавление нового монстра

Чтобы добавить нового противника, нужно внести его в перечисление и фабрику.

  • Чтобы добавить монстра нужно:
  • 1) Внести его в enum class
enum class MonsterType
{
    SLIME,      // слизень
    GOBLIN,     // гоблин
    SKELETON,   // скелет
    GHOST,      // призрак
    GOLEM,      // голем
    DRAGON      // дракон
    VAMPIRE     // <--- новый монстр
};
  • 2) Внести его в фабричный метод
Monster Monster::create(MonsterType type)
{
    switch (type)
    {
        case MonsterType::SKELETON:
            return Monster("Скелет", type,
                           10, 2, 2, 2, 1,
                           Weapon::create("Дубина"),
                           { std::make_shared<VulnerableToBluntAbility>() });

        // Новый монстр — вампир
        case MonsterType::VAMPIRE:
            return Monster("Вампир", type,
                           10,2, 2, 2, 2,
                           Weapon::create("Кинжал"),
                           { std::make_shared<LifeStealAbility>() });
  • **3) Добавить способность в AbilityImpl.h **
//------------------------------------------------------------------------------
// Вампир: Вампиризм 
//------------------------------------------------------------------------------
class LifeStealAbility : public Ability
{
public:
    std::string name() const override        { return "Вампиризм"; }
    std::string description() const override { return "Восстанавливает половину урона"; }

    int onAttack(const Entity* attacker,
                 const Monster* defender,
                 int baseDamage,
                 int turnCount) const override;
};
  • 4) Добавить способность в AbilityImpl.cpp
//------------------------------------------------------------------------------
// Вампир: Вампиризм 
//------------------------------------------------------------------------------

int LifeStealAbility::onAttackMonster(const Monster* attacker,
                                        const Entity* defender,
                                        int baseDamage,
                                        int turnCount) const
{
// Реализация способности 
}

🧙 Добавление нового персонажа

Чтобы добавить нового персонажа, нужно внести его в перечисление и фабрику.

  • Чтобы добавить персонажа нужно:
  • 1) Внести его в enum class
// source/Class.h
enum class ClassType
{
    WARRIOR,     // воин
    ROGUE,       // разбойник
    BARBARIAN,   // варвар
    MAGE         // <--- новый класс
};
  • 2) Внести его в фабричный метод в файле Class.cpp
CharacterClass CharacterClass::create(ClassType type)
{
    switch (type)
    {
        case ClassType::ROGUE:
            return CharacterClass(
                type, "Разбойник", 3,
                {
                    {}, // [0] пустой уровень (заглушка)
                    LevelBonus{4, 0, 0, 0, { std::make_shared<SneakAttackAbility>() }}, // lvl 1
                    LevelBonus{4, 0, 1, 0, {}},                                        // lvl 2
                    LevelBonus{4, 0, 0, 0, { std::make_shared<PoisonAbility>() }}      // lvl 3
                });

        case ClassType::MAGE:
            return CharacterClass(
                type, "Маг", 3,
                {
                    {}, // [0] пустой уровень (заглушка)
                    LevelBonus{3, 0, 0, 0, { std::make_shared<FireBallAbility>() }}, // lvl 1
                    LevelBonus{3, 0, 0, 0, {}},                                        // lvl 2
                    LevelBonus{3, 0, 0, 0, { std::make_shared<MagicShieldAbility>() }}      // lvl 3
                });
  • 3) Добавить способность в AbilityImpl.h
//------------------------------------------------------------------------------
// Маг: Огненный шар 
//------------------------------------------------------------------------------
class FireBallAbility : public Ability
{
public:
    std::string name() const override        { return "Огненный шар "; }
    std::string description() const override { return "+6 к атаке на чётном ходу"; }

    int onAttack(const Entity* attacker,
                 const Monster* defender,
                 int baseDamage,
                 int turnCount) const override;
};


//------------------------------------------------------------------------------
// Маг: Магический щит 
//------------------------------------------------------------------------------

class MagicShieldAbility : public Ability
{
public:
    int onDefense(const Entity* defender,
                  const Monster* attacker,
                  int incomingDamage,
                  int turnCount) const override;
};
  • 4) Добавить способность в AbilityImpl.cpp
//------------------------------------------------------------------------------
// Маг: Огненный шар 
//------------------------------------------------------------------------------

int FireBallAbility::onAttack(const Entity* attacker,
                            const Monster* defender,
                            int baseDamage,
                            int turnCount) const
{
// Реализация способности 
}

//------------------------------------------------------------------------------
// Маг: Магический щит 
//------------------------------------------------------------------------------

int MagicShieldAbility::onDefense(const Entity* defender,
                             const Monster* attacker,
                             int incomingDamage,
                             int turnCount) const
{
// Реализация способности 
}

🪓 Добавление нового оружия

Чтобы добавить новое оружие, нужно внести его в перечисление и фабрику.

  • Чтобы добавить оружие нужно:
  • 1) При необходимости добавить новый тип урона
// source/Weapon.h
enum class WeaponType
{
    SLASHING,   // рубящий
    BLUNT,      // дробящий
    PIERCING,   // колющий
    MAGICAL     // <--- новый тип урона
};
  • 1.2) Также нужно будет добавить новый тип урона в toString
//------------------------------------------------------------------------------
// возвращает строковое описание оружия.
//------------------------------------------------------------------------------
std::string Weapon::toString() const
{
    std::ostringstream oss;
    oss << name_ << " (урон: " << damage_ << ", тип: ";

    switch (type_)
    {
        case WeaponType::SLASHING:
            oss << "рубящее";
            break;
        case WeaponType::PIERCING:
            oss << "колющее";
            break;
        case WeaponType::BLUNT:
            oss << "дробящее";
            break;
        case WeaponType::MAGICAL:
            oss << "Магический"; // <--- новый тип урона
            break;
    }

    oss << ")";
    return oss.str();
}
  • 2) Внести в фабрику Weapon::create()
Weapon Weapon::create(const std::string& name)
{
    if (name == "Кинжал")
        return Weapon("Кинжал", 2, WeaponType::PIERCING);

    if (name == "Меч")
        return Weapon("Меч", 3, WeaponType::SLASHING);

    if (name == "Дубина")
        return Weapon("Дубина", 3, WeaponType::BLUNT);

    if (name == "Топор")
        return Weapon("Топор", 4, WeaponType::SLASHING);

    if (name == "Копьё")
        return Weapon("Копьё", 3, WeaponType::PIERCING);

    if (name == "Кулак")
        return Weapon("Кулак", 1, WeaponType::BLUNT);

    if (name == "Легендарный меч")
        return Weapon("Легендарный меч", 10, WeaponType::SLASHING);

    if (name == "Посох мага")
        return Weapon("Посох мага", 5, WeaponType::MAGICAL);

    throw std::invalid_argument("Неизвестное оружие: " + name);
}

🖼️ Настройка игрового поля (ConsoleBox)

  • 1) Размеры и позиция окон терминала задаются в main.cpp при создании ConsoleBox:
// main.cpp
ConsoleBox mainBox(90, 15, 5, 6);
ConsoleBox leftBox(40, 15, 20, 6);
ConsoleBox rightBox(40, 15, 20, 56);
  • 2) Формат конструктора:
ConsoleBox(width, height, top, left);

|Аргумент |Описание| |width |ширина окна (в символах)| |height |высота окна| |top |отступ сверху| |left |отступ слева|

Изменение начальных характеристик героя

  • 1) Начальные характеристики задаются при создании персонаж
//Player.cpp
    //--------------------------------------------------------------------------
    // Генерация случайных характеристик 1 - 3
    //--------------------------------------------------------------------------
    int strength  = Utils::randomInt(1, 3);
    int agility   = Utils::randomInt(1, 3);
    int endurance = Utils::randomInt(1, 3);

🏁 Конец

About

это консольная пошаговая RPG, где игрок создаёт героя, выбирает класс и наблюдает за автоматическими боями против монстров.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors