Nimbin[12]?SDL & Graphics / mapcreator / src/character/character.hpp

mapcreator git · master

SDL3 2.5D game and engine using assets, with map editor

sdl3 c++ game engine map-editor cmake · first commit 2025-10-31 · last commit 2026-09-07 (1 month ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/sdl-spieleentwicklung/map_creator

C++ 99.3%
git clone https://git.christianimmanuel.de/sdl-graphics/mapcreator.gitwget https://git.christianimmanuel.de/sdl-graphics/mapcreator/archive/mapcreator.tar.gz
src/character/character.hpp 7.8 KB · 348 lines raw
#pragma once

#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>

#include <vector>
#include <unordered_map>
#include <string>
#include <cmath>
#include <iostream>
#include <memory>

#include "defaults/defaults.hpp"
#include "map/tile.hpp"
#include "objects/object.hpp"
#include "character/animation.hpp"
#include "character/enemy.hpp"
#include "inventory/inventory.hpp"
#include "building/building_data.hpp"
#include "building/building.hpp"
#include "vegetables/vegetables.hpp"
#include "bird/bird.hpp"
#include "defaults/shuffle_texture.hpp"

// Character stuff

enum class CharacterMenuType {
    NONE,
    BUILDING,
    INVENTORY,
    WORKBENCH,
    RESEARCH,
};

enum class CharacterStatus {
    IDLE,
    WALK,
    RUN,
    COLLECT,
    ATTACK,
    HIT,
    DYING,
    DEAD,
    BUILD,
    CRAFT,
    BLOCK,
    DRINK_RIVER,
    EATING,
    CULTIVATING,
    PLANTING,
};


struct CharacterMoveLogic {
    SDL_FPoint move_to_position;
    bool automove = false;
};

struct CharacterCollectingLogic {
    float duration;
    float duration_max;
    TileObject* object;
    Resource_s resource;
    bool is_collecting;
    SDL_Point tile_point;
};


enum class AttackingLogicStatus_e {
    NONE,
    ATTACKING,
    BLOCKING_START,
    BLOCKING_RUNNING,
    BLOCKING_STOP
};

struct CharacterAttackingLogic {
    float duration;
    InventoryItem* item;
    AttackingLogicStatus_e  is_attacking;
    bool has_attacked;
    Enemy* enemy;
};

struct CharacterConsumingLogic {
    float duration;
    float duration_max;
    bool  is_consuming;
    bool  is_drinking;
    Resource* resource;
};

struct CharacterCultivatingLogic {
    float duration;
    float duration_max;
    bool  is_cultivating;
    bool  is_removing;
    SDL_Point tile_world;
};

struct CharacterPlantingLogic {
    float duration;
    float duration_max;
    bool  is_planting;
    SDL_Point tile_world;
    VegetableData::Type type;
    bool is_seed;
};

struct CharacterStats {
    float health_max;
    float health_reduced;
    float stamina_max;
    float stamina_reduced;
    float thirst;
    float thirst_max;

    float demage;
};

struct CharacterStaminaRegeneration {
    bool  is_regenerating = false;
    float delay_max       = 2.8;
    float delay_is        = 0;
    float regen_speed     = 2.4;
};

struct CharacterThirstDrainLogic {
    float drain_speed     = 0.01f;
    bool  send_message_0  = false;
    bool  send_message_20 = false;
};

struct CharacterSprintStartLogic {
    double started_gamesec = 0;
    double starting_duration = 2.8;
    bool   is_starting = false;
    bool   has_started = false;
};

struct CharacterStatsBonus {
    InventoryObjectType object_type;
    uint32_t type;
    float duration;
    ConsumingStatsBonus stats;
};

class Character {
    ////////////////////////////////////////
    /// Character

    float  speed;
    float  sprint_multiply;
    bool   is_sprinting = false;
    bool   flip = false;
    float  arm_reach_radius = 0;
    bool   is_placing_build = false;

    std::vector<BuildingType>
        unclocked__buildings;

    public:
    size_t tile_size; // this is the size of the texture
    CharacterMenuType  active_menu;
    Inventory_s*       selected_item;
    AnimationData*     active_anim = nullptr;
    CharacterAnimation animation;
    WalkDirection      direction = WalkDirection::UP;
    CharacterAttackingLogic   attacking_logic;
    CharacterConsumingLogic   consuming_logic;
    CharacterSprintStartLogic sprintstart_logic;
    Bird* bird = nullptr;

    bool   is_attackable = false;

    std::vector<CharacterStatsBonus> stats_bonus;

    PixelShuffler* death_shuffler;
    float shuffle_timer    = 0.0f;
    float shuffle_interval = 8.0f;


    int resurrect_start = 0; // 1 and 2
    int resurrection_start_frame = 0;
    float resurrection_unshuffle_timer = 0.0f;
    bool  resurrection_unshuffle_phase = false;
    float death_duration;
    float death_duration_max;
    int   resurrect_phase = 0;   // 0..5
    float resurrection_timer = 0.0f;

    int height;
    int width;
    SDL_FRect     collider;
    SDL_FPoint    collider_world;
    SDL_Point tile_world;
    std::vector<SDL_Point>
                  tiles_in_reach;

    SDL_FPoint death_position;


    CharacterMoveLogic move_logic;

    bool moving;

    CharacterCollectingLogic  collecting_logic;
    CharacterCultivatingLogic cultivation_logic;
    CharacterPlantingLogic    planting_logic;

    CharacterStatus status;


    CharacterStats  stats = {};
    CharacterStaminaRegeneration stamina_regen_logic;
    CharacterThirstDrainLogic    thirst_drain_logic;
    float x, y;
    SDL_FPoint spawn_point;
    int level = 1;

    std::unique_ptr<Messages> messages;
    std::unique_ptr<Inventory> inventory;

    std::vector<bool>discovered_resources;
    std::vector<bool>discovered_vegetables;
    std::vector<bool>discovered_buildings;
    std::vector<bool>researched_buildings;
    std::vector<bool>researched_items;
 
    Character();
    Character(Character&&);
    ~Character();

    void Init(SDL_Renderer* renderer);

    void set_Status(const CharacterStatus&);

    void
    draw_CircleProgress(SDL_Renderer* renderer, int cx, int cy, int radius, float progress,
                       Uint8 color_r=16, Uint8 color_g=47, Uint8 color_b=74, Uint8 color_a=210);
    void
    draw_HorizontalProgress(SDL_Renderer* renderer, float progress,
                                   Uint8 fill_r = 16, Uint8 fill_g = 47, Uint8 fill_b = 144, Uint8 fill_a = 210,
                                   Uint8 bg_r = 50, Uint8 bg_g = 50, Uint8 bg_b = 50, Uint8 bg_a = 100);

    void update_Animation(AnimationData& anim, float delta_time);
    void Draw(SDL_Renderer* renderer);


    float health_Get();
    float health_Max();
    float health_MaxBonus();
    void  health_Reduce(float amount);
    void  health_Increase(float amount);

    float stamina_Get();
    float stamina_Max();
    float stamina_MaxBonus();
    void  stamina_Reduce(float amount);
    void  stamina_Increase(float amount);
    void  stamina_StartReg();
    void  stamina_StopReg();

    float damage_Get();

    TileObject* find_ClosestObject(SDL_Point* tile_found, ObjectCategory category = ObjectCategory::NONE);
    void collect_Start(TileObject* map_object_p);
    void collect_Object();
    void collect_Stop();

    float get_SprintStartFactor() const;

    bool build_Start();

    void attack_Start();
    void attack_Enemy();
    void attack_Stop();

    void block_Start();
    void block_Enemy();
    void block_Stop();

    void building_Stop();

    void drink_Start();
    void drink_River();

    void eat_Start();
    void eat_Something();

    void consume_Stop();

    void cultivate_Start();
    void cultivate_Soil();
    void cultivate_Stop();

    bool plant_Start();
    void plant_Vegetable();
    void plant_Stop();

    void thirst_Drain();

    void interact_WithBuilding(Building* building, Input& input);

    bool is_StatsBonusAlready(InventoryObjectType object_type, uint32_t type);
    void add_ToStatsBonus(InventoryObjectType object_type, uint32_t type, ConsumingStatsBonus sb);
    void reduce_StatsBonus();

    void getting_Hit(float demage);
    void death();
    void Resurrect();
    void Revive();

    //bool is_CollidingWithObjects(const SDL_FRect& rect);
    bool is_Colliding(const SDL_FRect& rect);

    void handle_Input(Input& input, SDL_Rect win_size);
    void handle_Animation();
    void Update();
    void handle_Move();

    void draw_PickupRadius(SDL_Renderer* renderer);

    bool is_RectWithinReach( const SDL_FRect& target);

    void set_TilesInReach();

    bool using_Weapon();


    void
    set_ResourceDiscovery(ResourceType resource);
    void
    set_VegetableDiscovery(VegetableData::Type vegetable);
    void
    set_BuildingDiscovery();


    void
    unlock_Building(BuildingType type);
    bool
    is_BuildingUnlocked(BuildingType type);

    bool
    Save(const std::string &path) const;
    bool
    Load(const std::string &path);
};