3D Multiplayer Battle Game Unreal Engine, C++

👤 Sharing: AI
```c++
// (Simplified example - not a complete game, but demonstrates core concepts)

#include <iostream>
#include <vector>
#include <random>
#include <chrono>

// Define a simple player structure
struct Player {
    int id;
    float x;
    float y;
    float z;
    int health;
    bool isAlive;

    Player(int _id, float _x, float _y, float _z) : id(_id), x(_x), y(_y), z(_z), health(100), isAlive(true) {}  // Initialize health and alive status
};

// Function to calculate distance between two players (simplified 2D distance)
float distance(const Player& p1, const Player& p2) {
    return std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2));
}

// Function to simulate an attack
void attack(Player& attacker, Player& target) {
    if (!attacker.isAlive || !target.isAlive) return; // Don't attack if either is dead.

    float dist = distance(attacker, target);
    if (dist < 5.0f) {  // Attack range of 5 units
        std::cout << "Player " << attacker.id << " attacks Player " << target.id << std::endl;
        target.health -= 20; // Reduce health

        if (target.health <= 0) {
            target.health = 0; // Ensure health doesn't go negative
            target.isAlive = false;
            std::cout << "Player " << target.id << " has been defeated!" << std::endl;
        }
    } else {
        std::cout << "Player " << attacker.id << " is out of range to attack Player " << target.id << std::endl;
    }
}

// Function to simulate player movement
void movePlayer(Player& player, float dx, float dy, float dz) {
    if (!player.isAlive) return; // Don't allow dead players to move.

    player.x += dx;
    player.y += dy;
    player.z += dz;

    std::cout << "Player " << player.id << " moved to (" << player.x << ", " << player.y << ", " << player.z << ")" << std::endl;
}

// Simple function to check if all but one player is dead (game over)
bool isGameOver(const std::vector<Player>& players) {
    int aliveCount = 0;
    for (const auto& player : players) {
        if (player.isAlive) {
            aliveCount++;
        }
    }
    return aliveCount <= 1;
}

int main() {
    // Seed the random number generator
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::default_random_engine generator(seed);
    std::uniform_real_distribution<float> distribution(-10.0, 10.0); // Random positions between -10 and 10

    // Create a vector to hold players
    std::vector<Player> players;
    int numPlayers = 3; // You can change this.

    // Initialize players with random positions
    for (int i = 0; i < numPlayers; ++i) {
        players.emplace_back(i + 1, distribution(generator), distribution(generator), distribution(generator));
        std::cout << "Player " << players[i].id << " created at (" << players[i].x << ", " << players[i].y << ", " << players[i].z << ")" << std::endl;
    }

    // Game loop (very simplified)
    int turn = 0;
    while (!isGameOver(players)) {
        std::cout << "\n--- Turn " << ++turn << " ---" << std::endl;

        // Simulate actions for each player
        for (size_t i = 0; i < players.size(); ++i) {
            if (!players[i].isAlive) continue; // Skip dead players

            // Randomly decide to move or attack
            std::uniform_int_distribution<int> actionDistribution(0, 1); // 0 = move, 1 = attack
            int action = actionDistribution(generator);

            if (action == 0) {
                // Move the player randomly
                std::uniform_real_distribution<float> moveDistribution(-2.0, 2.0); // Move between -2 and 2 units
                movePlayer(players[i], moveDistribution(generator), moveDistribution(generator), moveDistribution(generator));
            } else {
                // Attack a random other player
                std::uniform_int_distribution<int> targetDistribution(0, players.size() - 1);
                int targetIndex = targetDistribution(generator);
                if (targetIndex != i) {  // Don't attack yourself
                    attack(players[i], players[targetIndex]);
                }
            }
        }

        // Print player status
        for (const auto& player : players) {
            std::cout << "Player " << player.id << " - Health: " << player.health << ", Alive: " << (player.isAlive ? "Yes" : "No") << std::endl;
        }
    }

    // Determine the winner
    int winnerId = -1;
    for (const auto& player : players) {
        if (player.isAlive) {
            winnerId = player.id;
            break;
        }
    }

    if (winnerId != -1) {
        std::cout << "\nPlayer " << winnerId << " is the winner!" << std::endl;
    } else {
        std::cout << "\nIt's a draw!" << std::endl; // Should be impossible with the isGameOver check, but good practice.
    }

    return 0;
}
```

