Nauka C++ w 2026

Wątek przeniesiony 2026-08-22 07:56 z Kariera przez pradoslaw.

LD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Czy warto uczyć się C++ w 2026 roku? Jest to główny język gier wideo na konsolach i PC. Nie działają dobrze w nim moduły i tylko GCC 16.2 je wspiera.
Wspiera tlyko w małych programach, gdzie jest 2-3 pliki ale gdy jest więcej to już się nie skompiluje. Moim zdaniem moduły w C++ są źle zaprojektowane.
Zwłaszcza że Rust jest mało popularnym i lubianym następcą i w jego skrzyniach pojawia się szkodliwe oprogramowanie.
https://safedep.io/arrayref-proc-macro1-rust-build-time-malware/

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5698
2
LibidoDominandi napisał(a):

Czy warto uczyć się C++ w 2026 roku?

Nie warto się uczyć w ogóle, ej aj wszystko zrobi lepiej

Jest to główny język gier wideo na konsolach i PC.

no to w takim razie warto jak chcesz robić gry wideo czy na pc

Nie działają dobrze w nim moduły i tylko GCC 16.2 je wspiera.

ale konkretnie 16.2 i żaden inny czy 16.2+? może nie jest to nikomu do niczego potrzebne. a może twórcy kompilatorów pracują za wolno i trzeba by ich z batem pogonić

Wspiera tlyko w małych programach, gdzie jest 2-3 pliki ale gdy jest więcej to już się nie skompiluje. Moim zdaniem moduły w C++ są źle zaprojektowane.

tu potrzebny jest ekspert jakiś od c++ niestety

Zwłaszcza że Rust

zwłaszcza sugeruje jakiś związek logiczny, tylko nie wiem czy do tych modułów w C++ czy do gier czy do czego

jest mało popularnym

to nie dobrze

i lubianym następcą

to dobrz jak jest lubianym, no chyba iż miało być "mało lubianym". ja tam lubię rust, ale to może dlatego że nigdy nic nie pisałem komercyjnego w c++

i w jego skrzyniach pojawia się szkodliwe oprogramowanie.

heh, no niestety wszędzie się pojawiają https://www.facebook.com/groups/egyptian.geeks/posts/8608815492491416/

tak więc nie do końca wiem czy to jest pytanie

  1. czy warto uczyć się C++ do pisania gier, pewnie tak
  2. warto się uczyć C++ do ogólnych programów, pewnie nie. C++ króluje w grach i embedded
  3. ukryty hejt na Rust bo ci się nudzi
LD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Mam taki prosty program z modułami w C++. I on się skompiluje pod GCC 16, ale jak jest większy program z modułami to już nie da rady go skompilować. Po prostu kompilatory nie wspierają tego.
Burrito.cpp

Kopiuj
module Burrito;
import std;

Burrito::Burrito()
{
    std::println("i am a orange");
}

Burrito.h

Kopiuj
#ifndef BURRITO_H
#define BURRITO_H

class BURRITO_H {
public:
    Burrito();

protected:
private:
};

#endif // BURRITO_H

main.cpp

Kopiuj
import std;
import Burrito;
 
int main()
{
    Burrito bo;
}

g++-16 -std=c++26 -fmodules --compile-std-module ../Burrito.ixx ../Burrito.cpp

Do pisania gier też w niedalekiej przyszłości C++ UE5 może być zastąpiony meta językiem VERSE.
https://www.reddit.com/r/gamedev/comments/1u8xp4t/all_things_about_ue6_announced_yesterday/
Niektórzy programiści twierdzą że zwykłe C++ jest o wiele łatwiejszy w obsłudze niż wersja UE5 C++.
Także w grach nikt nie wiąże przyszłości z językiem Rust, wolą dodawać do swoich silników zupełnie nowe autorskie języki programowania.

brokenelevator
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 66
1

Nie wiem do czego zmierzasz. Podany przykład działa na GCC 16.1.

burrito.cppm

Kopiuj
export module Burrito;

import std;

export class Burrito
{
public:
    Burrito();
};

burrito.cpp

Kopiuj
module Burrito;

Burrito::Burrito()
{
    std::println("i am an orange");
}

main.cpp

Kopiuj
import std;
import Burrito;

int main()
{
    Burrito bo;
}
Kopiuj
g++ -std=c++26 -fmodules --compile-std-module -c -x c++ burrito.cppm
g++ -std=c++26 -fmodules -c burrito.cpp
g++ -std=c++26 -fmodules -c main.cpp
g++ burrito.o main.o -o burrito
Kopiuj
$ ./burrito
i am an orange

g++ (GCC) 16.1.1 20260728

LD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

No zmierzam do tego tak jak napisałem, że gdy mam więcej plików moduły już nie działają.
Enemy.cpp

Kopiuj
module Enemy;

import std;

void Enemy::createEnemy(int type)
{
    if (type == 0) {
        name = "Zombie";
        maxHealth = 50;
        damage = 5;
    }
    else if (type == 1) {
        name = "Szkieletor";
        maxHealth = 35;
        damage = 8;
    }
    else if (type == 2) {
        name = "Goblinek";
        maxHealth = 30;
        damage = 10;
    }
    else {
        name = "Zombiak";
        maxHealth = 50;
        damage = 5;
    }

    currentHealth = maxHealth;
}

void Enemy::SetLevel(int enemyLevel)
{
    level = enemyLevel;

    maxHealth += (level - 1) * 10;
    damage += (level - 1) * 2;

    currentHealth = maxHealth;
}

Enemy.ixx

Kopiuj
export module Enemy;

import std;

export class Enemy {
public:
    std::string name;
    int maxHealth = 0;
    int currentHealth = 0;
    int level = 1;
    int damage = 0;

    void createEnemy(int type);
    void SetLevel(int enemyLevel);
};

Game.cpp

Kopiuj
module Game;

import std;
import Enemy;
import Player;
import Print;

enum class GameState {
    MainMenu,
    CharacterSelect,
    Playing,
    Exit
};

static int GetEnemyCount()
{
    int roll = std::rand() % 100;
    if (roll < 50) return 1;
    else if (roll < 75) return 2;
    else if (roll < 90) return 3;
    else return 4;
}

static int GetEnemyType() { return std::rand() % 4; }
static int GetEnemyLevel() { return 1 + std::rand() % 3; }

