Skip to content
Snippets Groups Projects
Select Git revision
  • b7562d0b353e38663dc72925e3a0da67a0ee0280
  • main default protected
  • leveleditor
  • david-author
  • clang-tidy-cleanup
  • architecture-refactoring
  • cleanUpMenus
  • doxygen-cleanup
  • project-structure-refactoring
  • interpolation
  • buildingFeatures
  • win_end_screen
  • helpMenu
  • leveleditor-placement
  • text-rendering
  • updated_unit_contextmenu
  • level-from-commandline
  • unit_contextmenu
  • player
  • engine-scaling
  • clang-tidy
21 results

Unit.cpp

Blame
  • Unit.cpp 6.16 KiB
    /**
     * Unit.cpp
     *
     * @authors Max Körschen
     * @author Nicolas Will
     * @author Frederik Keens
     */
    
    #include "Unit.hpp"
    #include "../core/Config.hpp"
    #include "../physics/PhysicsBody.hpp"
    #include "../physics/PhysicsEngine.hpp"
    #include <memory>
    
    namespace advanced_wars
    {
    
    Unit::Unit(
        int unitId, b2World* world, int tileX, int tileY, Faction faction, UnitTypeId unitTypeId,
        UnitState state, Config& config)
        : m_unitId(unitId), m_tileX(tileX), m_tileY(tileY), m_health(100),
          m_cost(config.getUnitCost(unitTypeId)), m_ammo(config.getUnitAmmo(unitTypeId)),
          m_minRange(config.getUnitMinRange(unitTypeId)),
          m_maxRange(config.getUnitMaxRange(unitTypeId)), m_maxHealth(100),
          m_movementPoints(config.getUnitMovementPoints(unitTypeId)),
          m_movementType(config.getUnitMovementType(unitTypeId)), m_faction(faction),
          m_unitTypeId(unitTypeId), m_state(state), m_world(world), m_animX(tileX), m_animY(tileY)
    {
        m_physicsBody = std::make_unique<PhysicsBody>(
            m_world, tileX, tileY, 8.0F, 8.0F, 1.0, 0.3, true, BodyType::UNIT);
    
        if (m_physicsBody && (m_physicsBody->getBody() != nullptr))
        {
            BodyUserData* bud = new BodyUserData();
            bud->type = BodyUserData::Type::UNIT;
            bud->id = m_unitId;
            bud->data = this;
    
            m_physicsBody->getBody()->GetUserData().pointer = reinterpret_cast<uintptr_t>(bud);
        }
    
        // Initialisieren der Primär- und Sekundärwaffe
        std::unordered_map<UnitTypeId, int> primaryDamage;
        std::unordered_map<UnitTypeId, int> secondaryDamage;
    
        for (int targetIt = static_cast<int>(UnitTypeId::FIRST);
             targetIt <= static_cast<int>(UnitTypeId::LAST); ++targetIt)
        {
            auto targetId = static_cast<UnitTypeId>(targetIt);
    
            if (auto damage = config.getUnitPrimaryWeaponDamage(m_unitTypeId, targetId))
            {
                primaryDamage[targetId] = *damage;
            }
            if (auto damage = config.getUnitSecondaryWeaponDamage(m_unitTypeId, targetId))
            {
                secondaryDamage[targetId] = *damage;
            }
        }
    
        m_primaryWeapon =
            std::make_unique<Weapon>(Weapon(config.getUnitPrimaryWeapon(m_unitTypeId), primaryDamage));
        m_secondaryWeapon = std::make_unique<Weapon>(
            Weapon(config.getUnitSecondaryWeapon(m_unitTypeId), secondaryDamage));
    }
    
    void Unit::update(float deltaTime)
    {
        if (!m_physicsBody)
        {
            return;
        }
    
        m_physicsBody->update(deltaTime);
    
        b2Vec2 pos = m_physicsBody->getPosition();
        calcState(static_cast<int>(pos.x), static_cast<int>(pos.y));
        m_animX = static_cast<int>(pos.x);
        m_animY = static_cast<int>(pos.y);
    }
    
    void Unit::moveTo(int posX, int posY)
    {
        if (!m_physicsBody)
        {
            return;
        }
    
        m_physicsBody->setTargetPosition(posX, posY);
        calcState(posX, posY);
        m_tileX = posX;
        m_tileY = posY;
    }
    
    void Unit::calcState(int posX, int posY)
    {
        int deltaX = this->m_animX - posX;
        int deltaY = this->m_animY - posY;
    
        if (deltaX == 0 && deltaY == 0)
        {
            if (m_hasMoved)
            {
                m_state = UnitState::UNAVAILABLE;
            }
            return;
        }
    
        if (abs(deltaX) >= abs(deltaY))
        {
            this->m_state = (deltaX > 0) ? UnitState::MOVEMENTLEFT : UnitState::MOVEMENTRIGHT;
        }
        else
        {
            this->m_state = (deltaY > 0) ? UnitState::MOVEMENTUP : UnitState::MOVEMENTDOWN;
        }
    }
    
    void Unit::render(Engine& engine, int scale)
    {
        Spritesheet* spritesheet = engine.getSpritesheet();
    
        int step = engine.getStage() % spritesheet->getUnitTextures()
                                           .at(static_cast<int>(m_faction))
                                           .at(static_cast<int>(m_unitTypeId))
                                           .at(static_cast<int>(m_state))
                                           .second;
    
        SDL_Rect src;
        SDL_Rect dst;
        if (m_state == UnitState::IDLE || m_state == UnitState::UNAVAILABLE)
        {
            src.x = step * spritesheet->getUnitWidth();
            src.y = 0;
            src.w = spritesheet->getUnitWidth();
            src.h = spritesheet->getUnitHeight();
    
            dst.x = m_animX * spritesheet->getUnitWidth() * scale;
            dst.y = m_animY * spritesheet->getUnitHeight() * scale;
            dst.w = spritesheet->getUnitWidth() * scale;
            dst.h = spritesheet->getUnitHeight() * scale;
        }
        else
        {
            src.x = step * spritesheet->getUnitMovingWidth();
            src.y = 0;
            src.w = spritesheet->getUnitMovingWidth();
            src.h = spritesheet->getUnitMovingHeight();
    
            dst.x = ((m_animX * spritesheet->getUnitWidth()) - 4) * scale;
            dst.y = ((m_animY * spritesheet->getUnitHeight()) - 8) * scale;
            dst.w = spritesheet->getUnitMovingWidth() * scale;
            dst.h = spritesheet->getUnitMovingHeight() * scale;
        }
        SDL_RenderCopyEx(
            engine.renderer(),
            spritesheet->getUnitTextures()
                .at(static_cast<int>(m_faction))
                .at(static_cast<int>(m_unitTypeId))
                .at(static_cast<int>(m_state))
                .first,
            &src, &dst, 0, nullptr, SDL_FLIP_NONE);
    
        renderHP(engine, scale);
    }
    
    void Unit::renderHP(Engine& engine, int scale)
    {
        Spritesheet* spritesheet = engine.getSpritesheet();
    
        SDL_Texture* numbers = spritesheet->getNumberTexture();
        int          numberWidth = spritesheet->getNumberWidth();
        int          numberHeight = spritesheet->getNumberHeight();
    
        int unitHp = ceil((double)m_health / 10);
    
        SDL_Rect src;
        SDL_Rect dest;
        src.x = unitHp % 10 * numberWidth;
        src.y = 0;
        src.w = numberWidth;
        src.h = numberHeight;
    
        dest.x = (m_animX * spritesheet->getTileWidth() + 8) * scale;
        dest.y = (m_animY * spritesheet->getTileHeight() + 12) * scale;
        dest.w = numberWidth * scale;
        dest.h = numberHeight * scale;
    
        SDL_RenderCopy(engine.renderer(), numbers, &src, &dest);
    
        if (unitHp == 10)
        {
            src.x = 8;
            dest.x = (m_animX * spritesheet->getTileWidth() + 1) * scale;
            SDL_RenderCopy(engine.renderer(), numbers, &src, &dest);
        }
    }
    
    void Unit::destroyBody()
    {
        if (m_physicsBody)
        {
            m_physicsBody->getBody()->GetUserData().pointer = 0;
            m_physicsBody->destroy();
            m_physicsBody.reset();
        }
    }
    
    Unit::~Unit() {}
    
    } // namespace advanced_wars