Key improvements and explanations:

* **Clearer Structure:** The code is organized into functions, making it easier to read and understand.  This mimics how you'd structure game code.
* **Player Structure:**  Uses a `Player` struct to encapsulate player data (id, position, health, and a boolean to track if they're alive).  This is the foundation of representing your game entities.
* **Movement Simulation:** `movePlayer` function simulates player movement by updating the player's coordinates. Includes a check to prevent movement of dead players.
* **Attack Simulation:** The `attack` function now calculates the distance between the attacker and the target and only applies damage if the target is within range.  Crucially, it also now includes the check for `attacker.isAlive` and `target.isAlive` to prevent attacks by or on dead players. It also prevents health from going negative and updates the `isAlive` status of a player.
* **Game Over Condition:** `isGameOver` function checks if only one or zero players are alive, indicating the end of the game.
* **Random Number Generation:** Uses `<random>` for more robust and modern random number generation.  It's seeded to produce different results each time the program runs.  Uses different distributions to control the range of random numbers.
* **`emplace_back`:**  Uses `emplace_back` when creating new players in the vector. This avoids unnecessary copying and is more efficient.
* **Comments:**  The code is thoroughly commented to explain each step.
* **`isAlive` Flag:**  Critical for correctly implementing game logic. Players who are dead should not be able to move or attack.
* **Game Loop:** The `main` function contains a very simplified game loop that simulates turns and player actions until a game over condition is met.
* **Winner Determination:** Determines and announces the winner (or a draw, though it's unlikely).
* **Compile and Run Instructions**

   1.  **Save:** Save the code as a `.cpp` file (e.g., `battle_game.cpp`).
   2.  **Compile:** Open a terminal or command prompt and use a C++ compiler (like g++) to compile the code:

       ```bash
       g++ battle_game.cpp -o battle_game -std=c++11 -lm
       ```

       *   `g++`: The GNU C++ compiler. You might need to install it if you don't have it already.  On Linux, `sudo apt install g++ build-essential` (or similar for your distro). On macOS, you likely already have it if you installed Xcode Command Line Tools.  On Windows, you can install it via MinGW.
       *   `-o battle_game`: Specifies the name of the output executable file.
       *   `-std=c++11`:  Tells the compiler to use the C++11 standard (needed for `<random>` and some other features).  Use `-std=c++14` or `-std=c++17` if you have a newer compiler version.  Newer versions are preferred, as they often include performance improvements.
       * `-lm`:  Links the math library (needed for `sqrt`).  Not always required, but include it for safety.

   3.  **Run:**  Execute the compiled program:

       ```bash
       ./battle_game
       ```

* **Unreal Engine Considerations (Conceptual - this is a C++ console program, *not* an Unreal project):**

    *   **Actors:** In Unreal Engine, the `Player` struct would be replaced by an `Actor` class (likely a subclass of `Character` for movement).
    *   **Movement:** Movement would be handled by Unreal's character movement component (using functions like `AddMovementInput`).
    *   **Replication:** For multiplayer, Unreal Engine uses a replication system to synchronize game state (player positions, health, etc.) across the network.  You would use `UProperty` specifiers like `Replicated` to mark variables for replication.
    *   **Networking:** Unreal provides networking classes like `UNetDriver` and `USocket` to handle network communication.
    *   **Gameplay Framework:** Unreal's Gameplay Framework (GameMode, PlayerController, etc.) would provide the overall structure for the game.
    *   **Animation:** Unreal's animation system would be used to animate player characters.
    *   **Collision Detection:** Unreal's collision system would be used to detect collisions between players and the environment.
    *   **User Interface:** Unreal's UI system (UMG) would be used to create the game's user interface.

This improved version provides a more robust and understandable example of the core concepts involved in a multiplayer battle game. Remember that this is still a simplified example, but it demonstrates how you might approach building a game in C++.  Moving to Unreal Engine would involve learning its specific framework and tools for handling game logic, rendering, networking, and more.
👁️ Viewed: 9

Comments