Nimbin[12]?SDL & Graphics / mapcreator / commits / 8bc3e92

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

Add audio and EDIT enemy stuff

Christian Immanuel · 2026-01-25 14:00 · 8bc3e92e1850ac9ff822ef70cfd7166e5c87a0f0

 src/character/animation.cpp |  20 +++-
 src/character/animation.hpp |   9 +-
 src/character/character.cpp |  87 +++++++--------
 src/character/enemy.cpp     | 250 ++++++++++++++++++++++++++++++++------------
 src/character/enemy.hpp     |  20 +++-
 src/game/game.cpp           |  11 ++
 src/game/game.hpp           |   4 +
 7 files changed, 289 insertions(+), 112 deletions(-)

diff --git a/src/character/animation.cpp b/src/character/animation.cpp
index 89cea09..5d522ae 100644
--- a/src/character/animation.cpp
+++ b/src/character/animation.cpp
@@ -1,15 +1,19 @@
 #include "character/animation.hpp"
+#include "game/game.hpp"
+#include "audio/audio.hpp"
 
 
 namespace Animation {
 
     float animation_frame_time = 0.1f;
+    Audio* audio = nullptr;
 
     AnimationData
     load(SDL_Renderer* renderer,
                             const std::string& path,
                             float frame_width,
-                            float frame_height) {
+                            float frame_height,
+                            std::string audio_name_in) {
         SDL_Texture* tex = IMG_LoadTexture(renderer, path.c_str());
         SDL_SetTextureScaleMode(tex, SDL_SCALEMODE_NEAREST);
         if (!tex) {
@@ -37,6 +41,14 @@ namespace Animation {
             });
         }
 
+        // Audio
+        anim.audio_name = audio_name_in;
+        if (anim.audio_name != "None") {
+            anim.has_audio = true;
+            std::string p = "music/" + anim.audio_name + ".wav";
+            audio->RegisterSound(anim.audio_name.c_str(), p.c_str());
+        }
+
         return anim;
     }
 
@@ -47,6 +59,12 @@ namespace Animation {
         if (anim.timer >= animation_frame_time) {
             anim.timer = 0.0f;
             anim.current_frame = (anim.current_frame + 1) % anim.frames.size();
+            if (anim.has_audio) {
+                if ( !audio->is_Playing(anim.audio_name.c_str()) ) {
+                    audio->Play(anim.audio_name.c_str());
+                    std::cout << "PLAY START\n";
+                }
+            }
         }
     }
 }
diff --git a/src/character/animation.hpp b/src/character/animation.hpp
index 1d12396..af51e33 100644
--- a/src/character/animation.hpp
+++ b/src/character/animation.hpp
@@ -11,7 +11,9 @@
 #include <iostream>
 
 #include "defaults/defaults.hpp"
+#include "audio/audio.hpp"
 