void RunGame()
{
    Player player;

    std::srand(std::time(0));

    bool running = true;
    GameState state = GameState::MainMenu;

    while (running)
    {
        if (state == GameState::MainMenu)
        {
            Print::WriteColor("====UpiornePotyczki====\n\n", Color::Red);
            Print::Write("1. Nowa Gra\n");
            Print::Write("2. Wyjście\n");

            int choice;
            std::cin >> choice;

            state = (choice == 1) ? GameState::CharacterSelect : GameState::Exit;
            Print::Clear();
        }

        else if (state == GameState::CharacterSelect)
        {
            Print::WriteColor("Wybierz klasę:\n\n", Color::Yellow);
            Print::Write("1. Wojownik\n2. Łotrzyk\n3. Mag\n");

            int choice;
            std::cin >> choice;

            player.SetClass(choice);
            player.DisplayPickedCharacter();

            int tmp;
            std::cin >> tmp;

            Print::Clear();
            state = GameState::Playing;
        }

        else if (state == GameState::Playing)
        {
            std::vector<Enemy> enemies;

            int enemyCount = GetEnemyCount();

            for (int i = 0; i < enemyCount; i++)
            {
                Enemy e;
                e.createEnemy(GetEnemyType());
                e.SetLevel(GetEnemyLevel());
                enemies.push_back(e);
            }

            bool inCombat = true;

            while (inCombat)
            {
                Print::Clear();
                Print::WriteColor("Pojawiają się przeciwnicy!\n\n", Color::Red);

                for (int i = 0; i < enemies.size(); i++)
                {
                    Print::Write("Przeciwnik " + std::to_string(i + 1) + ": ");
                    Print::WriteColor(enemies[i].name, Color::Yellow);
                    Print::Write("\n");
                }

                int choice;
                std::cin >> choice;

                if (choice == 2)
                    inCombat = false;
            }

            state = GameState::Exit;
        }
        else
        {
            running = false;
        }
    }

    Print::WriteColor("\nKoniec gry\n", Color::Magenta);
}

Game.ixx

Kopiuj
export module Game;

import std;
import Enemy;
import Player;
import Print;

export void RunGame();

Player.ixx

Kopiuj
export module Player;

import std;
import Print;

export class Player {
public:
    std::string name;
    std::string playerClass;

    int strength = 0;
    int intelligence = 0;
    int vitality = 0;

    int maxHealth = 0;
    int currentHealth = 0;

    int maxMana = 0;
    int currentMana = 0;

    int damage = 0;

    void SetClass(int choice);
    void CalculateStats();
    void DisplayPickedCharacter();
};

Print.cpp

Kopiuj
module Print;

import std;

void Print::Write(const std::string& text)
{
    std::print("{}", text);
}

void Print::SetColor(Color color)
{
    switch (color) {
    case Color::Red: std::print("\033[31m"); break;
    case Color::Green: std::print("\033[32m"); break;
    case Color::Yellow: std::print("\033[33m"); break;
    case Color::Cyan: std::print("\033[36m"); break;
    case Color::Blue: std::print("\033[34m"); break;
    case Color::Magenta: std::print("\033[35m"); break;
    case Color::White: std::print("\033[37m"); break;
    case Color::Black: std::print("\033[30m"); break;
    default: std::print("\033[0m"); break;
    }
}

void Print::WriteColor(const std::string& text, Color color)
{
    SetColor(color);
    std::print("{}", text);
    SetColor(Color::Default);
}

void Print::Clear()
{
    std::system("clear");
}

Print.ixx

Kopiuj
export module Print;

import std;

export enum class Color {
    Default, Red, Green, Yellow, Cyan, Blue, Magenta, White, Black
};

export class Print {
public:
    static void Write(const std::string& text);
    static void SetColor(Color color);
    static void WriteColor(const std::string& text, Color color);
    static void Clear();
};

main.cpp

Kopiuj
import Game;

int main()
{
    RunGame();
}

Makefile

Kopiuj
CXX = g++-16
CXXFLAGS = -std=c++26 -fmodules -O2 -Wall

TARGET = game

# moduły
MODS = Print.ixx Enemy.ixx Player.ixx Game.ixx
MOD_OBJS = Print.o Enemy.o Player.o Game.o

# main
MAIN = main.o

all: $(TARGET)

# --- moduły ---
Print.o: Print.ixx
	$(CXX) $(CXXFLAGS) -c Print.ixx -o Print.o

Enemy.o: Enemy.ixx
	$(CXX) $(CXXFLAGS) -c Enemy.ixx -o Enemy.o

Player.o: Player.ixx
	$(CXX) $(CXXFLAGS) -c Player.ixx -o Player.o

Game.o: Game.ixx
	$(CXX) $(CXXFLAGS) -c Game.ixx -o Game.o

# --- main ---
main.o: main.cpp
	$(CXX) $(CXXFLAGS) -c main.cpp -o main.o

# --- linkowanie ---
$(TARGET): $(MOD_OBJS) $(MAIN)
	$(CXX) $(CXXFLAGS) $^ -o $(TARGET)

run: $(TARGET)
	./$(TARGET)

clean:
	rm -f *.o $(TARGET)

CMakeLists.txt

