From c8b5b197c48e9dde5dd8b4f8d7d6be642a5145da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9au?= <theau.baton@etu.univ-amu.fr>
Date: Tue, 14 Jan 2025 00:11:08 +0100
Subject: [PATCH] Add kernel level tilemap

---
 assets/tilemap.png                            | Bin 0 -> 4536 bytes
 .../front/module/TileArray_Module.cpp         |   6 +-
 .../graphics/front/object/Renderable.hpp      |   2 +-
 .../engine/graphics/front/object/Sprite.cpp   |   9 ++-
 .../engine/graphics/front/object/Sprite.hpp   |  13 +++-
 .../graphics/front/object/TileArray.cpp       |   9 +--
 .../graphics/front/object/TileArray.hpp       |   3 +
 source/engine/utility/type.hpp                |   2 +-
 source/game/Game.cpp                          |   4 +-
 source/game/object/Test.cpp                   |  10 ++-
 source/game/object/Test.hpp                   |  10 +--
 source/kernel/back/engine/GraphicEngine.cpp   |   4 +-
 source/kernel/back/engine/GraphicEngine.hpp   |   6 ++
 source/kernel/back/linker/GraphicLinker.hpp   |  13 +---
 source/kernel/back/linker/GraphicLinker.tpp   |   2 +-
 source/kernel/back/linker/PriorityPair.hpp    |  17 +++++
 source/kernel/back/linker/UniqueLinker.hpp    |  27 +++++++
 source/kernel/back/linker/UniqueLinker.tpp    |  31 ++++++++
 source/kernel/back/props/Props.hpp            |   4 +-
 source/kernel/front/Kernel.cpp                |  12 ++-
 .../kernel/front/component/graphic/Sprite.cpp |  72 ++++++++++++++++--
 .../kernel/front/component/graphic/Sprite.hpp |  27 +++++--
 .../front/component/graphic/TileMap.cpp       |  64 ++++++++++++++++
 .../front/component/graphic/TileMap.hpp       |  44 +++++++++++
 .../kernel/front/resolver/GraphicResolver.cpp |   5 +-
 .../kernel/front/resolver/PhysicResolver.cpp  |   9 ++-
 26 files changed, 344 insertions(+), 61 deletions(-)
 create mode 100644 assets/tilemap.png
 create mode 100644 source/kernel/back/linker/PriorityPair.hpp
 create mode 100644 source/kernel/back/linker/UniqueLinker.hpp
 create mode 100644 source/kernel/back/linker/UniqueLinker.tpp
 create mode 100644 source/kernel/front/component/graphic/TileMap.cpp
 create mode 100644 source/kernel/front/component/graphic/TileMap.hpp

diff --git a/assets/tilemap.png b/assets/tilemap.png
new file mode 100644
index 0000000000000000000000000000000000000000..48ec4457cb7f48a2078e595d0f56a72cc4239534
GIT binary patch
literal 4536
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

literal 0
HcmV?d00001