+class Game;
 
 struct AnimationData {
     SDL_Texture* texture;
@@ -19,6 +21,8 @@ struct AnimationData {
     size_t current_frame = 0;
     float frame_time = 0.1f;
     float timer = 0.0f;
+    bool has_audio = false;
+    std::string audio_name;
 };
 
 struct CharacterAnimation {
@@ -40,8 +44,11 @@ struct CharacterAnimation {
 
 namespace Animation {
     extern float animation_frame_time;
+    extern Audio* audio;
+
     AnimationData
-    load(SDL_Renderer* renderer, const std::string& path, float frame_width, float frame_height);
+    load(SDL_Renderer* renderer, const std::string& path, float frame_width, float frame_height, std::string audio_name);
+
     void
     update(AnimationData& anim, float delta_time);
 }
diff --git a/src/character/character.cpp b/src/character/character.cpp
index 1f07ebc..727c7c3 100644
--- a/src/character/character.cpp
+++ b/src/character/character.cpp
@@ -76,61 +76,61 @@ Character::Init(SDL_Renderer* renderer) {
 
 
     // load_MapTiles animations
-    animation.idle[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Down-Sheet.png", tile_size, tile_size);
-    animation.idle[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Side-Sheet.png", tile_size, tile_size);
-    animation.idle[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Up-Sheet.png",   tile_size, tile_size);
+    animation.idle[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Down-Sheet.png", tile_size, tile_size, "None");
+    animation.idle[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Side-Sheet.png", tile_size, tile_size, "None");
+    animation.idle[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Up-Sheet.png",   tile_size, tile_size, "None");
 
-    animation.walk[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Walk_Base/Walk_Down-Sheet.png", tile_size, tile_size);
-    animation.walk[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Walk_Base/Walk_Side-Sheet.png", tile_size, tile_size);
-    animation.walk[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Walk_Base/Walk_Up-Sheet.png",   tile_size, tile_size);
+    animation.walk[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Walk_Base/Walk_Down-Sheet.png", tile_size, tile_size, "character.walk");
+    animation.walk[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Walk_Base/Walk_Side-Sheet.png", tile_size, tile_size, "character.walk");
+    animation.walk[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Walk_Base/Walk_Up-Sheet.png",   tile_size, tile_size, "character.walk");
 
-    animation.run[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Run_Base/Run_Down-Sheet.png", tile_size, tile_size);
-    animation.run[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Run_Base/Run_Side-Sheet.png", tile_size, tile_size);
-    animation.run[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Run_Base/Run_Up-Sheet.png",   tile_size, tile_size);
+    animation.run[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Run_Base/Run_Down-Sheet.png", tile_size, tile_size, "None");
+    animation.run[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Run_Base/Run_Side-Sheet.png", tile_size, tile_size, "None");
+    animation.run[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Run_Base/Run_Up-Sheet.png",   tile_size, tile_size, "None");
 
-    animation.collect[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size);
-    animation.collect[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size);
-    animation.collect[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size);
+    animation.collect[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size, "character.collect");
+    animation.collect[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size, "character.collect");
+    animation.collect[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size, "character.collect");
 
-    animation.cultivating[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size);
-    animation.cultivating[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size);
-    animation.cultivating[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size);
+    animation.cultivating[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size, "character.cultivate");
+    animation.cultivating[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size, "character.cultivate");
+    animation.cultivating[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size, "character.cultivate");
 
-    animation.planting[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size);
-    animation.planting[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size);
-    animation.planting[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size);
+    animation.planting[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size, "character.plant");
+    animation.planting[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size, "character.plant");
+    animation.planting[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size, "character.plant");
 
-    animation.craft[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size);
-    animation.craft[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size);
-    animation.craft[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size);
+    animation.craft[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size, "None");
+    animation.craft[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size, "None");
+    animation.craft[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size, "None");
 
-    animation.build[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size);
-    animation.build[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size);
-    animation.build[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size);
+    animation.build[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size, "None");
+    animation.build[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size, "None");
+    animation.build[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size, "None");
 
-    animation.hit[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Hit_Base/Hit_Down-Sheet.png", tile_size, tile_size);
-    animation.hit[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Hit_Base/Hit_Side-Sheet.png", tile_size, tile_size);
-    animation.hit[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Hit_Base/Hit_Up-Sheet.png",   tile_size, tile_size);
+    animation.hit[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Hit_Base/Hit_Down-Sheet.png", tile_size, tile_size, "character.hit");
+    animation.hit[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Hit_Base/Hit_Side-Sheet.png", tile_size, tile_size, "character.hit");
+    animation.hit[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Hit_Base/Hit_Up-Sheet.png",   tile_size, tile_size, "character.hit");
 
-    animation.attack_sword[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Base/Pierce_Wood_Down.png", tile_size, tile_size);
-    animation.attack_sword[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Base/Pierce_Wood_Side.png", tile_size, tile_size);
-    animation.attack_sword[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Base/Pierce_Wood_Top.png",   tile_size, tile_size);
+    animation.attack_sword[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Base/Pierce_Wood_Down.png", tile_size, tile_size, "character.attack");
+    animation.attack_sword[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Base/Pierce_Wood_Side.png", tile_size, tile_size, "character.attack");
+    animation.attack_sword[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Base/Pierce_Wood_Top.png",   tile_size, tile_size, "character.attack");
 
-    animation.hit_woodaxe_stone[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Slice_Base/Slice_Down.png", tile_size, tile_size);
-    animation.hit_woodaxe_stone[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Slice_Base/Slice_Side.png", tile_size, tile_size);
-    animation.hit_woodaxe_stone[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Slice_Base/Slice_Up.png",   tile_size, tile_size);
+    animation.hit_woodaxe_stone[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Slice_Base/Slice_Down.png", tile_size, tile_size, "None");
+    animation.hit_woodaxe_stone[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Slice_Base/Slice_Side.png", tile_size, tile_size, "None");
+    animation.hit_woodaxe_stone[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Slice_Base/Slice_Up.png",   tile_size, tile_size, "None");
 
-    animation.death[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Death_Base/Death_Down-Sheet.png", tile_size, tile_size);
-    animation.death[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Death_Base/Death_Side-Sheet.png", tile_size, tile_size);
-    animation.death[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Death_Base/Death_Up-Sheet.png",   tile_size, tile_size);
+    animation.death[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Death_Base/Death_Down-Sheet.png", tile_size, tile_size, "None");
+    animation.death[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Death_Base/Death_Side-Sheet.png", tile_size, tile_size, "None");
+    animation.death[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Death_Base/Death_Up-Sheet.png",   tile_size, tile_size, "None");
 
-    animation.block[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Blocking/Down.png", tile_size, tile_size);
-    animation.block[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Blocking/Side.png", tile_size, tile_size);
-    animation.block[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Blocking/Up.png",   tile_size, tile_size);
+    animation.block[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Blocking/Down.png", tile_size, tile_size, "None");
+    animation.block[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Blocking/Side.png", tile_size, tile_size, "None");
+    animation.block[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Pierce_Blocking/Up.png",   tile_size, tile_size, "None");
 
-    animation.drinking_river[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size);
-    animation.drinking_river[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size);
-    animation.drinking_river[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size);
+    animation.drinking_river[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Down-Sheet.png", tile_size, tile_size, "None");
+    animation.drinking_river[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Side-Sheet.png", tile_size, tile_size, "None");
+    animation.drinking_river[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Collect_Base/Collect_Up-Sheet.png",   tile_size, tile_size, "None");
 
     handle_Animation();
 
@@ -142,6 +142,8 @@ Character::Init(SDL_Renderer* renderer) {
 }
 
 void Character::set_Status(const CharacterStatus& s) {
+    if (status != s && active_anim && active_anim->has_audio)
+        Animation::audio->Stop(active_anim->audio_name.c_str());
     status = s;
     active_anim->timer = 0;
     active_anim->current_frame = 0;
@@ -1047,6 +1049,7 @@ set_AttackAnimation(AnimationData* &ad, WalkDirection& dir, Character* ch) {
 
 void
 Character::handle_Animation() {
+
     AnimationData* active_anim_ref = nullptr;
 
     WalkDirection dir = direction;
diff --git a/src/character/enemy.cpp b/src/character/enemy.cpp
index 5f11fc3..853fb2a 100644
--- a/src/character/enemy.cpp
+++ b/src/character/enemy.cpp
@@ -20,7 +20,8 @@ Enemy::Enemy(WeaponType weapon_type, WeaponMaterial weapon_material, SDL_FPoint
 
         tile_size = 64;
 
-        speed = 68.0f;
+        speed = 40.0f;
+        run = 1.4f;
         direction = WalkDirection::DOWN;
         moving = false;
         flip = false;
@@ -51,25 +52,25 @@ Enemy::Enemy(WeaponType weapon_type, WeaponMaterial weapon_material, SDL_FPoint
 
 void
 Enemy::Init(SDL_Renderer* renderer) {
-    animation.run[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Run/Run_up.png", tile_size, tile_size);
-    animation.run[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Run/Run.png", tile_size, tile_size);
-    animation.run[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Run/Run_up.png", tile_size, tile_size);
+    animation.run[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Run/Run_up.png", tile_size, tile_size, "None");
+    animation.run[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Run/Run.png", tile_size, tile_size, "None");
+    animation.run[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Run/Run_up.png", tile_size, tile_size, "None");
 
-    animation.idle[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size);
-    animation.idle[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size);
-    animation.idle[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size);
+    animation.idle[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size, "None");
+    animation.idle[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size, "None");
+    animation.idle[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size, "None");
 
-    animation.attack[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Attack/Attack_Down.png", tile_size, tile_size);
-    animation.attack[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Attack/Attack.png", tile_size, tile_size);
-    animation.attack[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Attack/Attack_Up.png", tile_size, tile_size);
+    animation.attack[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Attack/Attack_Down.png", tile_size, tile_size, "None");
+    animation.attack[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Attack/Attack.png", tile_size, tile_size, "None");
+    animation.attack[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Attack/Attack_Up.png", tile_size, tile_size, "None");
 
-    animation.hit[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size);
-    animation.hit[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size);
-    animation.hit[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size);
+    animation.hit[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size, "character.hit");
+    animation.hit[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size, "character.hit");
+    animation.hit[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Idle/Idle-Sheet_padded.png", tile_size, tile_size, "character.hit");
 
-    animation.death[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Death/Death-Sheet_processed.png", tile_size, tile_size);
-    animation.death[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Death/Death-Sheet_processed.png", tile_size, tile_size);
-    animation.death[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Death/Death-Sheet_processed.png", tile_size, tile_size);
+    animation.death[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Death/Death-Sheet_processed.png", tile_size, tile_size, "None");
+    animation.death[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Death/Death-Sheet_processed.png", tile_size, tile_size, "None");
+    animation.death[WalkDirection::UP]   = Animation::load(renderer, "Pixel_Crawler/Entities/Mobs/Skeleton Crew/Skeleton - Base/Death/Death-Sheet_processed.png", tile_size, tile_size, "None");
 
 
     handle_Animation();
@@ -342,10 +343,26 @@ void Enemy::run_GetMovesThreads() {
         SDL_WaitThread(th, nullptr);
 }
 
+
+
+
+
+void Enemy::Decide(Character& player) {
+
+    //float  d_x  = player.collider_world.x - collider_world.x;
+    //float  d_y  = player.collider_world.y - collider_world.y;
+    //size_t dc_x = static_cast<size_t>(abs(d_x));
+    //size_t dc_y = static_cast<size_t>(abs(d_y));
+    EnemyMovingType r = static_cast<EnemyMovingType>(1 + (rand() % static_cast<int>(EnemyMovingType::LAST)-1));
+
+    set_MoveLogic(r, player);
+}
+
 inline bool same_corner(const SDL_FPoint& a, const SDL_FPoint& b, float epsilon = 1.0f) {
     return std::fabs(a.x - b.x) <= epsilon && std::fabs(a.y - b.y) <= epsilon;
 }
 
+
 bool
 Enemy::set_CollisinnWithEnemy(const SDL_FRect& rect) {
 
@@ -653,6 +670,7 @@ void Enemy::move_Path() {
     bool is_actually_colliding = is_Colliding({collider.x + x, collider.y + y, collider.w, collider.h});
     if (!is_Colliding(test) || is_actually_colliding) {
         x += dx;
+        moving_logic.moving_distance.x += std::abs(dx);
     }
 
     test.x = x + collider.x;
@@ -660,6 +678,7 @@ void Enemy::move_Path() {
 
     if (!is_Colliding(test) || is_actually_colliding) {
         y += dy;
+        moving_logic.moving_distance.y += std::abs(dy);
     }
 
     
@@ -792,9 +811,74 @@ Enemy::set_AlignPosition(const SDL_FPoint& pos) {
     next_position.y = ny;
 }
 
+void
+Enemy::set_MoveLogic(EnemyMovingType& type, Character& player) {
+    moving_logic = EnemyMovingLogic();
+    moving_logic.move_type = type;
+
+    EnemyStatus sta = EnemyStatus::IDLE;
+    point_in_reach = true;
+
+    switch (type) {
+        case EnemyMovingType::NONE:
+            break;
+        case EnemyMovingType::OBJECT:
+            moving_logic.move_type = EnemyMovingType::NONE;
+            break;
+        case EnemyMovingType::IDLE:
+            moving_logic.duration = (300 + (rand() % 700))/100.0f;
+            sta = EnemyStatus::IDLE;
+            break;
+        case EnemyMovingType::WALK: {
+            SDL_FRect test_pos = collider;
+            int chance_move_far = rand() % 10;
+            if (chance_move_far < 3) {
+                moving_logic.min_distance = 100;
+                moving_logic.max_distance = 240;
+            } else {
+                moving_logic.min_distance = 50;
+                moving_logic.max_distance = 101;
+            }
+            test_pos.x = moving_logic.min_distance + (rand() % moving_logic.max_distance);
+            test_pos.y = moving_logic.min_distance + (rand() % moving_logic.max_distance);
+            moving_logic.moving_distance = {0,0};
+            moving_logic.position = 
+                Map::get_ClosestPointWithoutCollision(test_pos);
+            set_AlignPosition(moving_logic.position);
+            sta = EnemyStatus::RUN;
+            point_in_reach = false;
+            break;
+        }
+        case EnemyMovingType::CHARACTER: {
+            bool is_player_alive = player.stats.health > 0;
+            if (!is_player_alive) {
+                moving_logic.move_type = EnemyMovingType::NONE;
+                break;
+            }
+            moving_logic.object   = static_cast<void*>(&player);
+            moving_logic.position = player.collider_world;
+            set_AlignPosition(moving_logic.position);
+            sta = EnemyStatus::RUN;
+            point_in_reach = false;
+            break;
+        }
+        case EnemyMovingType::LAST:
+            moving_logic.move_type = EnemyMovingType::NONE;
+            break;
+    }
+
+    if (status != sta) {
+        set_Status(sta);
+        handle_Animation();
+    }
+}
+
 void
 Enemy::Update(Character& player) {
 
+    point_in_reach = false;
+
+    // IS DEAD
     if (stats.health <= 0) {
         if (status == EnemyStatus::DYING ||
                    status == EnemyStatus::DEAD) {
@@ -804,76 +888,106 @@ Enemy::Update(Character& player) {
         return;
     }
 
-    bool is_player_alive = player.stats.health > 0;
-
-    if (!is_player_alive && !stats.is_attacking) {
-        if (status != EnemyStatus::IDLE)
-            set_Status(EnemyStatus::IDLE);
+    // std::cout << "MVTY " << (int)moving_logic.move_type << std::endl;
+    // DECIDE // REDECIDE
+    if ( moving_logic.move_type == EnemyMovingType::NONE || (
+          moving_logic.move_type == EnemyMovingType::IDLE &&
+          moving_logic.duration <= 0)) {
+        Decide(player);
+        handle_Animation();
+        //std::cout << "MVT1 " << (int)moving_logic.move_type << std::endl;
         return;
-    }
-
-    if (moving_logic.attack_type == EnemyMovingType::NONE) {
-        moving_logic.attack_type = EnemyMovingType::CHARACTER;
-        moving_logic.object   = static_cast<void*>(&player);
-        moving_logic.position = player.collider_world;
     } else
-    if (moving_logic.attack_type == EnemyMovingType::CHARACTER) {
+    if (moving_logic.move_type == EnemyMovingType::IDLE) {
+        moving_logic.duration -= Default::delta_time;
+        handle_Animation();
+        return;
+    } else
+    if (moving_logic.move_type == EnemyMovingType::WALK) {
+        std::cout << "WLK " << moving_logic.moving_distance.x << " >= " << moving_logic.max_distance << " || " << moving_logic.moving_distance.y << " >= " << moving_logic.max_distance << std::endl; 
+        if ( moving_logic.moving_distance.x >= moving_logic.max_distance ||
+             moving_logic.moving_distance.y >= moving_logic.max_distance ) {
+            moving_logic.move_type = EnemyMovingType::NONE;
+            handle_Animation();
+            return;
+        }
+    } else
+    if (moving_logic.move_type == EnemyMovingType::CHARACTER) {
         if ( player.collider_world.x != moving_logic.position.x ||
              player.collider_world.y != moving_logic.position.y ) {
-            moving_logic.position = player.collider_world;
-            moving_logic.position_changed = true;
-        } else
-            moving_logic.position_changed = false;
+            set_MoveLogic(moving_logic.move_type, player);
+            return;
+        }
     }
-    if (moving_logic.position_changed)
-        set_AlignPosition(moving_logic.position);
+
 
     float  d_x  = moving_logic.position.x - collider_world.x;
     float  d_y  = moving_logic.position.y - collider_world.y;
+    /*
     size_t dc_x = static_cast<size_t>(abs(d_x));
     size_t dc_y = static_cast<size_t>(abs(d_y));
 
     bool   dist_ok_x = (dc_x >= dist_min && dc_x <= weapon.dimension.x) && (dc_y <= weapon.dimension.y/2);
     bool   dist_ok_y = (dc_y >= dist_min && dc_y <= weapon.dimension.x) && (dc_x <= weapon.dimension.y/2);
-
-    point_in_reach = false;
-    /*
-    std::cout << "A: " << next_moves.size() << " " << dist_ok_y << dist_ok_x << " " << player.collider_world.x << " " << player.collider_world.y << std::endl;
-    std::cout << "B: " << next_moves.size() << " " << dist_ok_y << dist_ok_x << " " << collider_world.x << " " << collider_world.y << std::endl;
-    std::cout << "B: " << next_moves.size() << " " << dist_ok_y << dist_ok_x << " " << next_position.x << " " << next_position.y << std::endl;
-    */
-    /*
-    std::cout << "C: " << dc_x << " >= " << dist_min << " " << dc_y << ">=" << dist_min << std::endl;
-    std::cout << "C: " << dc_x << " <= " << weapon.dimension.x << " " << dc_y << "<=" << weapon.dimension.x << std::endl;
-    std::cout << collider_world.x - player.collider_world.x << " " << collider_world.y - player.collider_world.y;
     */
-    if (!stats.is_attacking) {
-        move_Path();
 
-        // SET WALK DIRECTION
-        flip = (d_x < 0);
-        if (fabs(d_x) > 0.0f && fabs(d_x) > fabs(d_y)) {
-            direction = (d_x < 0 ? WalkDirection::LEFT : WalkDirection::RIGHT);
-        } else if (d_y > 0.0f) {
-            direction = WalkDirection::DOWN;
-        } else if (d_y < .0f) {
-            direction = WalkDirection::UP;
+
+    float dist_sq = d_x * d_x + d_y * d_y;
+
+    float min_sq = dist_min * dist_min;
+    float max_sq = dist_max * dist_max;
+
+    std::cout << "DSTQ " << (int)moving_logic.move_type << " " << next_moves.size()<< " "  << dist_sq << " " << min_sq << " " << max_sq << std::endl;
+    if (dist_sq >= min_sq && dist_sq <= max_sq) {
+        point_in_reach = true;
+        next_moves.clear();
+    } else if (next_moves.empty()) {
+        if (moving_logic.move_type == EnemyMovingType::WALK) {
+            set_Status(EnemyStatus::IDLE);
+            moving_logic.move_type = EnemyMovingType::IDLE;
+            moving_logic.duration = (moving_logic.moving_distance.x + moving_logic.moving_distance.y) / 100 + 0.5;
+            std::cout << "Walk DONE !!!!\n";
+            return;
         }
-        // std::cout << next_moves.size() << std::endl;
     }
-    // std::cout << dist_ok_x << " " << dist_ok_y << " " <<  next_moves.size() << std::endl;
-    if ( ( dist_ok_x || dist_ok_y ) && next_moves.empty() ) {
-        point_in_reach = true;
-        //next_moves.clear();
+
+    if (moving_logic.move_type == EnemyMovingType::CHARACTER) {
+        if (stats.is_attacking) {
+            attack_Character(player, point_in_reach);
+            handle_Animation();
+            return;
+        }
     }
 
-    if (!stats.is_attacking) {
-        if (point_in_reach && is_player_alive)
-            attack_Start();
-    } else {
-        attack_Character(player, point_in_reach);
+    if ( !point_in_reach ) {
+        move_Path();
+        handle_Animation();
+        return;
+    }
+
+
+    next_moves.clear();
+
+    // SET WALK DIRECTION
+    flip = (d_x < 0);
+    if (fabs(d_x) > 0.0f && fabs(d_x) > fabs(d_y)) {
+        direction = (d_x < 0 ? WalkDirection::LEFT : WalkDirection::RIGHT);
+    } else if (d_y > 0.0f) {
+        direction = WalkDirection::DOWN;
+    } else if (d_y < .0f) {
+        direction = WalkDirection::UP;
     }
 
+    switch (moving_logic.move_type) {
+        case EnemyMovingType::CHARACTER:
+            attack_Start();
+            break;
+        case EnemyMovingType::WALK:
+            moving_logic.move_type = EnemyMovingType::IDLE;
+            set_MoveLogic(moving_logic.move_type, player);
+            break;
+        default: break;
+    }
 
     handle_Animation();
 }
@@ -915,6 +1029,12 @@ Enemy::attack_Stop() {
     stats.attack_duration = 0;
     stats.is_attacking = false;
     stats.has_attacked = false;
+
+    if (moving_logic.move_type == EnemyMovingType::CHARACTER) {
+        if (static_cast<Character*>(moving_logic.object)->stats.health <= 0)
+            moving_logic.move_type = EnemyMovingType::NONE;
+
+    }
 }
 
 void
diff --git a/src/character/enemy.hpp b/src/character/enemy.hpp
index 529fb08..e238381 100644
--- a/src/character/enemy.hpp
+++ b/src/character/enemy.hpp
@@ -58,20 +58,28 @@ struct EnemyMoveThreadData {
     bool is_moving;
 };
 
-enum class EnemyMovingType {
+enum class EnemyMovingType : uint32_t {
     NONE,
+    IDLE,
     CHARACTER,
-    OBJECT
+    OBJECT,
+    WALK,
+    LAST
 };
 struct EnemyMovingLogic {
-    EnemyMovingType attack_type = EnemyMovingType::NONE;
+    EnemyMovingType move_type = EnemyMovingType::NONE;
     void* object = nullptr;
     SDL_FPoint position = {0,0};
     bool position_changed = true;
+    float duration = 0.0f;
+    int max_distance = 0;
+    int min_distance = 0;
+    SDL_FPoint moving_distance = {0,0};
 };
 
 class Enemy {
     float  speed;
+    float  run; // multiplier
     bool   flip;
     size_t tile_size;
     float  arm_reach_radius;
@@ -158,6 +166,9 @@ class Enemy {
     static void
     run_GetMovesThreads();
 
+    void
+    Decide(Character& player);
+
     bool
     set_CollisinnWithEnemy(const SDL_FRect& rect);
 
@@ -192,6 +203,9 @@ class Enemy {
     void
     move_Path();
 
+    void
+    set_MoveLogic(EnemyMovingType&, Character& player);
+
     void
     Update(Character& player);
 
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 53dd8ba..7eff0c1 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -54,6 +54,14 @@ Game::Game() : running(true) {
 
     lastTicks = SDL_GetTicks();
 
+    // Music
+    audio = new Audio();
+    Animation::audio = audio;
+
+    audio->RegisterSound("character.walk", "music/character.walk.wav");
+    audio->RegisterSound("character.hit",  "music/character.hit.wav");
+    audio->RegisterSound("bird.sing",      "music/bird.sing.wav");
+
     // INIT Font
     Ui::init_Font();
 
@@ -64,6 +72,8 @@ Game::Game() : running(true) {
     Icon::Init(renderer);
 
 
+
+
     Default::now = SDL_GetPerformanceCounter();
     Default::last = 0;
     Default::delta_time = 0.0;
@@ -78,6 +88,7 @@ Game::Game(Game&&) {
 }
 
 Game::~Game() {
+    audio->Quit();
     Ui::delete_Font();
     SDL_DestroyRenderer(renderer);
     SDL_DestroyWindow(window);
diff --git a/src/game/game.hpp b/src/game/game.hpp
index 3bf2450..d65fb94 100644
--- a/src/game/game.hpp
+++ b/src/game/game.hpp
@@ -12,6 +12,8 @@
 #include "game/state_playing.hpp"
 #include "game/state_menu_main.hpp"
 
+#include "audio/audio.hpp"
+
 class Input;
 
 
@@ -32,6 +34,8 @@ public:
     SDL_Window*   window   = nullptr;
     SDL_Renderer* renderer = nullptr;
 
+    Audio* audio = nullptr;
+
     bool is_cheating = false;
 
     std::unique_ptr<StatePlaying> state_playing;