Kopiuj
cmake_minimum_required(VERSION 3.28)
project(UpiornePotyczki LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options(-fmodules)
set(CMAKE_CXX_SCAN_FOR_MODULES OFF)

add_executable(game
    main.cpp
)

target_sources(game PRIVATE
    Game.ixx
    Player.ixx
    Enemy.ixx
    Print.ixx
)
"cpp": "clear && cd $dir && mkdir -p bin && cd bin && g++-16 -std=c++26 -fmodules --compile-std-module ../Print.ixx ../Enemy.ixx ../Player.ixx ../Game.ixx ../Print.cpp ../Enemy.cpp ../Game.cpp ../main.cpp -o game && ./game"

Mam błąd przy poleceniu make

Bash (Shell)
Opcje:
rm -rf build
mkdir build
cd build
cmake -DCMAKE_CXX_COMPILER=g++-16 -DCMAKE_CXX_STANDARD=26 ..
make

Kopiuj
make
[ 16%] Building CXX object CMakeFiles/game.dir/main.cpp.o
In module imported at /home/user/UpiornePotyczki/main.cpp:1:1:
Game: error: failed to read compiled module: Nie ma takiego pliku ani katalogu
Game: note: compiled module file is ‘gcm.cache/Game.gcm’
Game: note: imports must be built before being imported
Game: fatal error: returning to the gate for a mechanical issue
compilation terminated.
make[2]: *** [CMakeFiles/game.dir/build.make:79: CMakeFiles/game.dir/main.cpp.o] Błąd 1
make[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/game.dir/all] Błąd 2
make: *** [Makefile:91: all] Błąd 2
GCC musi wygenerować .gcm zanim skompiluje main.cpp ale Game.ixx NIE został jeszcze zbudowany jako .gcm
brokenelevator
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 66
1

Ten kod też się kompiluje i uruchamia. Jest jeden problem. Funkcje klasy Player nie są zdefiniowane. 'Poprawiony' (tj. puste definicje) nie wydaję się działać poprawnie. W tej chwili nie mam ochoty na szukanie przyczyny.

Nie chciało mi się też sprawdzać Makefile i CMakeLists więc użyłem mojej ulubionej metody.

Kopiuj
g++ -std=c++26 -fmodules --compile-std-module -c -x c++ enemy.cppm
g++ -std=c++26 -fmodules -c -x c++ print.cppm
g++ -std=c++26 -fmodules -c -x c++ player.cppm
g++ -std=c++26 -fmodules -c -x c++ game.cppm
g++ -std=c++26 -fmodules -c print.cpp
g++ -std=c++26 -fmodules -c enemy.cpp
g++ -std=c++26 -fmodules -c game.cpp
g++ -std=c++26 -fmodules -c main.cpp
g++ print.o player.o enemy.o game.o main.o -o itworks
LD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Teraz działa! Wtedy miałem GCC 16.1 a teraz mam GCC 16.2. usunałem pliki Game, poprawiłem plik Makefile i dodałem Linkowanie.
Enemy.cpp

Kopiuj
module Enemy;

import std;

void Enemy::createEnemy(int type)
{
    if (type == 0) {
        name = "Zombie";
        maxHealth = 50;
        damage = 5;
    }
    else if (type == 1) {
        name = "Szkieletor";
        maxHealth = 35;
        damage = 8;
    }
    else if (type == 2) {
        name = "Goblinek";
        maxHealth = 30;
        damage = 10;
    }
    else {
        name = "Zombiak";
        maxHealth = 50;
        damage = 5;
    }

    currentHealth = maxHealth;
}

void Enemy::SetLevel(int enemyLevel)
{
    level = enemyLevel;

    maxHealth += (level - 1) * 10;
    damage += (level - 1) * 2;

    currentHealth = maxHealth;
}

Enemy.ixx

Kopiuj
export module Enemy;

import std;

export class Enemy {
public:
    std::string name;
    int maxHealth = 0;
    int currentHealth = 0;
    int level = 1;
    int damage = 0;

    void createEnemy(int type);
    void SetLevel(int enemyLevel);
};

Player.cpp

Kopiuj
module Player;

import std;
import Print;

void Player::SetClass(int choice)
{
     name = "Bohater";

    if (choice == 1) {
        playerClass = "Wojownik";
        strength = 10;
        intelligence = 2;
        vitality = 8;
    }

    else if (choice == 2) {
        playerClass = "Łotrzyk";
        strength = 6;
        intelligence = 5;
        vitality = 6;
    }

    else if (choice == 3) {
        playerClass = "Mag";
        strength = 2;
        intelligence = 10;
        vitality = 5;
    }

    CalculateStats();
}

void Player::CalculateStats()
{
   int baseHealth = 50;
    int baseMana = 30;

    // Obliczanie zdrowia
    maxHealth = baseHealth + (vitality * 10);
    currentHealth = maxHealth;

    // Obliczanie many
    maxMana = baseMana + (intelligence * 10);
    currentMana = maxMana;

    // Obliczanie obrażeń w zależności od klasy
    if (playerClass == "Wojownik") {
        damage = strength * 2;
    }

    else if (playerClass == "Łotrzyk") {
        damage = strength * 2 + 2;
    }

    else if (playerClass == "Mag") {
        damage = intelligence * 2;
    }

    else {
        damage = 5;
    }
}

void Player::DisplayPickedCharacter()
{
   Print::Clear();

    Print::Write("Wybrałeś ");
    Print::WriteColor(playerClass, Color::Cyan);
    Print::Write("!\n\n");

    Print::Write("Siła: ");
    Print::Write(std::to_string(strength) + "\n");

    Print::Write("Inteligencja: ");
    Print::Write(std::to_string(intelligence) + "\n");

    Print::Write("Witalność: ");
    Print::Write(std::to_string(vitality) + "\n");

    Print::Write("Zdrowie: ");
    Print::WriteColor(std::to_string(currentHealth), Color::Green);
    Print::Write("\n");

    Print::Write("Mana: ");
    Print::WriteColor(std::to_string(currentMana), Color::Cyan);
    Print::Write("\n");

    Print::Write("\nNaciśnij 1, aby kontynuować: ");
}

Player.ixx

Kopiuj
export module Player;

import std;
import Print;

export class Player {
public:
    std::string name;
    std::string playerClass;

    int strength = 0;
    int intelligence = 0;
    int vitality = 0;

    int maxHealth = 0;
    int currentHealth = 0;

    int maxMana = 0;
    int currentMana = 0;

    int damage = 0;

    void SetClass(int choice);
    void CalculateStats();
    void DisplayPickedCharacter();
};

Print.cpp

Kopiuj
module Print;

import std;

void Print::Write(const std::string& text)
{
    std::print("{}", text);
}

void Print::SetColor(Color color)
{
    switch (color) {
    case Color::Red: std::print("\033[31m"); break;
    case Color::Green: std::print("\033[32m"); break;
    case Color::Yellow: std::print("\033[33m"); break;
    case Color::Cyan: std::print("\033[36m"); break;
    case Color::Blue: std::print("\033[34m"); break;
    case Color::Magenta: std::print("\033[35m"); break;
    case Color::White: std::print("\033[37m"); break;
    case Color::Black: std::print("\033[30m"); break;
    default: std::print("\033[0m"); break;
    }
}

void Print::WriteColor(const std::string& text, Color color)
{
    SetColor(color);
    std::print("{}", text);
    SetColor(Color::Default);
}

void Print::Clear()
{
    std::system("clear");
}

Print.ixx

Kopiuj
export module Print;

import std;

export enum class Color {
    Default, Red, Green, Yellow, Cyan, Blue, Magenta, White, Black
};

export class Print {
public:
    static void Write(const std::string& text);
    static void SetColor(Color color);
    static void WriteColor(const std::string& text, Color color);
    static void Clear();
};

main.cpp

Kopiuj
import std;
import Enemy;
import Player;
import Print;

// Stany gry
enum class GameState {
    MainMenu,
    CharacterSelect,
    Playing,
    Exit
};

// Losuje liczbę przeciwników
int GetEnemyCount()
{
    int roll = std::rand() % 100;

    if (roll < 50) {
        return 1;
    }

    else if (roll < 75) {
        return 2;
    }

    else if (roll < 90) {
        return 3;
    }

    else {
        return 4;
    }
}

// Losuje typ przeciwnika
int GetEnemyType()
{
    return std::rand() % 4;
}

// Losuje poziom przeciwnika
int GetEnemyLevel()
{
    return 1 + std::rand() % 3;
}

Player player;

int main()
{
    std::srand(std::time(0));

    bool running = true;
    GameState state = GameState::MainMenu;

    while (running) {
        if (state == GameState::MainMenu) {
            Print::WriteColor("====UpiornePotyczki====\n\n", Color::Red);
            Print::Write("1. Nowa Gra\n");
            Print::Write("2. Wyjście\n");
            Print::WriteColor("\nWybierz opcję: ", Color::Yellow);

            int choice;
            std::cin >> choice;

            if (choice == 1) {
                state = GameState::CharacterSelect;
            }

            if (choice == 2) {
                state = GameState::Exit;
            }

            Print::Clear();
        }

        else if (state == GameState::CharacterSelect) {
            Print::WriteColor("Wybierz swoją klasę:\n\n", Color::Yellow);
            Print::Write("1. Wojownik\n");
            Print::Write("2. Łotrzyk\n");
            Print::Write("3. Mag\n");
            Print::WriteColor("\nWybierz opcję: ", Color::Yellow);
            int choice;
            std::cin >> choice;

            player.SetClass(choice);

            player.DisplayPickedCharacter();

            int continueChoice;
            std::cin >> continueChoice;

            Print::Clear();
            state = GameState::Playing;
        }

        else if (state == GameState::Playing) {
            std::vector<Enemy> enemies;

            int enemyCount = GetEnemyCount();

            // Tworzenie przeciwników
            for (int i = 0; i < enemyCount; i++) {
                Enemy enemy;

                int type = GetEnemyType();
                int level = GetEnemyLevel();

                enemy.createEnemy(type);
                enemy.SetLevel(level);

                enemies.push_back(enemy);
            }

            bool inCombat = true;

            // Pętla walki
            while (inCombat) {
                Print::Clear();
                Print::WriteColor("Pojawiają się przeciwnicy!\n\n", Color::Red);

                for (int i = 0; i < enemies.size(); i++) {
                    Print::Write("Przeciwnik " + std::to_string(i + 1) + ": ");
                    Print::WriteColor(enemies[i].name, Color::Yellow);
                    Print::Write(" Poziom. " + std::to_string(enemies[i].level));
                    Print::Write(" - Zdrowie: " + std::to_string(enemies[i].currentHealth) + "\n");
                }

                Print::Write("\nTwoje zdrowie: ");
                Print::WriteColor(std::to_string(player.currentHealth), Color::Green);
                Print::Write("\n");

                Print::Write("\n1. Atak\n");
                Print::Write("2. Ucieczka\n");
                Print::WriteColor("\nWybierz opcję: ", Color::Yellow);

                int choice;
                std::cin >> choice;

                if (choice == 1) {
                    Print::WriteColor("\nWybierz przeciwnika do ataku: ", Color::Yellow);

                    int targetChoice;
                    std::cin >> targetChoice;

                    int targetIndex = targetChoice - 1;

                    if (targetIndex >= 0 && targetIndex < enemies.size()) {
                        enemies[targetIndex].currentHealth -= player.damage;

                        Print::Write("\nUderzasz ");
                        Print::WriteColor(enemies[targetIndex].name, Color::Yellow);
                        Print::Write(" za " + std::to_string(player.damage) + " obrażeń!\n");

                        if (enemies[targetIndex].currentHealth <= 0) {
                            Print::WriteColor("\n" + enemies[targetIndex].name + " został pokonany!\n", Color::Green);
                            enemies.erase(enemies.begin() + targetIndex);
                        }

                        if (enemies.empty()) {
                            Print::WriteColor("\nWygrałeś walkę!\n", Color::Green);
                            inCombat = false;
                        }

                        else {
                            Print::Write("\nPrzeciwnicy atakują!\n");

                            for (int i = 0; i < enemies.size(); i++) {
                                player.currentHealth -= enemies[i].damage;

                                if (player.currentHealth < 0) {
                                    player.currentHealth = 0;
                                    inCombat = false;
                                    state = GameState::Exit;
                                    Print::Write("\nZostałeś pokonany\n");
                                    break;
                                }

                                Print::WriteColor(enemies[i].name, Color::Red);
                                Print::Write(" uderza cię za " + std::to_string(enemies[i].damage) + " obrażeń!\n");

                                if (player.currentHealth <= 0) {
                                    Print::WriteColor("\nZostałeś pokonany..\n", Color::Red);
                                    inCombat = false;
                                    state = GameState::Exit;
                                    break;
                                }
                            }
                        }
                    }

                    else {
                        Print::Write("\nNieprawidłowy cel!\n");
                    }
                }

                else if (choice == 2) {
                    Print::WriteColor("\nUciekasz jak tchórz!\n", Color::Yellow);
                    inCombat = false;
                }

                else {
                    Print::Write("\nNieprawidłowy wybór!\n");
                }
            }

            state = GameState::Exit;
        }

        else if (state == GameState::Exit) {
            running = false;
        }
    }

    Print::WriteColor("\n************************************\n", Color::Magenta);
    Print::WriteColor("* Dzięki za grę w UpiornePotyczki! *\n", Color::Magenta);
    Print::WriteColor("************************************\n", Color::Magenta);
}

Makefile

Kopiuj
CXX = g++-16
CXXFLAGS = -std=c++26 -fmodules

TARGET = game

.PHONY: all clean run std-module

all: $(TARGET)

# =========================
# Standard library
# =========================

std-module:
	$(CXX) $(CXXFLAGS) --compile-std-module -c

# =========================
# Print
# =========================

Print.ixx.gcm: Print.ixx std-module
	$(CXX) $(CXXFLAGS) -c Print.ixx

Print.o: Print.cpp Print.ixx.gcm
	$(CXX) $(CXXFLAGS) -c Print.cpp -o Print.o

# =========================
# Enemy
# =========================

Enemy.ixx.gcm: Enemy.ixx std-module
	$(CXX) $(CXXFLAGS) -c Enemy.ixx

Enemy.o: Enemy.cpp Enemy.ixx.gcm
	$(CXX) $(CXXFLAGS) -c Enemy.cpp -o Enemy.o

# =========================
# Player
# =========================

Player.ixx.gcm: Player.ixx Print.ixx.gcm std-module
	$(CXX) $(CXXFLAGS) -c Player.ixx

Player.o: Player.cpp Player.ixx.gcm
	$(CXX) $(CXXFLAGS) -c Player.cpp -o Player.o


# =========================
# main
# =========================

main.o: main.cpp 
	$(CXX) $(CXXFLAGS) -c main.cpp -o main.o

# =========================
# Linkowanie
# =========================

$(TARGET): Print.o Enemy.o Player.o main.o
	$(CXX) $^ -o $@

# =========================
# Uruchamianie
# =========================

run: $(TARGET)
	./$(TARGET)

# =========================
# Czyszczenie
# =========================

clean:
	rm -rf *.o $(TARGET) gcm.cache
	rm -f *.ixx.gcm

README.md

Kopiuj
# Projekt C++ – Makefile i moduły C++26

Projekt jest przykładową aplikacją C++ wykorzystującą **moduły C++20/C++26 (`.ixx`)** oraz moduł standardowej biblioteki `std`. Do kompilacji wykorzystywany jest **GCC 16.2**.

## Wymagania

Do poprawnej kompilacji projektu wymagane są:

* **GCC 16.2** (`g++-16`)
* Obsługa standardu **C++26**
* Obsługa modułów C++
* Program **GNU Make**
* System **Linux**

Sprawdzenie wersji kompilatora:

```bash
g++-16 --version

Przykładowy wynik:

Kopiuj
g++-16 (GCC) 16.2.0

Kompilacja

Aby skompilować projekt, wykonaj:

Kopiuj
make

Makefile wykorzystuje:

Kopiuj
CXX = g++-16
CXXFLAGS = -std=c++26 -fmodules

Podczas pierwszej kompilacji generowany jest również skompilowany moduł standardowej biblioteki C++.

GCC przechowuje skompilowane moduły w katalogu:

Kopiuj
gcm.cache/

Po poprawnej kompilacji zostanie utworzony plik wykonywalny:

Kopiuj
game

Uruchomienie programu

Aby skompilować projekt i uruchomić program:

Kopiuj
make run

Można również uruchomić wcześniej skompilowany program bezpośrednio:

Kopiuj
./game

Czyszczenie projektu

Aby usunąć pliki wygenerowane podczas kompilacji:

Kopiuj
make clean

Polecenie usuwa:

  • pliki obiektowe *.o,
  • program wykonywalny game,
  • katalog gcm.cache,
  • wygenerowane pliki *.ixx.gcm.

Struktura projektu

Kopiuj
.
├── CMakeLists.txt
├── Makefile
├── Enemy.cpp
├── Enemy.ixx
├── Player.cpp
├── Player.ixx
├── Print.cpp
├── Print.ixx
└── main.cpp

Moduły projektu

Plik Opis
Print.ixx Interfejs modułu odpowiedzialnego za funkcje związane z wyświetlaniem informacji.
Print.cpp Implementacja modułu Print.
Enemy.ixx Interfejs modułu reprezentującego przeciwników.
Enemy.cpp Implementacja modułu Enemy.
Player.ixx Interfejs modułu gracza.
Player.cpp Implementacja modułu Player.
main.cpp Główny punkt wejścia programu.
Makefile Automatyzuje proces kompilacji, linkowania, uruchamiania i czyszczenia projektu.
CMakeLists.txt Konfiguracja projektu dla systemu CMake.

Moduły C++

Projekt wykorzystuje moduły zamiast tradycyjnych plików nagłówkowych .h/.hpp.

Przykładowy interfejs modułu znajduje się w pliku:

Kopiuj
Player.ixx

Natomiast jego implementacja w:

Kopiuj
Player.cpp

Moduły są kompilowane przez GCC przy użyciu:

Kopiuj
-fmodules

oraz standardu:

Kopiuj
-std=c++26

Moduł standardowej biblioteki

Makefile zawiera osobny cel:

Kopiuj
std-module:
	$(CXX) $(CXXFLAGS) --compile-std-module -c

Odpowiada on za przygotowanie modułu standardowej biblioteki, który może być następnie importowany w kodzie za pomocą:

Kopiuj
import std;

Dzięki temu projekt korzysta z mechanizmu modułów dostępnego w GCC 16 zamiast klasycznych:

Kopiuj
#include <iostream>
#include <vector>
#include <string>

Makefile

Najważniejsze ustawienia:

Kopiuj
CXX = g++-16
CXXFLAGS = -std=c++26 -fmodules

TARGET = game

Dostępne polecenia

Polecenie Opis
make Kompiluje cały projekt i tworzy game.
make run Kompiluje projekt, jeśli jest to konieczne, i uruchamia game.
make clean Usuwa pliki wynikowe oraz skompilowane moduły.
make std-module Przygotowuje skompilowany moduł standardowej biblioteki.

Kolejność kompilacji

Makefile zapewnia odpowiednią kolejność budowania modułów.

Najpierw przygotowywany jest moduł standardowej biblioteki:

Kopiuj
std-module

Następnie kompilowane są moduły:

Kopiuj
Print.ixx
Enemy.ixx
Player.ixx

Po nich kompilowane są odpowiadające im pliki implementacyjne:

Kopiuj
Print.cpp
Enemy.cpp
Player.cpp

Na końcu kompilowany jest:

Kopiuj
main.cpp

Wszystkie pliki obiektowe są następnie łączone w jeden program:

Kopiuj
game

Schemat budowania:

Kopiuj
std
 │
 ├── Print.ixx ──> Print.o
 │
 ├── Enemy.ixx ──> Enemy.o
 │
 └── Player.ixx ──> Player.o
                         │
main.cpp ─────────> main.o
                         │
                         ▼
                    ┌─────────┐
                    │  game   │
                    └─────────┘

Uwagi dotyczące GCC 16.2

Projekt jest skonfigurowany konkretnie pod:

Kopiuj
GCC 16.2
g++-16

Dlatego Makefile używa:

Kopiuj
CXX = g++-16

Jeżeli system posiada inną wersję GCC lub kompilator jest dostępny pod inną nazwą, należy odpowiednio zmienić wartość CXX.

Przykładowo:

Kopiuj
CXX = g++

lub:

Kopiuj
CXX = g++-16

Dla tego projektu zalecane jest jednak używanie GCC 16.2, ponieważ obsługa modułów i import std; jest zależna od wersji kompilatora.

Szybki start

Po pobraniu projektu wystarczy wykonać:

Kopiuj
make

a następnie:

Kopiuj
./game

lub bezpośrednio:

Kopiuj
make run

Aby wyczyścić wszystkie pliki wygenerowane podczas kompilacji:

Kopiuj
make clean
Kopiuj
LD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Przepisałem też wersję na Rust trochę rozbudowaną z paskami postępu, aby sprawdzić czy kodu będzie duzo mniej niż w C++.
enemy.rs

Kopiuj
pub struct Enemy {
    pub name: String,
    pub max_health: u32,
    pub current_health: u32,
    pub level: u8,
    pub damage: u32,
}

impl Enemy {
    pub fn new() -> Self {
        Self {
            name: String::new(),
            max_health: 0,
            current_health: 0,
            level: 1,
            damage: 0,
        }
    }

    pub fn create_enemy(&mut self, enemy_type: u8) {
        match enemy_type {
            0 => {
                self.name = "Zombie".to_string();
                self.max_health = 30;
                self.damage = 5;
            }
            1 => {
                self.name = "Szkieletor".to_string();
                self.max_health = 25;
                self.damage = 6;
            }
            2 => {
                self.name = "Goblin".to_string();
                self.max_health = 20;
                self.damage = 4;
            }
            _ => {
                self.name = "Zombie".to_string();
                self.max_health = 30;
                self.damage = 5;
            }
        }
        self.current_health = self.max_health;
    }

    pub fn set_level(&mut self, level: u8) {
        self.level = level;
        self.max_health += (level as u32 - 1) * 10;
        self.current_health = self.max_health;
        self.damage += (level as u32 - 1) * 2;
    }
}

player.rs

Kopiuj
use crate::print::{Color, Print};

pub struct Player {
    pub name: String,
    pub player_class: String,
    pub strength: u32,
    pub intelligence: u32,
    pub vitality: u32,
    pub max_health: u32,
    pub current_health: u32,
    pub damage: u32,
}

impl Player {
    pub fn new() -> Self {
        Self {
            name: String::new(),
            player_class: String::new(),
            strength: 0,
            intelligence: 0,
            vitality: 0,
            max_health: 0,
            current_health: 0,
            damage: 0,
        }
    }

    pub fn set_class(&mut self, choice: u8) {
        self.name = "Bohater".to_string();
        match choice {
            1 => {
                self.player_class = "Wojownik".to_string();
                self.strength = 10;
                self.intelligence = 2;
                self.vitality = 8;
            }
            2 => {
                self.player_class = "Łotrzyk".to_string();
                self.strength = 6;
                self.intelligence = 5;
                self.vitality = 6;
            }
            3 => {
                self.player_class = "Mag".to_string();
                self.strength = 2;
                self.intelligence = 10;
                self.vitality = 5;
            }
            _ => {
                self.player_class = "Wojownik".to_string();
                self.strength = 10;
                self.intelligence = 2;
                self.vitality = 8;
            }
        }
        self.calculate_stats();
    }

    fn calculate_stats(&mut self) {
        self.max_health = 50 + self.vitality * 10;
        self.current_health = self.max_health;
        self.damage = match self.player_class.as_str() {
            "Wojownik" => self.strength * 2,
            "Łotrzyk" => self.strength * 2 + 2,
            "Mag" => self.intelligence * 2,
            _ => 5,
        };
    }

    pub fn display(&self) {
        Print::clear();
        Print::write("Wybrałeś ");
        Print::write_color(&self.player_class, Color::Cyan);
        Print::write("!\n\n");

        Print::write(&format!("Siła: {}\n", self.strength));
        Print::write(&format!("Inteligencja: {}\n", self.intelligence));
        Print::write(&format!("Witalność: {}\n", self.vitality));

        Print::write("Zdrowie: ");
        Print::draw_hp_bar(self.current_health, self.max_health, 20, Color::Green);
    }
}

print.rs

Kopiuj
use crossterm::{
    ExecutableCommand,
    cursor::MoveTo,
    style::Color as CtColor,
    style::Stylize,
    terminal::{Clear, ClearType},
};
use std::io::{Write, stdout};

#[derive(Clone, Copy)]
pub enum Color {
    // Default,
    Red,
    Green,
    Yellow,
    Cyan,
    // Blue,
    Magenta,
    // White,
    // Black,
}

pub struct Print;

impl Print {
    pub fn write(text: &str) {
        print!("{}", text);
        stdout().flush().unwrap();
    }

    pub fn write_color(text: &str, color: Color) {
        let ct_color = match color {
            Color::Red => CtColor::Red,
            Color::Green => CtColor::Green,
            Color::Yellow => CtColor::Yellow,
            Color::Cyan => CtColor::Cyan,
            // Color::Blue => CtColor::Blue,
            Color::Magenta => CtColor::Magenta,
            // Color::White => CtColor::White,
            // Color::Black => CtColor::Black,
            // Color::Default => CtColor::Reset,
        };
        print!("{}", text.with(ct_color));
        stdout().flush().unwrap();
    }

    pub fn clear() {
        // stdout().execute(Clear(ClearType::All)).unwrap();
        let mut stdout = stdout();

        stdout.execute(Clear(ClearType::All)).unwrap();
        stdout.execute(MoveTo(0, 0)).unwrap();

        stdout.flush().unwrap();
    }

    pub fn draw_hp_bar(current: u32, max: u32, width: usize, color: Color) {
        let filled = (current * width as u32) / max;
        let empty = width as u32 - filled;
        let bar = format!(
            "[{}{}] {}/{}",
            "█".repeat(filled as usize),
            " ".repeat(empty as usize),
            current,
            max
        );
        Print::write_color(&bar, color);
        Print::write("\n");
    }
}

main.rs

Kopiuj
mod enemy;
mod player;
mod print;

use crate::enemy::Enemy;
use crate::player::Player;
use crate::print::{Color, Print};
use rand::Rng;
use std::io;

fn get_enemy_count() -> usize {
    let mut rng = rand::rng();
    let roll = rng.random_range(0..100);

    match roll {
        0..=49 => 1,
        50..=74 => 2,
        75..=89 => 3,
        _ => 4,
    }
}

fn get_enemy_type() -> u8 {
    let mut rng = rand::rng();
    rng.random_range(0..3)
}

fn get_enemy_level() -> u8 {
    let mut rng = rand::rng();
    rng.random_range(1..=3)
}

fn main() {
    let mut player = Player::new();

    loop {
        Print::clear();
        Print::write_color("==== UpiornePotyczki ====\n\n", Color::Red);
        Print::write("1. Nowa Gra\n");
        Print::write("2. Wyjście\n");
        Print::write_color("\nWybierz opcję: ", Color::Yellow);

        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();
        let choice = input.trim().parse::<u8>().unwrap_or(0);

        if choice == 2 {
            break;
        } else if choice == 1 {
            // wybór klasy
            Print::clear();
            Print::write_color("Wybierz klasę:\n\n", Color::Yellow);
            Print::write("1. Wojownik\n2. Łotrzyk\n3. Mag\n");
            Print::write_color("\nWybierz opcję: ", Color::Yellow);

            input.clear();
            io::stdin().read_line(&mut input).unwrap();
            let class_choice = input.trim().parse::<u8>().unwrap_or(1);
            player.set_class(class_choice);
            player.display();

            // rozpoczęcie walki
            let enemy_count = get_enemy_count();
            let mut enemies: Vec<Enemy> = Vec::new();
            for _ in 0..enemy_count {
                let mut e = Enemy::new();
                e.create_enemy(get_enemy_type());
                e.set_level(get_enemy_level());
                enemies.push(e);
            }

            let mut in_combat = true;
            while in_combat {
                Print::clear();
                Print::write_color("Przeciwnicy:\n", Color::Red);
                for (i, e) in enemies.iter().enumerate() {
                    Print::write(&format!("{}: {} lvl {} ", i + 1, e.name, e.level));
                    Print::draw_hp_bar(e.current_health, e.max_health, 20, Color::Green);
                }
                Print::write("\nTwoje HP: ");
                Print::draw_hp_bar(player.current_health, player.max_health, 20, Color::Cyan);

                Print::write("\n1. Atak\n2. Ucieczka\nWybierz: ");
                input.clear();
                io::stdin().read_line(&mut input).unwrap();
                let combat_choice = input.trim().parse::<u8>().unwrap_or(1);

                if combat_choice == 2 {
                    Print::write_color("\nUciekasz!\n", Color::Yellow);

                    Print::write("\nNaciśnij ENTER, aby kontynuować...");
                    let mut pause = String::new();
                    io::stdin().read_line(&mut pause).unwrap();

                    break;
                } else if combat_choice == 1 {
                    Print::write_color("\nWybierz przeciwnika: ", Color::Yellow);
                    input.clear();
                    io::stdin().read_line(&mut input).unwrap();
                    let target_idx = input.trim().parse::<usize>().unwrap_or(1) - 1;

                    if target_idx < enemies.len() {
                        let dmg = player.damage;
                        let e = &mut enemies[target_idx];
                        e.current_health = e.current_health.saturating_sub(dmg);
                        Print::write(&format!("\nZadajesz {} obrażeń {}!\n", dmg, e.name));

                        if e.current_health == 0 {
                            Print::write_color(&format!("{} pokonany!\n", e.name), Color::Green);
                            enemies.remove(target_idx);
                        }

                        if enemies.is_empty() {
                            Print::write_color("\nWygrałeś walkę!\n", Color::Green);

                            Print::write("\nNaciśnij ENTER, aby kontynuować...");
                            let mut pause = String::new();
                            io::stdin().read_line(&mut pause).unwrap();

                            in_combat = false;
                        } else {
                            // atak przeciwników
                            for e in enemies.iter() {
                                player.current_health =
                                    player.current_health.saturating_sub(e.damage);
                                Print::write_color(
                                    &format!("{} zadaje {} obrażeń!\n", e.name, e.damage),
                                    Color::Red,
                                );
                                if player.current_health == 0 {
                                    Print::write_color("\nZostałeś pokonany!\n", Color::Red);
                                    in_combat = false;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    Print::write_color("\nDzięki za grę!\n", Color::Magenta);
}
LD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Skompilowałem też program pod Zig aby sprawdzić czy składnia będzie bardziej czytelna od Rust. Ale wyszedł mi jakiś bardziej rozwlekły kod.
Ale ja najsłabiej znam ten język. Skompilowałem grę na Zig 0.16, ale na 0.17 też powinno działać, uruchamiamy zig run.
W tych nowych językach programowania systemowego to jest dobre, że nie trzeba tworzyć dodatkowych plików .h, .ixx.
I nie trzeba wypisywać Makefile i CMakeLists.txt
enemy.zig

Kopiuj
const std = @import("std");
 
pub const Enemy = struct {
    name: []const u8,
    max_health: u32,
    current_health: u32,
    level: u8,
    damage: u32,
 
    pub fn init() Enemy {
        return Enemy{
            .name = "",
            .max_health = 0,
            .current_health = 0,
            .level = 1,
            .damage = 0,
        };
    }
 
    pub fn createEnemy(self: *Enemy, enemy_type: u8) void {
        switch (enemy_type) {
            0 => {
                self.name = "Zombie";
                self.max_health = 30;
                self.damage = 5;
            },
 
            1 => {
                self.name = "Szkieletor";
                self.max_health = 25;
                self.damage = 6;
            },
 
            2 => {
                self.name = "Goblin";
                self.max_health = 20;
                self.damage = 4;
            },
 
            else => {
                self.name = "Zombie";
                self.max_health = 30;
                self.damage = 5;
            },
        }
 
        self.current_health = self.max_health;
    }
 
    pub fn setLevel(self: *Enemy, level: u8) void {
        self.level = level;
 
        self.max_health += (@as(u32, level) - 1) * 10;
        self.current_health = self.max_health;
 
        self.damage += (@as(u32, level) - 1) * 2;
    }
};

player.zig

Kopiuj
const std = @import("std");
const Print = @import("print.zig").Print;
const Color = @import("print.zig").Color;
 
pub const PlayerClass = enum {
    Warrior,
    Rogue,
    Mage,
};
 
pub const Player = struct {
    name: []const u8,
    class: PlayerClass,
 
    strength: u32,
    intelligence: u32,
    vitality: u32,
 
    max_health: u32,
    current_health: u32,
 
    damage: u32,
 
    pub fn init() Player {
        return Player{
            .name = "",
            .class = .Warrior,
 
            .strength = 0,
            .intelligence = 0,
            .vitality = 0,
 
            .max_health = 0,
            .current_health = 0,
 
            .damage = 0,
        };
    }
 
    pub fn setClass(
        self: *Player,
        choice: u8,
    ) void {
        self.name = "Bohater";
 
        switch (choice) {
            1 => {
                self.class = .Warrior;
                self.strength = 10;
                self.intelligence = 2;
                self.vitality = 8;
            },
 
            2 => {
                self.class = .Rogue;
                self.strength = 6;
                self.intelligence = 5;
                self.vitality = 6;
            },
 
            3 => {
                self.class = .Mage;
                self.strength = 2;
                self.intelligence = 10;
                self.vitality = 5;
            },
 
            else => {
                self.class = .Warrior;
                self.strength = 10;
                self.intelligence = 2;
                self.vitality = 8;
            },
        }
 
        self.calculateStats();
    }
 
    fn calculateStats(
        self: *Player,
    ) void {
        self.max_health =
            50 + self.vitality * 10;
 
        self.current_health =
            self.max_health;
 
        self.damage = switch (self.class) {
            .Warrior => self.strength * 2,
 
            .Rogue => self.strength * 2 + 2,
 
            .Mage => self.intelligence * 2,
        };
    }
 
    pub fn display(
        self: Player,
    ) void {
        Print.clear();
 
        Print.write("Wybrałeś ");
 
        const class_name = switch (self.class) {
            .Warrior => "Wojownik",
            .Rogue => "Łotrzyk",
            .Mage => "Mag",
        };
 
        Print.writeColor(
            class_name,
            Color.Cyan,
        );
 
        Print.write("\n\n");
 
        std.debug.print(
            "Siła: {}\n",
            .{self.strength},
        );
 
        std.debug.print(
            "Inteligencja: {}\n",
            .{self.intelligence},
        );
 
        std.debug.print(
            "Witalność: {}\n",
            .{self.vitality},
        );
 
        Print.write("Zdrowie: ");
 
        Print.drawHpBar(
            self.current_health,
            self.max_health,
            20,
            Color.Green,
        );
    }
};

print.zig

Kopiuj
const std = @import("std");
 
pub const Color = enum {
    Default,
    Red,
    Green,
    Yellow,
    Cyan,
    Blue,
    Magenta,
    White,
    Black,
};
 
pub const Print = struct {
    pub fn write(text: []const u8) void {
        std.debug.print("{s}", .{text});
    }
 
    pub fn writeColor(text: []const u8, color: Color) void {
        const code = switch (color) {
            .Red => "\x1b[31m",
            .Green => "\x1b[32m",
            .Yellow => "\x1b[33m",
            .Cyan => "\x1b[36m",
            .Blue => "\x1b[34m",
            .Magenta => "\x1b[35m",
            .White => "\x1b[37m",
            .Black => "\x1b[30m",
            .Default => "\x1b[0m",
        };
 
        std.debug.print("{s}{s}\x1b[0m", .{
            code,
            text,
        });
    }
 
    pub fn clear() void {
        std.debug.print("\x1b[2J\x1b[H", .{});
    }
 
    pub fn drawHpBar(
        current: u32,
        max: u32,
        width: usize,
        color: Color,
    ) void {
        const filled = (current * width) / max;
        const empty = width - filled;
 
        Print.writeColor(
            "[",
            color,
        );
 
        for (0..filled) |_| {
            Print.write("█");
        }
 
        for (0..empty) |_| {
            Print.write(" ");
        }
 
        std.debug.print("] {}/{}\n", .{
            current,
            max,
        });
    }
};

main.zig

Kopiuj
const std = @import("std");
 
const Player = @import("player.zig").Player;
const Enemy = @import("enemy.zig").Enemy;
const Print = @import("print.zig").Print;
const Color = @import("print.zig").Color;
 
var random_counter: u32 = 0;
 
fn readNumber() u8 {
    var buffer: [32]u8 = undefined;
 
    const size = std.posix.read(
        0,
        &buffer,
    ) catch return 0;
 
    var end: usize = 0;
 
    while (end < size and buffer[end] != '\n') {
        end += 1;
    }
 
    return std.fmt.parseInt(
        u8,
        buffer[0..end],
        10,
    ) catch 0;
}
 
fn waitEnter() void {
    var buffer: [8]u8 = undefined;
 
    _ = std.posix.read(
        0,
        &buffer,
    ) catch {};
}
 
fn getEnemyType() u8 {
    random_counter += 1;
 
    return @intCast(
        random_counter % 3,
    );
}
 
fn getEnemyCount() usize {
    random_counter += 1;
 
    return switch (random_counter % 4) {
        0 => 1,
        1 => 2,
        2 => 3,
        else => 4,
    };
}
 
fn getEnemyLevel() u8 {
    random_counter += 1;
 
    return @intCast(
        (random_counter % 3) + 1,
    );
}
 
pub fn main() !void {
    var player = Player.init();
 
    while (true) {
        Print.clear();
 
        Print.writeColor(
            "==== UpiornePotyczki Zig ====\n\n",
            Color.Red,
        );
 
        Print.write(
            "1. Nowa Gra\n",
        );
 
        Print.write(
            "2. Wyjście\n\n",
        );
 
        Print.writeColor(
            "Wybierz: ",
            Color.Yellow,
        );
 
        const menu = readNumber();
 
        if (menu == 2) {
            break;
        }
 
        if (menu != 1) {
            continue;
        }
 
        Print.clear();
 
        Print.writeColor(
            "Wybierz klasę:\n\n",
            Color.Yellow,
        );
 
        Print.write(
            "1. Wojownik\n",
        );
 
        Print.write(
            "2. Łotrzyk\n",
        );
 
        Print.write(
            "3. Mag\n\n",
        );
 
        Print.writeColor(
            "Wybierz: ",
            Color.Yellow,
        );
 
        player.setClass(
            readNumber(),
        );
 
        player.display();
 
        waitEnter();
 
        var enemies: [4]Enemy = undefined;
 
        var enemy_count =
            getEnemyCount();
 
        var i: usize = 0;
 
        while (i < enemy_count) {
            enemies[i] =
                Enemy.init();
 
            enemies[i].createEnemy(
                getEnemyType(),
            );
 
            enemies[i].setLevel(
                getEnemyLevel(),
            );
 
            i += 1;
        }
 
        var fighting = true;
 
        while (fighting) {
            Print.clear();
 
            Print.writeColor(
                "=== WALKA ===\n\n",
                Color.Red,
            );
 
            i = 0;
 
            while (i < enemy_count) {
                std.debug.print(
                    "{}. {s} lvl {}\n",
                    .{
                        i + 1,
                        enemies[i].name,
                        enemies[i].level,
                    },
                );
 
                Print.drawHpBar(
                    enemies[i].current_health,
                    enemies[i].max_health,
                    20,
                    Color.Green,
                );
 
                i += 1;
            }
 
            Print.write(
                "\nTwoje HP:\n",
            );
 
            Print.drawHpBar(
                player.current_health,
                player.max_health,
                20,
                Color.Green,
            );
 
            Print.write(
                "\n1. Atak\n",
            );
 
            Print.write(
                "2. Ucieczka\n\n",
            );
 
            Print.writeColor(
                "Wybierz: ",
                Color.Yellow,
            );
 
            const action =
                readNumber();
 
            if (action == 2) {
                Print.writeColor(
                    "\nUciekasz!\n",
                    Color.Yellow,
                );
 
                fighting = false;
 
                continue;
            }
 
            if (action == 1) {
                Print.write(
                    "\nWybierz przeciwnika: ",
                );
 
                const target =
                    readNumber();
 
                if (target == 0 or target > enemy_count) {
                    continue;
                }
 
                const index =
                    target - 1;
 
                enemies[index].current_health =
                    if (enemies[index].current_health > player.damage)
                        enemies[index].current_health - player.damage
                    else
                        0;
 
                std.debug.print(
                    "\nZadajesz {} obrażeń {s}\n",
                    .{
                        player.damage,
                        enemies[index].name,
                    },
                );
 
                if (enemies[index].current_health == 0) {
                    Print.writeColor(
                        "Pokonany!\n",
                        Color.Green,
                    );
 
                    enemies[index] =
                        enemies[enemy_count - 1];
 
                    enemy_count -= 1;
                }
 
                if (enemy_count == 0) {
                    Print.writeColor(
                        "\nWygrałeś walkę!\n",
                        Color.Green,
                    );
 
                    fighting = false;
 
                    continue;
                }
 
                i = 0;
 
                while (i < enemy_count) {
                    player.current_health =
                        if (player.current_health > enemies[i].damage)
                            player.current_health - enemies[i].damage
                        else
                            0;
 
                    std.debug.print(
                        "{s} zadaje {} obrażeń!\n",
                        .{
                            enemies[i].name,
                            enemies[i].damage,
                        },
                    );
 
                    if (player.current_health == 0) {
                        Print.writeColor(
                            "\nZostałeś pokonany!\n",
                            Color.Red,
                        );
 
                        fighting = false;
 
                        break;
                    }
 
                    i += 1;
                }
 
                waitEnter();
            }
        }
 
        Print.write(
            "\nENTER aby wrócić do menu...\n",
        );
 
        waitEnter();
    }
 
    Print.writeColor(
        "\nDzięki za grę!\n",
        Color.Magenta,
    );
}

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.