mapcreator git · master
SDL3 2.5D game and engine using assets, with map editor
C++ 99.3%git clone https://git.christianimmanuel.de/sdl-graphics/mapcreator.gitwget https://git.christianimmanuel.de/sdl-graphics/mapcreator/archive/mapcreator.tar.gzsrc/character/enemy.hpp raw
#pragma once
#include <algorithm>
#include <mutex>
#include <condition_variable>
#include "animation.hpp"
#include "objects/object.hpp"
#include "inventory/weapon.hpp"
class Character;
class Enemy;
enum class EnemyStatus {
IDLE,
RUN,
ATTACK,
HIT,
DEAD,
DYING,
};
struct EnemyAnimation {
std::unordered_map<WalkDirection, AnimationData> idle;
std::unordered_map<WalkDirection, AnimationData> run;
std::unordered_map<WalkDirection, AnimationData> attack;
std::unordered_map<WalkDirection, AnimationData> hit;
std::unordered_map<WalkDirection, AnimationData> death;
};
struct EnemyStats {
float health;
float health_max;
float demage;
bool is_attacking;
bool has_attacked;
float attack_duration;
float attack_duration_max;
};
struct CollisionInterval {
float min_x, max_x;
float min_y, max_y;
bool valid;
};
struct SpawnParams {
double spawn_date;
WeaponType type;
WeaponMaterial material;
SDL_FPoint pos;
EnemyStats stats;
};
struct EnemyMoveThreadData {
Enemy* enemy;
SDL_FPoint player;
bool is_moving;
};
enum class EnemyMovingType : uint32_t {
NONE,
IDLE,
CHARACTER,
OBJECT,
WALK,
LAST
};
struct EnemyMovingLogic {
EnemyMovingType move_type = EnemyMovingType::NONE;
void* object = nullptr;
SDL_FPoint position = {0,0};
bool position_changed = true;
float duration = 0.0f;
int max_distance = 120;
int min_distance = 80;
double path_blocked = 0; // time when blocked?
bool avoid_blockage = false;
SDL_FPoint moving_distance = {0,0};
};
struct WorkerData {
Enemy* enemy;
std::shared_ptr<std::vector<bool>> grid; // use shared_ptr for safety
};
class Enemy {
static int id_next;
int id;
float speed;
float run; // multiplier
bool flip;
static size_t tile_size;
float arm_reach_radius;
float detection_radius;
public:
static SDL_FPoint colider_default;
static std::vector<Enemy*> enemies;
static std::vector<SpawnParams> enemies_to_spawn;
EnemyMovingLogic moving_logic = {EnemyMovingType::NONE, nullptr};
bool moving;
EnemyMovingType move_focus = EnemyMovingType::NONE;
float x, y;
SDL_FPoint next_position = {0,0};
SDL_FRect collider;
CollisionInterval last_object_collision = {0,0,0,0,false};
bool avoiding_object = false;
SDL_FPoint avoidance_target = {0,0};
std::vector<SDL_FPoint> avoidance_targets;
Enemy* collidiing_with_enemy = nullptr;
CollisionInterval last_map_collision = {0,0,0,0,false};
bool avoiding_map = false;
float dist_min = 24;
float dist_max = 32;
bool is_character_in_range = false;
int stuck_moves = 0;
std::vector<SDL_FPoint> next_moves;
SDL_Point last_player_pos{};
SDL_Point last_target_pos{};
AnimationData* active_anim;
static EnemyAnimation animation_all;
EnemyAnimation animation;
WalkDirection direction;
std::unordered_map<WalkDirection, bool> direction_blocked;
bool direction_tested_up;
bool direction_tested_left;
EnemyStatus status;
Weapon weapon;
EnemyStats stats;
float max_death_time;
float death_duration;
float death_duration_max;
bool point_in_reach;
Enemy(WeaponType weapon_type,
WeaponMaterial weapon_material, SDL_FPoint position, EnemyStats status);
std::unordered_map<ResourceType,size_t> resources;
SDL_FPoint collider_world;
SDL_Point tile_world;
std::vector<SDL_Point> tiles_in_reach;
// START THREAD
static std::vector<SDL_Thread*> workers;
static std::vector<WorkerData> job_queue;
static std::mutex queue_mutex;
static std::condition_variable queue_cv;
static bool stop_threads;
// Job completion tracking
static int jobs_remaining;
static std::condition_variable jobs_done_cv;
static void init_Workers(int num_threads);
static void shutdown_Workers();
static void run_GetMovesThreads();
// END THREAD
void
Init();
static void
init_All(SDL_Renderer*);
void
set_Status(const EnemyStatus&);
void
handle_Animation();
void
Draw(SDL_Renderer* renderer);
static void
init_SpawnEnemy(double delay_to_spawn_in_sec, WeaponType weapon_type, WeaponMaterial weapon_material, SDL_FPoint position, EnemyStats status);
static bool
spawn_Enemy(SpawnParams&);
static Enemy*
is_InEnemyReach(const SDL_FRect& rect);
void
Decide(Character& player);
bool
set_CollisinnWithEnemy(const SDL_FRect& rect);
static bool
is_CollidingWithEnemy(const SDL_FRect& rect);
bool
is_CollidingWithObjects(const SDL_FRect& rect);
bool
is_CollidingWithWorld(const SDL_FRect& rect);
bool
is_Colliding(const SDL_FRect& rect);
inline bool character_InRange(SDL_FPoint char_pos) const;
void
compute_MapCollisionInterval(size_t cx, size_t cy, size_t max_x, size_t max_y);
void death();
static void remove_Dead();
// void // OLD??
// move_ToPosition(SDL_FPoint move_to_position);
void
set_AlignPosition(const SDL_FPoint& player);
void
set_NextMoves(const std::vector<bool>& map_tiles);
void
move_Path();
void
set_MoveLogic(EnemyMovingType&, Character& player);
void
Update(Character& player);
void
attack_Start();
void
Attack(bool in_reach);
void
attack_Stop();
void
getting_Hit(float demage);
void
set_TilesInReach();
static bool
save_All(const std::string &path);
static bool
load_All(const std::string &path);
};