From 55c8a14a7e2b2dadf0def3e09f970818164366f5 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 18 Jun 2015 12:14:05 -0400 Subject: Now displaying player character --- CMakeLists.txt | 4 + src/algorithms.h | 12 +++ src/components/sprite_renderable.cpp | 27 ++++++ src/components/sprite_renderable.h | 25 ++++++ src/components/transformable.cpp | 47 ++++++++++ src/components/transformable.h | 27 ++++++ src/entity_manager.cpp | 38 ++++++++ src/entity_manager.h | 169 +++++------------------------------ src/main.cpp | 25 +++++- src/system.h | 11 +++ src/systems/rendering.cpp | 21 +++++ src/systems/rendering.h | 16 ++++ 12 files changed, 270 insertions(+), 152 deletions(-) create mode 100644 src/algorithms.h create mode 100644 src/components/sprite_renderable.cpp create mode 100644 src/components/sprite_renderable.h create mode 100644 src/components/transformable.cpp create mode 100644 src/components/transformable.h create mode 100644 src/entity_manager.cpp create mode 100644 src/system.h create mode 100644 src/systems/rendering.cpp create mode 100644 src/systems/rendering.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dfce6f..2bfde77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,10 @@ add_executable(Aromatherapy src/main.cpp src/renderer.cpp src/muxer.cpp + src/entity_manager.cpp + src/components/sprite_renderable.cpp + src/components/transformable.cpp + src/systems/rendering.cpp ) target_link_libraries(Aromatherapy ${ALL_LIBS}) install(TARGETS Aromatherapy RUNTIME DESTINATION ${BIN_DIR}) diff --git a/src/algorithms.h b/src/algorithms.h new file mode 100644 index 0000000..80e3e27 --- /dev/null +++ b/src/algorithms.h @@ -0,0 +1,12 @@ +#ifndef ALGORITHMS_H_1DDC517E +#define ALGORITHMS_H_1DDC517E + +template< typename ContainerT, typename PredicateT > +void erase_if( ContainerT& items, const PredicateT& predicate ) { + for( auto it = items.begin(); it != items.end(); ) { + if( predicate(*it) ) it = items.erase(it); + else ++it; + } +}; + +#endif /* end of include guard: ALGORITHMS_H_1DDC517E */ diff --git a/src/components/sprite_renderable.cpp b/src/components/sprite_renderable.cpp new file mode 100644 index 0000000..4c61111 --- /dev/null +++ b/src/components/sprite_renderable.cpp @@ -0,0 +1,27 @@ +#include "sprite_renderable.h" + +SpriteRenderableComponent::SpriteRenderableComponent(const char* filename, int frame_width, int frame_height, int frames_across) + : texture(filename), frame_width(frame_width), frame_height(frame_height), frames_across(frames_across) +{ + +} + +int SpriteRenderableComponent::getFrame() const +{ + return frame; +} + +void SpriteRenderableComponent::setFrame(int frame) +{ + this->frame = frame; +} + +const Texture& SpriteRenderableComponent::getTexture() const +{ + return texture; +} + +Rectangle SpriteRenderableComponent::getFrameRect() const +{ + return {frame_width * (frame % frames_across), frame_height * (frame / frames_across), frame_width, frame_height}; +} diff --git a/src/components/sprite_renderable.h b/src/components/sprite_renderable.h new file mode 100644 index 0000000..b4465c3 --- /dev/null +++ b/src/components/sprite_renderable.h @@ -0,0 +1,25 @@ +#ifndef SPRITE_RENDERABLE_H_D3AACBBF +#define SPRITE_RENDERABLE_H_D3AACBBF + +#include "component.h" +#include "renderer.h" + +class SpriteRenderableComponent : public Component { + public: + SpriteRenderableComponent(const char* filename, int frame_width, int frame_height, int frames_across); + + int getFrame() const; + void setFrame(int frame); + + const Texture& getTexture() const; + Rectangle getFrameRect() const; + + private: + Texture texture; + int frame_width; + int frame_height; + int frames_across; + int frame = 0; +}; + +#endif /* end of include guard: SPRITE_RENDERABLE_H_D3AACBBF */ diff --git a/src/components/transformable.cpp b/src/components/transformable.cpp new file mode 100644 index 0000000..0d6b67e --- /dev/null +++ b/src/components/transformable.cpp @@ -0,0 +1,47 @@ +#include "transformable.h" + +TransformableComponent::TransformableComponent(double x, double y, int w, int h) + : x(x), y(y), w(w), h(h) +{ + +} + +double TransformableComponent::getX() const +{ + return x; +} + +double TransformableComponent::getY() const +{ + return y; +} + +int TransformableComponent::getW() const +{ + return w; +} + +int TransformableComponent::getH() const +{ + return h; +} + +void TransformableComponent::setX(double v) +{ + x = v; +} + +void TransformableComponent::setY(double v) +{ + y = v; +} + +void TransformableComponent::setW(int v) +{ + w = v; +} + +void TransformableComponent::setH(int v) +{ + h = v; +} diff --git a/src/components/transformable.h b/src/components/transformable.h new file mode 100644 index 0000000..87ba84d --- /dev/null +++ b/src/components/transformable.h @@ -0,0 +1,27 @@ +#ifndef LOCATABLE_H_39E526CA +#define LOCATABLE_H_39E526CA + +#include "component.h" + +class TransformableComponent : public Component { + public: + TransformableComponent(double x, double y, int w, int h); + + double getX() const; + double getY() const; + int getW() const; + int getH() const; + + void setX(double v); + void setY(double v); + void setW(int v); + void setH(int v); + + private: + double x; + double y; + int w; + int h; +}; + +#endif /* end of include guard: LOCATABLE_H_39E526CA */ diff --git a/src/entity_manager.cpp b/src/entity_manager.cpp new file mode 100644 index 0000000..4bdfe8a --- /dev/null +++ b/src/entity_manager.cpp @@ -0,0 +1,38 @@ +#ifndef ENTITY_MANAGER_CPP_42D78C22 +#define ENTITY_MANAGER_CPP_42D78C22 + +#include "entity_manager.h" + +template <> +std::set EntityManager::getEntitiesWithComponents<>(std::set& componentTypes) +{ + if (cachedComponents.count(componentTypes) == 1) + { + return cachedComponents[componentTypes]; + } + + std::set& cache = cachedComponents[componentTypes]; + for (auto& entity : entities) + { + EntityData& data = entity.second; + bool cacheEntity = true; + + for (auto& componentType : componentTypes) + { + if (data.components.count(componentType) == 0) + { + cacheEntity = false; + break; + } + } + + if (cacheEntity) + { + cache.insert(entity.first); + } + } + + return cache; +} + +#endif /* end of include guard: ENTITY_MANAGER_CPP_42D78C22 */ diff --git a/src/entity_manager.h b/src/entity_manager.h index 74e758c..5f0f2d4 100644 --- a/src/entity_manager.h +++ b/src/entity_manager.h @@ -6,70 +6,31 @@ #include #include #include "component.h" +#include "algorithms.h" class EntityManager { private: struct EntityData { - int parent = -1; std::map> components; }; std::map entities; - std::map> cachedChildren; std::map, std::set> cachedComponents; int nextEntityID = 0; - bool ensureNoParentCycles(int entity, int parent) + template + std::set getEntitiesWithComponentsHelper(std::set& componentTypes) { - EntityData& data = entities[parent]; - if (data.parent == entity) - { - return false; - } else if (data.parent == -1) - { - return true; - } + componentTypes.insert(typeid(T)); - return ensureNoParentCycles(entity, data.parent); + return getEntitiesWithComponents(componentTypes); } + template std::set getEntitiesWithComponents(std::set& componentTypes) { - if (cachedComponents.count(componentTypes) == 1) - { - return cachedComponents[componentTypes]; - } - - std::set& cache = cachedComponents[componentTypes]; - for (auto& entity : entities) - { - EntityData& data = entity.second; - bool cacheEntity = true; - - for (auto& componentType : componentTypes) - { - if (data.components.count(componentType) == 0) - { - cacheEntity = false; - break; - } - } - - if (cacheEntity) - { - cache.insert(entity.first); - } - } - - return cache; - } - - template std::set getEntitiesWithComponents(std::set& componentTypes) - { - componentTypes.insert(typeid(T)); - - return getEntitiesWithComponents(componentTypes); + return getEntitiesWithComponentsHelper(componentTypes); } public: @@ -107,26 +68,6 @@ class EntityManager { { assert(entities.count(entity) == 1); - EntityData& data = entities[entity]; - - // Destroy the children - std::set children = getChildren(entity); - for (int child : children) - { - EntityData& childData = entities[child]; - childData.parent = -1; - - deleteEntity(child); - } - - // Uncache children - cachedChildren.erase(entity); - - if ((data.parent != -1) && (cachedChildren.count(data.parent) == 1)) - { - cachedChildren[data.parent].erase(entity); - } - // Uncache components for (auto& cache : cachedComponents) { @@ -137,81 +78,8 @@ class EntityManager { entities.erase(entity); } - std::set getChildren(int parent) - { - assert(entities.count(parent) == 1); - - if (cachedChildren.count(parent) == 1) - { - return cachedChildren[parent]; - } - - std::set& cache = cachedChildren[parent]; - for (auto& entity : entities) - { - EntityData& data = entity.second; - if (data.parent == parent) - { - cache.insert(entity.first); - } - } - - return cache; - } - - void setParent(int entity, int parent) - { - assert(entities.count(entity) == 1); - assert(entities.count(parent) == 1); - assert(ensureNoParentCycles(entity, parent)); - - EntityData& data = entities[entity]; - - // Remove from old parent - if (data.parent != -1) - { - if (cachedChildren.count(data.parent) == 1) - { - cachedChildren[data.parent].erase(entity); - } - } - - data.parent = parent; - - // Cache new parent - if (cachedChildren.count(parent) == 1) - { - cachedChildren[parent].insert(entity); - } - } - - void setNoParent(int entity) - { - assert(entities.count(entity) == 1); - - EntityData& data = entities[entity]; - - // Remove from old parent - if (data.parent != -1) - { - if (cachedChildren.count(data.parent) == 1) - { - cachedChildren[data.parent].erase(entity); - } - } - - data.parent = -1; - } - - int getParent(int entity) - { - assert(entities.count(entity) == 1); - - EntityData& data = entities[entity]; - return data.parent; - } - - template T& emplaceComponent(int entity, Args&&... args) + template + T& emplaceComponent(int entity, Args&&... args) { assert(entities.count(entity) == 1); @@ -226,14 +94,15 @@ class EntityManager { data.components[componentType] = std::move(ptr); // Invalidate related caches - std::remove_if(begin(cachedComponents), end(cachedComponents), [&] (std::pair, int>& cache) { + erase_if(cachedComponents, [&componentType] (std::pair, std::set>& cache) { return cache.first.count(componentType) == 1; }); return component; } - template void removeComponent(int entity) + template + void removeComponent(int entity) { assert(entities.count(entity) == 1); @@ -255,7 +124,8 @@ class EntityManager { } } - template T& getComponent(int entity) + template + T& getComponent(int entity) { assert(entities.count(entity) == 1); @@ -264,16 +134,19 @@ class EntityManager { assert(data.components.count(componentType) == 1); - return *(data.components[componentType]); + return *((T*)data.components[componentType].get()); } - template std::set getEntitiesWithComponents() + template + std::set getEntitiesWithComponents() { std::set componentTypes; - componentTypes.insert(typeid(T)); - return getEntitiesWithComponents(componentTypes); + return getEntitiesWithComponentsHelper(componentTypes); } }; +template <> +std::set EntityManager::getEntitiesWithComponents<>(std::set& componentTypes); + #endif /* end of include guard: ENTITY_MANAGER_H_C5832F11 */ diff --git a/src/main.cpp b/src/main.cpp index 29a364b..dcf8d87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,22 +4,39 @@ #include "renderer.h" #include "muxer.h" #include "entity_manager.h" +#include "components/sprite_renderable.h" +#include "components/transformable.h" +#include "systems/rendering.h" int main() { srand(time(NULL)); GLFWwindow* window = initRenderer(); + glfwSwapInterval(1); + initMuxer(); // Put this in a block so game goes out of scope before we destroy the renderer { EntityManager manager; - int eRef = manager.emplaceEntity(); - int eRef2 = manager.emplaceEntity(); - manager.setParent(eRef, eRef2); - printf("%d\n", manager.getParent(eRef)); + int player = manager.emplaceEntity(); + manager.emplaceComponent(player, "res/Starla.png", 10, 12, 6); + manager.emplaceComponent(player, 203, 44, 10, 12); + + std::list> loop; + loop.push_back(std::unique_ptr(new RenderingSystem())); + + while (!glfwWindowShouldClose(window)) + { + for (auto& sys : loop) + { + sys->tick(manager, 1.0); + } + + glfwPollEvents(); + } } destroyMuxer(); diff --git a/src/system.h b/src/system.h new file mode 100644 index 0000000..85415f0 --- /dev/null +++ b/src/system.h @@ -0,0 +1,11 @@ +#ifndef SYSTEM_H_B61A8CEA +#define SYSTEM_H_B61A8CEA + +class EntityManager; + +class System { + public: + virtual void tick(EntityManager& manager, float dt) = 0; +}; + +#endif /* end of include guard: SYSTEM_H_B61A8CEA */ diff --git a/src/systems/rendering.cpp b/src/systems/rendering.cpp new file mode 100644 index 0000000..0034dc3 --- /dev/null +++ b/src/systems/rendering.cpp @@ -0,0 +1,21 @@ +#include "rendering.h" +#include "entity_manager.h" +#include "components/sprite_renderable.h" +#include "components/transformable.h" + +void RenderingSystem::tick(EntityManager& manager, float dt) +{ + texture.fill(texture.entirety(), 0, 0, 0); + + std::set spriteEntities = manager.getEntitiesWithComponents(); + for (int entity : spriteEntities) + { + auto& sprite = manager.getComponent(entity); + auto& transform = manager.getComponent(entity); + Rectangle dstrect {(int) transform.getX(), (int) transform.getY(), transform.getW(), transform.getH()}; + + texture.blit(sprite.getTexture(), sprite.getFrameRect(), dstrect); + } + + texture.renderScreen(); +} diff --git a/src/systems/rendering.h b/src/systems/rendering.h new file mode 100644 index 0000000..80ea79e --- /dev/null +++ b/src/systems/rendering.h @@ -0,0 +1,16 @@ +#ifndef RENDERING_H_76ABC02A +#define RENDERING_H_76ABC02A + +#include "system.h" +#include "renderer.h" +#include "consts.h" + +class RenderingSystem : public System { + public: + void tick(EntityManager& manager, float dt); + + private: + Texture texture {GAME_WIDTH, GAME_HEIGHT}; +}; + +#endif /* end of include guard: RENDERING_H_76ABC02A */ -- cgit 1.4.1