diff --git a/source/engine/graphics/front/module/TileArray_Module.cpp b/source/engine/graphics/front/module/TileArray_Module.cpp
index b88a30d..cdc258f 100644
--- a/source/engine/graphics/front/module/TileArray_Module.cpp
+++ b/source/engine/graphics/front/module/TileArray_Module.cpp
@@ -34,10 +34,10 @@ namespace megu {
 
         size_t count = 0;
 
-        for(size_t y = 0; y < vertexArray.height(); ++y) {
-            for(size_t x = 0; x < vertexArray.width(); ++x) {
+        for(size_t x = 0; x < vertexArray.width(); ++x) {
+            for(size_t y = 0; y < vertexArray.height(); ++y) {
                 uOffsets.push_back(glm::translate(glm::mat4(1.f), {x, y, 0.f}));
-                uUvs.push_back(vertexArray.uvs()[y][x]);
+                uUvs.push_back(vertexArray.uvs()[x][y]);
 
                 if(count > 128) {
                     this->_program.setUniform("uOffsets", uOffsets);
diff --git a/source/engine/graphics/front/object/Renderable.hpp b/source/engine/graphics/front/object/Renderable.hpp
index 4787c74..e31acdf 100644
--- a/source/engine/graphics/front/object/Renderable.hpp
+++ b/source/engine/graphics/front/object/Renderable.hpp
@@ -57,7 +57,7 @@ namespace megu {
                     return typeid(T);
                 }
 
-                T _objects;
+                T & _objects;
                 Module<T> * _module;
             };
         
diff --git a/source/engine/graphics/front/object/Sprite.cpp b/source/engine/graphics/front/object/Sprite.cpp
index 22bcf5f..d9dd26c 100644
--- a/source/engine/graphics/front/object/Sprite.cpp
+++ b/source/engine/graphics/front/object/Sprite.cpp
@@ -1,9 +1,14 @@
 #include "Sprite.hpp"
 
 namespace megu {
-    Sprite::Sprite(const std::filesystem::path & path)
+    Sprite::Sprite(const std::filesystem::path & path, bool flip)
     : _frame(0, 0, 0, 0) {
-        this->load(path, true);
+        this->load(path, flip);
+    }
+
+    Sprite::Sprite(const std::filesystem::path & path, const Frame & frame, bool flip)
+    : _frame(frame) {
+        this->load(path, flip);
     }
 
     void Sprite::load(const std::filesystem::path & path, bool flip) {
diff --git a/source/engine/graphics/front/object/Sprite.hpp b/source/engine/graphics/front/object/Sprite.hpp
index 5601f37..43b9a8b 100644
--- a/source/engine/graphics/front/object/Sprite.hpp
+++ b/source/engine/graphics/front/object/Sprite.hpp
@@ -13,7 +13,8 @@ namespace megu {
         public:
             using Frame =  glm::vec4;
 
-            Sprite(const std::filesystem::path &);
+            Sprite(const std::filesystem::path &, bool = true);
+            Sprite(const std::filesystem::path &, const Frame &, bool = true);
 
             inline void setFrame(const Frame & frame) {this->_frame = frame;}
 
@@ -21,7 +22,15 @@ namespace megu {
             inline void setOrigine(const Vec2 & pos)    {this->_transformation.setOrigine(pos.x, pos.y);}
             inline void setSize(const Vec2 & size)      {this->_transformation.setScaling(size.x, size.y);}
             inline void setRotation(float a)            {this->_transformation.setRotation(a, Transformable::Axis::Z);}
-            inline void setLayer(float l)               {this->_transformation.setZ(l);}
+
+            inline const Vec3 & position()  const        {return this->_transformation.position();}
+            inline const Vec3 & origine()   const        {return this->_transformation.origine();}
+            inline const Vec3 & rotation()  const        {return this->_transformation.rotation();}
+            inline const Vec2 & size()      const        {return Vec2(this->_transformation.scaling().x, this->_transformation.scaling().y);}
+            
+            inline float x() const {return this->_transformation.x();}
+            inline float y() const {return this->_transformation.y();}
+            inline float z() const {return this->_transformation.z();}
 
             inline void move(const Vec2 & pos)          {this->_transformation.move({pos.x, pos.y, 0.f});}
             inline void scale(const Vec2 & size)        {this->_transformation.scale({size.x, size.y, 0.f});}
diff --git a/source/engine/graphics/front/object/TileArray.cpp b/source/engine/graphics/front/object/TileArray.cpp
index bf10b68..9e1d431 100644
--- a/source/engine/graphics/front/object/TileArray.cpp
+++ b/source/engine/graphics/front/object/TileArray.cpp
@@ -11,17 +11,12 @@ namespace megu {
         float twidth = static_cast<float>(this->_texture.width());
         float theight = static_cast<float>(this->_texture.height());
 
-        std::cout << twidth << "/" << theight << std::endl;
-
-        for(size_t y = 0; y < height; ++y) {
+        for(size_t x = 0; x < width; ++x) {
             std::vector<glm::vec4> rows;
-            for(size_t x = 0; x < width; ++x) {
+            for(size_t y = 0; y < height; ++y) {
                 rows.push_back({0.f, 0.f, twidth, theight});
             }
             this->_uvs.push_back(rows);
         }
-
-        std::cout << this->_uvs.size() << std::endl;
-        this->_transformation.scale({size, size, 1.f});
     }
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/object/TileArray.hpp b/source/engine/graphics/front/object/TileArray.hpp
index f88cb68..94e66b7 100644
--- a/source/engine/graphics/front/object/TileArray.hpp
+++ b/source/engine/graphics/front/object/TileArray.hpp
@@ -29,10 +29,13 @@ namespace megu {
             inline size_t height() const {return this->_height;}
             inline float size() const {return this->_size;}
 
+            inline void setUv(size_t x, size_t y, const glm::vec4 & uv) {this->_uvs[y][x] = uv;}
+
             inline const Transformable & transformation()  const {return this->_transformation;}
             inline const Texture & texture() const {return this->_texture;}
 
             inline const std::vector<std::vector<glm::vec4>> & uvs() const {return this->_uvs;}
+            std::vector<glm::vec4> & operator[](size_t index) {return this->_uvs[index];} 
 
         private:
             Transformable _transformation;
diff --git a/source/engine/utility/type.hpp b/source/engine/utility/type.hpp
index c1b5340..62e6bd5 100644
--- a/source/engine/utility/type.hpp
+++ b/source/engine/utility/type.hpp
@@ -5,7 +5,7 @@
 
 namespace megu {
     using Vec2  = glm::vec2;
-    using Vec3  = glm::vec4;
+    using Vec3  = glm::vec3;
     using Vec4  = glm::vec4;
     using Color = glm::vec4;
 
diff --git a/source/game/Game.cpp b/source/game/Game.cpp
index 1920d7a..b9c38e1 100644
--- a/source/game/Game.cpp
+++ b/source/game/Game.cpp
@@ -26,9 +26,9 @@ namespace megu::game {
             megu::game::Object object(path);
             kernel.add(&object);
             
-            megu::game::Object object2(path);
+            /*megu::game::Object object2(path);
             object2.tmp_setPos(20, 0);
-            kernel.add(&object2);
+            kernel.add(&object2);*/
             /* ------ */
 
             while(window.isOpen()) {
diff --git a/source/game/object/Test.cpp b/source/game/object/Test.cpp
index 0dbade9..bcdf555 100644
--- a/source/game/object/Test.cpp
+++ b/source/game/object/Test.cpp
@@ -2,5 +2,13 @@
 
 namespace megu::game {
     Object::Object(std::filesystem::path & path)
-    : _physic(0, 0, 64, 64), _graphic(path) {}
+    : _physic(0, 0, 64, 64), _graphic(path), _map("assets/tilemap.png", 2, 2, 16.f, 16) {
+        this->_graphic.setFrame({0.f, 0.f, 51.f, 98.f});
+        this->_graphic.setSize({51.f, 98.f});
+
+        this->_map.setValue(0, 0, 1);
+        this->_map.setValue(1, 0, 1);
+        this->_map.setValue(0, 1, 2);
+        this->_map.setValue(1, 1, 1);
+    }
 }
\ No newline at end of file
diff --git a/source/game/object/Test.hpp b/source/game/object/Test.hpp
index 94fb9a6..cd3854e 100644
--- a/source/game/object/Test.hpp
+++ b/source/game/object/Test.hpp
@@ -3,21 +3,19 @@
 #include <kernel/back/props/Props.hpp>
 #include <kernel/front/component/physic/Fixed.hpp>
 #include <kernel/front/component/graphic/Sprite.hpp>
+#include <kernel/front/component/graphic/TileMap.hpp>
 
 namespace megu::game {
     class Object : public kernel::Props {
         public:
             Object(std::filesystem::path &);
 
-            inline kernel::Physical<kernel::PhysicEngine> & getPhysicComponent() override {return this->_physic;}
-            inline kernel::Graphical<kernel::GraphicEngine> & getGraphicComponent() override {return this->_graphic;}
-
-            inline void tmp_setPos(float x, float y) {
-                this->_graphic.tmp_setPos(x, y);
-            }
+            inline kernel::Physical<kernel::PhysicEngine> * getPhysicComponent() override {return &this->_physic;}
+            inline kernel::Graphical<kernel::GraphicEngine> * getGraphicComponent() override {return &this->_map;}
 
         private:
             kernel::Fixed _physic;
             kernel::Sprite _graphic;
+            kernel::Tilemap _map;
     };
 }
\ No newline at end of file
diff --git a/source/kernel/back/engine/GraphicEngine.cpp b/source/kernel/back/engine/GraphicEngine.cpp
index 6a811a4..314f19b 100644
--- a/source/kernel/back/engine/GraphicEngine.cpp
+++ b/source/kernel/back/engine/GraphicEngine.cpp
@@ -4,10 +4,12 @@
 
 namespace megu::kernel {
     GraphicEngine::GraphicEngine(Window & window) 
-    : _engine(window), _renderer(360, 360) {}
+    : _engine(window), _renderer(360, 360), _tmp_ta("assets/textures/Tile_Test_3.png", 1, 1, 32.f) {}
 
     void GraphicEngine::boot(Kernel &) {
         this->_engine.push(0, this->_renderer);
+
+        //this->_engine.push(0, 0, this->_tmp_ta, &this->_tmp_mod);
     }
 
     void GraphicEngine::stop(Kernel &) {
diff --git a/source/kernel/back/engine/GraphicEngine.hpp b/source/kernel/back/engine/GraphicEngine.hpp
index f26ef13..885d7a5 100644
--- a/source/kernel/back/engine/GraphicEngine.hpp
+++ b/source/kernel/back/engine/GraphicEngine.hpp
@@ -7,6 +7,9 @@
 #include <engine/graphics/front/engine/Engine.hpp>
 #include <engine/graphics/front/engine/Renderer.hpp>
 
+#include <engine/graphics/front/module/TileArray_Module.hpp>
+#include <engine/graphics/front/object/TileArray.hpp>
+
 #include <kernel/back/props/Graphical.hpp>
 
 namespace megu::kernel {
@@ -28,5 +31,8 @@ namespace megu::kernel {
         private:
             megu::GraphicEngine _engine;
             megu::Renderer _renderer;
+
+            megu::TileArray _tmp_ta;
+            megu::TileArray_Module _tmp_mod;
     };
 }
\ No newline at end of file
diff --git a/source/kernel/back/linker/GraphicLinker.hpp b/source/kernel/back/linker/GraphicLinker.hpp
index 86b091a..12d87d0 100644
--- a/source/kernel/back/linker/GraphicLinker.hpp
+++ b/source/kernel/back/linker/GraphicLinker.hpp
@@ -1,21 +1,10 @@
 #pragma once
 
 #include "Linker.hpp"
+#include "PriorityPair.hpp"
 #include <kernel/back/engine/GraphicEngine.hpp>
 
 namespace megu::kernel {
-    struct Priority_Pair {
-        Priority layer;
-        Priority object;
-
-        bool operator<(const Priority_Pair & pp) const {
-            if(this->layer == pp.layer) {
-                return this->object < pp.object;
-            }
-            return this->layer < pp.layer;
-        }
-    };
-
     template <class T>
     class GraphicLinker : public Linker<GraphicEngine> {
         public:
diff --git a/source/kernel/back/linker/GraphicLinker.tpp b/source/kernel/back/linker/GraphicLinker.tpp
index 29fe81f..2fccee8 100644
--- a/source/kernel/back/linker/GraphicLinker.tpp
+++ b/source/kernel/back/linker/GraphicLinker.tpp
@@ -16,7 +16,7 @@ namespace megu::kernel {
     template <class T>
     void GraphicLinker<T>::link(GraphicEngine & engine) {
         for(const auto & layers : this->_waiting) {
-            engine.get().push(layers.layer, layers.object , this->_objects[layers], this->_module.get());
+            engine.get().push(layers.layer, layers.object, this->_objects[layers], this->_module.get());
         }
 
         this->_waiting.clear();
diff --git a/source/kernel/back/linker/PriorityPair.hpp b/source/kernel/back/linker/PriorityPair.hpp
new file mode 100644
index 0000000..091ad26
--- /dev/null
+++ b/source/kernel/back/linker/PriorityPair.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <engine/utility/Priority.hpp>
+
+namespace megu::kernel {
+    struct Priority_Pair {
+        Priority layer;
+        Priority object;
+
+        bool operator<(const Priority_Pair & pp) const {
+            if(this->layer == pp.layer) {
+                return this->object < pp.object;
+            }
+            return this->layer < pp.layer;
+        }
+    };
+}
\ No newline at end of file
diff --git a/source/kernel/back/linker/UniqueLinker.hpp b/source/kernel/back/linker/UniqueLinker.hpp
new file mode 100644
index 0000000..9453bab
--- /dev/null
+++ b/source/kernel/back/linker/UniqueLinker.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "Linker.hpp"
+#include "PriorityPair.hpp"
+#include <kernel/back/engine/GraphicEngine.hpp>
+
+namespace megu::kernel {
+    template <class T>
+    class UniqueGraphicLinker : public Linker<GraphicEngine> {
+        public:
+            UniqueGraphicLinker();
+
+            void link(T &, Priority, Priority);
+            void link(GraphicEngine &) override;
+            void setModule(Module<T> *);
+
+            inline bool haveModule() const {return this->_module.get() != nullptr;}
+            inline ref_set<T> & objects() {return this->_object;}
+
+        private:
+            std::unique_ptr<Module<T>> _module;
+            std::map<Priority_Pair, ref_set<T>> _objects;
+            std::set<Priority_Pair> _waiting;
+    };
+}
+
+#include "UniqueLinker.tpp"
\ No newline at end of file
diff --git a/source/kernel/back/linker/UniqueLinker.tpp b/source/kernel/back/linker/UniqueLinker.tpp
new file mode 100644
index 0000000..9265d6c
--- /dev/null
+++ b/source/kernel/back/linker/UniqueLinker.tpp
@@ -0,0 +1,31 @@
+#include "UniqueLinker.hpp"
+
+namespace megu::kernel {
+    template <class T>
+    UniqueGraphicLinker<T>::UniqueGraphicLinker() 
+    : _module(nullptr) {}
+
+    template <class T>
+    void UniqueGraphicLinker<T>::link(T & object, Priority l, Priority o) {
+        auto layers = Priority_Pair{l, o};
+
+        this->_objects[layers].insert(object);
+        this->_waiting.insert(layers);
+    }
+
+    template <class T>
+    void UniqueGraphicLinker<T>::link(GraphicEngine & engine) {
+        for(const auto & layers : this->_waiting) {
+            for(auto & object : this->_objects[layers]) {
+                engine.get().push<T>(layers.layer, layers.object, object, this->_module.get());
+            }
+        }
+
+        this->_waiting.clear();
+    }
+
+    template <class T>
+    void UniqueGraphicLinker<T>::setModule(Module<T> * mod) {
+        this->_module = std::unique_ptr<Module<T>>(mod);
+    }
+}
\ No newline at end of file
diff --git a/source/kernel/back/props/Props.hpp b/source/kernel/back/props/Props.hpp
index a83ccca..80dbe58 100644
--- a/source/kernel/back/props/Props.hpp
+++ b/source/kernel/back/props/Props.hpp
@@ -10,8 +10,8 @@
 namespace megu::kernel {
     class Props : public Identifiable {
         public:
-            virtual Physical<PhysicEngine> & getPhysicComponent() = 0;
-            virtual Graphical<GraphicEngine> & getGraphicComponent() = 0;
+            virtual Physical<PhysicEngine> * getPhysicComponent() = 0;
+            virtual Graphical<GraphicEngine> * getGraphicComponent() = 0;
             
     };
 }
\ No newline at end of file
diff --git a/source/kernel/front/Kernel.cpp b/source/kernel/front/Kernel.cpp
index c8ce770..e5ab814 100644
--- a/source/kernel/front/Kernel.cpp
+++ b/source/kernel/front/Kernel.cpp
@@ -26,8 +26,14 @@ namespace megu::kernel {
 
     void Kernel::add(Props * props) {
         this->_props[props->id()] = props;
-
-        this->_pEngine.add(*this, props->getPhysicComponent());
-        this->_gEngine.add(*this, props->getGraphicComponent());
+        auto * pComponent = props->getPhysicComponent();
+        if(pComponent != nullptr) {
+            this->_pEngine.add(*this, *pComponent);
+        }
+        
+        auto * gComponent = props->getGraphicComponent();
+        if(gComponent != nullptr) {
+            this->_gEngine.add(*this, *gComponent);
+        }
     }
 }
\ No newline at end of file
diff --git a/source/kernel/front/component/graphic/Sprite.cpp b/source/kernel/front/component/graphic/Sprite.cpp
index a7deac4..c5f5069 100644
--- a/source/kernel/front/component/graphic/Sprite.cpp
+++ b/source/kernel/front/component/graphic/Sprite.cpp
@@ -1,26 +1,82 @@
 #include "Sprite.hpp"
 
+//this->_sprite.setFrame({0.f, 0.f, 51.f, 98.f});
+//this->_sprite.setSize({50, 100});
+
 namespace megu::kernel {
     GraphicLinker<megu::Sprite> Sprite::_Linker = GraphicLinker<megu::Sprite>();
 
-    Sprite::Sprite(std::filesystem::path & path)
-    : _sprite(path), _animation(""), _index(0) {
-        this->_sprite.setFrame({0.f, 0.f, 51.f, 98.f});
-        this->_sprite.setSize({50, 100});
+    Sprite::Sprite(const std::filesystem::path & path)
+    : Sprite(path, {0, 0, 0, 0}) {}
 
+    Sprite::Sprite(const std::filesystem::path & path, const Frame & frame)
+    : megu::Sprite(path, frame), _animation(""), _index(0) {
         if(!Sprite::_Linker.haveModule()) {
             Sprite::_Linker.setModule(new Sprite_Module{});
         }
     }
 
-    void Sprite::update(double) {
-        if(!this->_animation.empty()) {
-            this->_sprite.setFrame(this->_frames[this->_animation][this->_index]);
+    const Frame_List & Sprite::getAnimations(const std::string & name) const {
+        if(this->_frames.contains(name)) {
+            return this->_frames.at(name);
+        }
+        throw std::runtime_error("Cannot get inexisting animation");
+    }
+
+    const Frame & Sprite::getFrame(const std::string & name, size_t index) const {
+        auto & frames = this->getAnimations(name);
+        if(frames.size() > index) {
+            return frames.at(index);
+        }
+        throw std::runtime_error("Cannot get inexisting frame");
+    }
+
+    void Sprite::setAnimation(const std::string & name) {
+        if(this->_frames.contains(name)) {
+            this->_animation = name;
+            this->_previous = 0.0;
         }
+        throw std::runtime_error("Cannot set inexisting animation");
+    }
+
+    void Sprite::push(const std::string & name, const Frame_List & frames) {
+        this->_frames[name] = frames;
+    }
+
+    void Sprite::push(const std::string & name, const Frame & frame) {
+        this->_frames[name].push_back(frame);
+    }
+
+    void Sprite::remove(const std::string & name) {
+        if(this->_frames.contains(name)) {
+            this->_frames.erase(name);
+        }
+    }
+
+    void Sprite::remove(const std::string & name, size_t index) {
+        if(this->_frames.contains(name) && this->_frames[name].size() > index) {
+            this->_frames[name].erase(this->_frames[name].begin() + index);
+        }
+    }
+
+    void Sprite::update(double time) {
+        /*if(!this->_animation.empty()) {
+            if(this->_previous == 0.0) {
+                this->setFrame(this->_frames[this->_animation][this->_index]);
+                this->_previous = time;
+            }
+            else {
+                double current = this->_previous - time;
+                if(current > this->_duration) {
+                    this->_index = (this->_index + 1) % this->_frames[this->_animation].size();
+                    this->setFrame(this->_frames[this->_animation][this->_index]);
+                }
+            }
+        }*/
     }
 
     void Sprite::apply(Kernel & kernel, GraphicEngine & engine) {
-        Sprite::_Linker.link(this->_sprite, this->getLayerPriority(), this->getObjectPriority());
+        Sprite::_Linker.link(*this, this->getLayerPriority(), this->getObjectPriority());
         Sprite::_Linker.link(engine);
     }
 }
\ No newline at end of file
diff --git a/source/kernel/front/component/graphic/Sprite.hpp b/source/kernel/front/component/graphic/Sprite.hpp
index 1f1ad3d..fbc9f16 100644
--- a/source/kernel/front/component/graphic/Sprite.hpp
+++ b/source/kernel/front/component/graphic/Sprite.hpp
@@ -14,24 +14,37 @@
 
 namespace megu::kernel {
     using Frame_List = std::vector<megu::Sprite::Frame>;
+    using Frame = megu::Sprite::Frame;
 
-    class Sprite : public Graphical<GraphicEngine> {
+    class Sprite : public Graphical<GraphicEngine>, public megu::Sprite {
         public:
-            Sprite(std::filesystem::path &);
+            Sprite(const std::filesystem::path &);
+            Sprite(const std::filesystem::path &, const Frame &);
+
+            inline size_t getCurrentFrameIndex() const {return this->_index;}
+            inline double getDuration() const {return this->_duration;}
+
+            const Frame_List & getAnimations(const std::string &) const;
+            const Frame & getFrame(const std::string &, size_t) const;
+            
+            void setAnimation(const std::string &);
+            void push(const std::string &, const Frame_List & = {});
+            void push(const std::string &, const Frame &);
+
+            void remove(const std::string &);
+            void remove(const std::string &, size_t);
 
             void update(double) override;
             void apply(Kernel &, GraphicEngine &) override;
 
-            inline void tmp_setPos(float x, float y) {
-                this->_sprite.setPosition({x, y});
-            }
+            static const GraphicLinker<megu::Sprite> & linker() {return Sprite::_Linker;}
 
         private:
-            megu::Sprite _sprite;
-
             std::map<std::string, Frame_List> _frames;
             std::string _animation;
             size_t _index;
+            double _duration;
+           double _previous;
 
             static GraphicLinker<megu::Sprite> _Linker;
     };
diff --git a/source/kernel/front/component/graphic/TileMap.cpp b/source/kernel/front/component/graphic/TileMap.cpp
new file mode 100644
index 0000000..da61dc8
--- /dev/null
+++ b/source/kernel/front/component/graphic/TileMap.cpp
@@ -0,0 +1,64 @@
+#include "TileMap.hpp"
+
+namespace megu::kernel {
+    UniqueGraphicLinker<TileArray> Tilemap::_Linker = UniqueGraphicLinker<TileArray>();
+
+    Tilemap::Tilemap(const std::filesystem::path & path, size_t width, size_t height, float size, size_t lenght) 
+    : TileArray(path, width , height, size), _tileSize(lenght) {
+        if(lenght % width != 0 && lenght % height != 0) {
+            throw std::runtime_error("Tilemap dimension not matching tiles size.");
+        }
+
+        size_t i = 0, j = 0;
+        for(size_t x = 0; x < this->texture().width(); x += this->_tileSize) {
+            j = 0;
+            for(size_t y = 0; y < this->texture().height(); y += this->_tileSize) {
+                this->_tilesPosition.push_back({j * this->_tileSize, i * this->_tileSize});
+                ++j;
+            }
+            ++i;
+        }
+        
+        i = 0;
+        for(size_t x = 0; x < width * this->_tileSize; x += this->_tileSize) {
+            this->_tilesValue.push_back({});
+            for(size_t y = 0; y < height * this->_tileSize; y += this->_tileSize) {
+                this->_tilesValue[i].push_back(0);
+            }
+            ++i;
+        }
+
+        if(!Tilemap::_Linker.haveModule()) {
+           Tilemap::_Linker.setModule(new TileArray_Module{});
+        }
+
+        this->setSize({width * size, height * size});
+    }
+
+    void Tilemap::setValue(size_t x, size_t y, size_t value) {
+        TilePosition position = this->_tilesPosition[value];
+        glm::vec4 uv = {position.x, 
+                        this->texture().height() - position.y - this->_tileSize, 
+                        this->_tileSize, 
+                        this->_tileSize};
+
+        this->setUv(x, this->width() - 1 - y, uv);
+        this->_tilesValue[x][y] = value;
+    }
+
+    size_t Tilemap::getValue(size_t x, size_t y) {
+        if(this->_tilesValue.size() > x && this->_tilesValue[x].size() > y) {
+            return this->_tilesValue[x][y];
+        }
+        throw std::runtime_error("Tilemap coords out of bound");
+    }
+
+    void Tilemap::update(double time) {
+        //... Peut-être des tiles animées si j'ai le temps 🙌 (spoiler non).
+    }
+
+    void Tilemap::apply(Kernel & kernel, GraphicEngine & engine) {
+        Tilemap::_Linker.link(*this, this->getLayerPriority(), this->getObjectPriority());
+        Tilemap::_Linker.link(engine);
+    }
+}
\ No newline at end of file
diff --git a/source/kernel/front/component/graphic/TileMap.hpp b/source/kernel/front/component/graphic/TileMap.hpp
new file mode 100644
index 0000000..3834953
--- /dev/null
+++ b/source/kernel/front/component/graphic/TileMap.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <map>
+#include <vector>
+
+#include <kernel/back/engine/GraphicEngine.hpp>
+#include <kernel/back/props/Graphical.hpp>
+#include <kernel/back/linker/UniqueLinker.hpp>
+
+#include <engine/graphics/front/object/TileArray.hpp>
+#include <engine/graphics/front/module/TileArray_Module.hpp> 
+
+namespace megu::kernel {
+    class Tilemap : public Graphical<GraphicEngine>, public TileArray {
+        public:
+            struct TilePosition {
+                size_t x = 0;
+                size_t y = 0;
+
+                friend bool operator<(const TilePosition & p1, const TilePosition & p2) {
+                    if(p1.x == p2.x) {
+                        return p1.y < p2.y;
+                    }
+                    return p1.x < p1.y;
+                }
+            };
+
+            Tilemap(const std::filesystem::path &, size_t, size_t, float, size_t);
+
+            void setValue(size_t, size_t, size_t);
+            size_t getValue(size_t, size_t);
+
+            void update(double) override;
+            void apply(Kernel &, GraphicEngine &) override;
+
+        private:
+            std::vector<TilePosition> _tilesPosition;
+            std::vector<std::vector<size_t>> _tilesValue;
+            TileArray_Module _module;
+            size_t _tileSize;
+
+            static UniqueGraphicLinker<TileArray> _Linker;
+    };
+}
\ No newline at end of file
diff --git a/source/kernel/front/resolver/GraphicResolver.cpp b/source/kernel/front/resolver/GraphicResolver.cpp
index 5c7c574..a436473 100644
--- a/source/kernel/front/resolver/GraphicResolver.cpp
+++ b/source/kernel/front/resolver/GraphicResolver.cpp
@@ -3,7 +3,10 @@
 namespace megu::kernel {
     void GraphicResolver::resolve(double time, GraphicEngine &, const Identifiable_Map<Props> & props) {
         for(auto & [id, object] : props) {
-            object->getGraphicComponent().update(time);
+            auto * component =  object->getGraphicComponent();
+            if(component != nullptr) {
+                component->update(time);
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/source/kernel/front/resolver/PhysicResolver.cpp b/source/kernel/front/resolver/PhysicResolver.cpp
index 2c90527..81ed40e 100644
--- a/source/kernel/front/resolver/PhysicResolver.cpp
+++ b/source/kernel/front/resolver/PhysicResolver.cpp
@@ -11,7 +11,14 @@ namespace megu::kernel {
             if(props.contains(source.id()) && props.contains(target.id())) {
                 Props * props_source = props.at(source.id()); 
                 Props * props_target = props.at(target.id());
-                props_source->getPhysicComponent().on_collide(time, target, props_target->getPhysicComponent());
+
+                auto * sComponent = props_source->getPhysicComponent();
+                auto * tComponent = props_target->getPhysicComponent();
+
+                if(sComponent != nullptr && tComponent != nullptr) {
+                    sComponent->on_collide(time, target, *tComponent);
+                }
+                
             }
         }
 
-- 
GitLab