From 36aa2fa24549f545fa784dd15c6f51b957622d06 Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Mon, 10 Jul 2023 21:54:35 +0200 Subject: [PATCH] Fixed player attacks --- src/config.h | 6 +- src/game/game.cpp | 6 +- src/game/input/input_mapper.cpp | 4 +- src/game/level/level_generator.cpp | 2 +- src/game/physics/map/map_player.cpp | 4 +- src/game/physics/map/map_simulation.cpp | 12 +++ src/game/physics/map/map_simulation.hpp | 2 + src/game/player/player.cpp | 100 ++++++++++++++++++++++-- src/game/player/player.hpp | 18 ++++- src/game/player/player_collection.cpp | 13 +++ src/game/player/player_collection.hpp | 2 + 11 files changed, 152 insertions(+), 17 deletions(-) diff --git a/src/config.h b/src/config.h index 19e44f0..1ce18d6 100644 --- a/src/config.h +++ b/src/config.h @@ -4,9 +4,10 @@ #include #include -#define DEVELOPER_MODE true +#define DEVELOPER_MODE false #define GAME_NAME "Holesome" +#define CLOSE_GAME_BTN sf::Keyboard::Escape // Player #define DEFAULT_PLAYER_SPEED 5.f // World units per second @@ -15,6 +16,9 @@ #define PLAYER_RADIUS_PER_LEVEL 0.25f #define DEFAULT_MAX_PLAYER_NUMBER 4 #define MIN_PLAYER_COUNT 2 +#define REDUCED_POINT_DELTA_FOR_ATTACK 20 +#define ATTACK_PER_SECOND 5.f +#define PLAYER_ALIVE_THRESHOLD -10 // World #define WORLD_GRAVITY b2Vec2(0.f, -9.8f) diff --git a/src/game/game.cpp b/src/game/game.cpp index d8a7829..1e76cdf 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -162,17 +162,17 @@ void Game::startCountdown(int durationInSeconds) std::shared_ptr Game::checkForWinner() { - std::vector> players = PlayerCollection::getInstance()->getPlayers(); + std::vector> remainingPlayers = PlayerCollection::getInstance()->getRemainingPlayers(); // Has timer run out or is only one player left? - if (!countdown->isFinished() && players.size() > 1) + if (!countdown->isFinished() && remainingPlayers.size() > 1) { return nullptr; } // Return player with highest score as winner std::shared_ptr winner = nullptr; - for (const auto &player: players) + for (const auto &player: remainingPlayers) { if (winner == nullptr || player->getPoints() > winner->getPoints()) { diff --git a/src/game/input/input_mapper.cpp b/src/game/input/input_mapper.cpp index 25dc3ce..f4a2991 100644 --- a/src/game/input/input_mapper.cpp +++ b/src/game/input/input_mapper.cpp @@ -52,8 +52,8 @@ void InputMapper::processEvents() void InputMapper::handleKeyPress(sf::Event::KeyEvent event) { - // Close game on Escape or Q in DEV Mode - if (DEVELOPER_MODE && event.code == sf::Keyboard::Escape) + // Close game on Special button + if (event.code == CLOSE_GAME_BTN) { Game::getInstance()->exit(); return; diff --git a/src/game/level/level_generator.cpp b/src/game/level/level_generator.cpp index 769564d..b0fc863 100644 --- a/src/game/level/level_generator.cpp +++ b/src/game/level/level_generator.cpp @@ -8,7 +8,7 @@ LevelConfig LevelGenerator::generateLevel(const std::string &name) std::vector collectables = generateRandomCollectables(levelSize, levelSize); return LevelConfig(name, - 120, + 90, { {1, 2}, {2, 1}, diff --git a/src/game/physics/map/map_player.cpp b/src/game/physics/map/map_player.cpp index 5342635..68d4145 100644 --- a/src/game/physics/map/map_player.cpp +++ b/src/game/physics/map/map_player.cpp @@ -84,11 +84,13 @@ void MapPlayer::updateCollidingWithPlayers() if (mapPlayerA->player->getPlayerId() == player->getPlayerId()) { collidingWithPlayers.push_back(mapPlayerB->player->getPlayerId()); - } else if (mapPlayerB->player->getPlayerId() == player->getPlayerId()) + } else { collidingWithPlayers.push_back(mapPlayerA->player->getPlayerId()); } } + + player->setCollidingPlayers(collidingWithPlayers); } void MapPlayer::updatePlayer() diff --git a/src/game/physics/map/map_simulation.cpp b/src/game/physics/map/map_simulation.cpp index 97fa30a..804e8ba 100644 --- a/src/game/physics/map/map_simulation.cpp +++ b/src/game/physics/map/map_simulation.cpp @@ -117,3 +117,15 @@ std::shared_ptr MapSimulation::getMapPlayerByBody(b2Body *body) const } return nullptr; } + +void MapSimulation::removePlayer(int playerId) +{ + // Still in simulation? + if (mapPlayersById.find(playerId) == mapPlayersById.end()) + { + return; + } + + world->DestroyBody(mapPlayersById[playerId]->body); + mapPlayersById.erase(playerId); +} diff --git a/src/game/physics/map/map_simulation.hpp b/src/game/physics/map/map_simulation.hpp index 244ffe4..d79c20b 100644 --- a/src/game/physics/map/map_simulation.hpp +++ b/src/game/physics/map/map_simulation.hpp @@ -22,6 +22,8 @@ public: void addPlayer(const std::shared_ptr& player); + void removePlayer(int playerId); + [[nodiscard]] std::shared_ptr getMapPlayerByBody(b2Body* body) const; private: diff --git a/src/game/player/player.cpp b/src/game/player/player.cpp index a280ff2..3b4a1a6 100644 --- a/src/game/player/player.cpp +++ b/src/game/player/player.cpp @@ -1,5 +1,8 @@ #include "player.hpp" #include "../../logging/easylogging++.h" +#include "player_collection.hpp" +#include "../../typography/font_manager.hpp" +#include "../physics/map/map_simulation.hpp" #include @@ -37,10 +40,13 @@ void Player::update() return; } - if (!passiveMode) { + if (!passiveMode) + { performInteractiveUpdates(); } + handlePlayerCollisions(); + GameObject::update(); } @@ -83,23 +89,23 @@ void Player::setWorldRadius(float newWorldRadius) skinSprite->coordinates->setScreenOffset(IsometricCoordinates(-newSize / 2.f)); } -long Player::getPoints() const +int Player::getPoints() const { return points; } void Player::updateRadiusBasedOnPoints() { - long points = getPoints(); + int points = getPoints(); float newWorldRadius = PLAYER_MIN_RADIUS + PLAYER_RADIUS_PER_LEVEL * points / 10.f; setWorldRadius(newWorldRadius); } -void Player::consume(int points) +void Player::consume(int consumedPoints) { - this->points += points; - LOG(INFO) << "Player " << playerId << " consumed " << points << " points. Total: " << this->points; + this->points += consumedPoints; + LOG(INFO) << "Player " << playerId << " consumed " << consumedPoints << " points. Total: " << this->points; updateRadiusBasedOnPoints(); } @@ -125,3 +131,85 @@ void Player::performInteractiveUpdates() auto moveDelta = moveDirection * speed * FRAME_TIME.asSeconds(); coordinates->move(moveDelta); } + +void Player::setCollidingPlayers(const std::vector& collidingPlayerIds) +{ + collidingPlayers.clear(); + for (auto collidingPlayerId: collidingPlayerIds) + { + collidingPlayers.push_back(PlayerCollection::getInstance()->getPlayerById(collidingPlayerId)); + } +} + +void Player::handlePlayerCollisions() +{ + if (collidingPlayers.empty()) + { + return; + } + + // Count number of players that are bigger than this player by the required margin + float numAttackingPlayers = 0; + for (const auto& collidingPlayer: collidingPlayers) + { + if (collidingPlayer->getPoints() >= points + REDUCED_POINT_DELTA_FOR_ATTACK) + { + numAttackingPlayers++; + } + } + + // Reduce points if necessary + float damage = numAttackingPlayers * ATTACK_PER_SECOND * FRAME_TIME.asSeconds(); + points -= damage; + + if (damage > 0) { + LOG(INFO) << "Player " << playerId << " lost " << damage << " points due to collisions. Total: " << points; + } + + if (points <= PLAYER_ALIVE_THRESHOLD) + { + setAlive(false); + } + + updateRadiusBasedOnPoints(); +} + +bool Player::getAlive() const +{ + return isAlive; +} + +void Player::setAlive(bool newAlive) +{ + if (isAlive == newAlive) + { + return; + } + + if (!newAlive) + { + setPassiveMode(true); + MapSimulation::getInstance()->removePlayer(getPlayerId()); + } + isAlive = newAlive; +} + +void Player::draw(sf::RenderWindow *window) +{ + if (isAlive) { + GameObject::draw(window); + return; + } + + // Print "You were consumed" message + sf::Text text; + text.setFont(*FontManager::getInstance()->getDefaultFont()); + text.setString("x-x"); + text.setCharacterSize(15); + text.setFillColor(sf::Color::Red); + text.setOutlineColor(sf::Color::Black); + text.setOutlineThickness(2); + text.setPosition(coordinates->isometric().x - text.getLocalBounds().width / 2.f, + coordinates->isometric().y - text.getLocalBounds().height / 2.f); + window->draw(text); +} diff --git a/src/game/player/player.hpp b/src/game/player/player.hpp index 232e4ba..694e029 100644 --- a/src/game/player/player.hpp +++ b/src/game/player/player.hpp @@ -29,27 +29,37 @@ public: [[nodiscard]] float getWorldRadius() const; - [[nodiscard]] long getPoints() const; + [[nodiscard]] int getPoints() const; - void consume(int points); + void consume(int consumedPoints); std::string getSkinName() const; + void setAlive(bool newAlive); + + [[nodiscard]] bool getAlive() const; + std::shared_ptr getInput() const; void setPassiveMode(bool newPassiveMode); + void setCollidingPlayers(const std::vector& collidingPlayerIds); + + void draw(sf::RenderWindow *window) override; + TranslatedCoordinates spawnPosition; private: std::shared_ptr input; float radiusInWorld = 0.5f; // In world units std::shared_ptr skinSprite; + std::vector> collidingPlayers; bool passiveMode = true; + bool isAlive = true; std::string skinName; - long points = DEFAULT_PLAYER_POINTS; + float points = DEFAULT_PLAYER_POINTS; int playerId; static inline int playerCreationCounter = 0; @@ -59,6 +69,8 @@ private: void updateRadiusBasedOnPoints(); void performInteractiveUpdates(); + + void handlePlayerCollisions(); }; diff --git a/src/game/player/player_collection.cpp b/src/game/player/player_collection.cpp index c326942..9fbe3fa 100644 --- a/src/game/player/player_collection.cpp +++ b/src/game/player/player_collection.cpp @@ -227,3 +227,16 @@ void PlayerCollection::resetPlayers() spawnPlayer(player->getInput(), player->getSkinName()); } } + +std::vector> PlayerCollection::getRemainingPlayers() const +{ + std::vector> remainingPlayers = {}; + for (auto &player: getPlayers()) + { + if (player->getAlive()) + { + remainingPlayers.push_back(player); + } + } + return remainingPlayers; +} diff --git a/src/game/player/player_collection.hpp b/src/game/player/player_collection.hpp index 6c47771..f307848 100644 --- a/src/game/player/player_collection.hpp +++ b/src/game/player/player_collection.hpp @@ -28,6 +28,8 @@ public: [[nodiscard]] std::vector> getRemovedPlayers() const; + [[nodiscard]] std::vector> getRemainingPlayers() const; + [[nodiscard]] int getMaxPlayerCount() const; void lateUpdate() override;