From 4444fdb3af85250b48fa84d6bab549860cb306eb Mon Sep 17 00:00:00 2001 From: Jerboa-app Date: Sat, 10 Aug 2024 09:06:54 +0100 Subject: [PATCH 1/5] Adds cSprite, sprite rendering and documents --- include/Component/cRenderable.h | 7 +- include/Component/cSprite.h | 39 ++++++ include/Object/entityComponentSystem.h | 167 ++++++++++++++--------- include/System/Rendering/sRender.h | 75 +++++++--- include/System/systemManager.h | 41 ++++-- include/Util/assetStore.h | 105 +++++++++++--- include/constants.h | 20 +++ src/Object/LuaBindings/lua_objectIO.cpp | 45 ++++-- src/Object/LuaBindings/lua_textureIO.cpp | 99 ++++++++++++++ src/Object/entityComponentSystem.cpp | 23 +--- src/System/Rendering/sRender.cpp | 37 ++++- src/System/systemManager.cpp | 10 -- 12 files changed, 519 insertions(+), 149 deletions(-) create mode 100644 include/Component/cSprite.h create mode 100644 include/constants.h create mode 100644 src/Object/LuaBindings/lua_textureIO.cpp diff --git a/include/Component/cRenderable.h b/include/Component/cRenderable.h index 6e1fda7c..f326d5df 100644 --- a/include/Component/cRenderable.h +++ b/include/Component/cRenderable.h @@ -6,7 +6,7 @@ namespace Hop::Object::Component { - struct cRenderable + struct cRenderable { // offset in transform @@ -19,7 +19,7 @@ namespace Hop::Object::Component // atlas coord float ux; float uy; - + // extra? float vx; float vy; @@ -53,7 +53,7 @@ namespace Hop::Object::Component {} cRenderable( - std::string shader, + std::string shader, float r, float g, float b, float a, float ua, float ub, float uc, float ud, uint64_t p = 0 @@ -75,7 +75,6 @@ namespace Hop::Object::Component priority(p), shaderHandle(""),stale(true) {} - }; } diff --git a/include/Component/cSprite.h b/include/Component/cSprite.h new file mode 100644 index 00000000..cbc0e7cf --- /dev/null +++ b/include/Component/cSprite.h @@ -0,0 +1,39 @@ +#ifndef CSPRITE_H +#define CSPRITE_H + +#include +#include + +namespace Hop::Object::Component +{ + /** + * @brief A sprite component. + * Represents a relative path to a texture asset, and a rectangular + * region of the texture to draw (in pixel units). + */ + struct cSprite + { + + cSprite() + : texturePath(""), tx(0), ty(0), lx(0), ly(0) + {} + + cSprite + ( + std::string path, + u_int16_t tx, + u_int16_t ty, + u_int16_t lx, + u_int16_t ly + ) + : texturePath(path), tx(tx), ty(ty), lx(lx), ly(ly) + {} + + std::string texturePath; + uint16_t tx; + uint16_t ty; + uint16_t lx; + uint16_t ly; + }; +} +#endif /* CSPRITE_H */ diff --git a/include/Object/entityComponentSystem.h b/include/Object/entityComponentSystem.h index 0cc6f46f..aeb5eba2 100644 --- a/include/Object/entityComponentSystem.h +++ b/include/Object/entityComponentSystem.h @@ -1,6 +1,8 @@ #ifndef ENTITYCOMPONENTSYSTEM_H #define ENTITYCOMPONENTSYSTEM_H +#include + #include #include @@ -33,7 +35,7 @@ #include using namespace std::chrono; -namespace Hop +namespace Hop { class Console; } @@ -58,7 +60,7 @@ namespace Hop::Object { using namespace Hop::Object::Component; - + using namespace Hop::System; using Hop::System::Physics::sPhysics; using Hop::System::Physics::sCollision; @@ -66,48 +68,45 @@ namespace Hop::Object using Hop::System::Sound::sSound; using Hop::Console; - - /* - Stores an unordered map of objects that can be added to - and removed from - - Objects are associated with a string identity, which can be - the string form of Object/id.h or a user provided handle - subject to a uniqueness check - - Object dynamics is step by step(delta), and drawing - is dispatched with draw(debug) - - Callback is calle on collisions, can be user specified with - user logic, e.g: - "if collision between player and power up call player.collectPowerUp() and powerUp.delete()" - */ - - // define CollisionCallback as this func ptr - typedef void (*CollisionCallback)(Id & i, Id & j); - void identityCallback(Id & i, Id & j); - - const uint32_t MAX_OBJECTS = 100000; - - class EntityComponentSystem + /** + * @brief Stores objects (identity) dynamic components and systems. + * @remark An object is associated with a unique Id. + * @remark Components can be dynamically added, removed, and modified. + */ + class EntityComponentSystem { public: - EntityComponentSystem( - void (*callback)(Id & i, Id & j) = &identityCallback - ) - : collisionCallback(callback), - nextComponentIndex(0) + /** + * @brief Construct a new EntityComponentSystem + * + * @remark Constructs an default ECS with all Hop components and systems. + */ + EntityComponentSystem() + : nextComponentIndex(0) { initialiseBaseECS(); objects.clear(); } Id createObject(); + + /** + * @brief Create a Object returning its id and associating a user defined string name. + * + * @param handle user defined alias. + * @return Id the objects unique id. + */ Id createObject(std::string handle); void remove(Id id); + + /** + * @brief Remove an object by the users alias. + * + * @param handle user defined alias. + */ void remove(std::string handle); bool handleExists(std::string handle) const { return handleToId.find(handle) != handleToId.cend(); } @@ -119,10 +118,13 @@ namespace Hop::Object const std::unordered_map> & getObjects() { return objects; } - CollisionCallback collisionCallback; - // component interface + /** + * @brief Register a new component. + * + * @tparam T the component class to register. + */ template void registerComponent() { @@ -141,9 +143,15 @@ namespace Hop::Object registeredComponents[handle] = nextComponentIndex; nextComponentIndex++; componentData[handle] = std::make_shared>(MAX_OBJECTS); - } + /** + * @brief Add a component to an object. + * + * @tparam T the registered component. + * @param i the object Id. + * @param component the component value. + */ template void addComponent(Id i, T component) { @@ -162,6 +170,12 @@ namespace Hop::Object systemManager.objectSignatureChanged(i,idToSignature[i]); } + /** + * @brief Remove a component from an object. + * + * @tparam T the registered component class. + * @param i the object Id to remove from. + */ template void removeComponent(Id i) { @@ -180,54 +194,78 @@ namespace Hop::Object systemManager.objectSignatureChanged(i,idToSignature[i]); } + /** + * @brief Get a Component for an object. + * + * @tparam T the component class. + * @param i the object Id to get the component T from. + * @return T& the component values for the object Id; + */ template inline T & getComponent(const Id & i) { const char * handle = typeid(T).name(); - - // if (!componentRegistered(handle)){ - // throw ComponentNotRegistered(" Attempt to getComponent<"+i.idStr+")"); - // } return (std::static_pointer_cast>(componentData[handle]))->get(i); } - void objectFreed(Id i) - { - for (auto const& pair : componentData) - { - pair.second.get()->objectFreed(i); - } - } - - template - uint32_t getComponentId() - { - const char * handle = typeid(T).name(); - return registeredComponents[handle]; - } - // system interface + + /** + * @brief Register a class T as a new system. + * + * @tparam T the class to register. + */ template void registerSystem(){systemManager.registerSystem();} + /** + * @brief Set the Signature for the system T + * + * @tparam T the registered system class. + * @param signature the new Signature. + */ template void setSystemSignature(Signature signature){systemManager.setSignature(signature);} + /** + * @brief Get the System T + * + * @tparam T the registered system T to get.. + * @return T& the system. + */ template T & getSystem(){return systemManager.getSystem();} + /** + * @brief Check if the object has the given component. + * + * @tparam T the registered component class. + * @param i the object Id to check. + * @return true i has the component. + * @return false i does not have the component. + */ template bool hasComponent(const Id & i){return idToSignature[i][getComponentId()];} + /** + * @brief Get the full array of component T, as a copy; + * + * @tparam T the registered component + * @return ComponentArray all values of component T. + */ template ComponentArray getComponentArrayCopy() { const char * handle = typeid(T).name(); - return *(std::static_pointer_cast>(componentData[handle])); - } + /** + * @brief Get the full array of component T, as a copy; + * + * @tparam T the registered component + * @return ComponentArray & all values of component T. + */ template ComponentArray & getComponentArray() { @@ -237,14 +275,11 @@ namespace Hop::Object } - template - void updateMainComponents(); - // Lua bindings int lua_loadObject(lua_State * lua); int lua_deleteObject(lua_State * lua); - + int lua_getTransform(lua_State * lua); int lua_setTransform(lua_State * lua); @@ -255,6 +290,12 @@ namespace Hop::Object int lua_getColour(lua_State * lua); int lua_setColour(lua_State * lua); + int lua_setTextureRegion(lua_State * lua); + int lua_getTextureRegion(lua_State * lua); + + int lua_setTexturePath(lua_State * lua); + int lua_getTexturePath(lua_State * lua); + private: @@ -266,8 +307,6 @@ namespace Hop::Object void initialiseBaseECS(); - // components - bool componentRegistered(const char * h){return registeredComponents.find(h)!=registeredComponents.end();} uint32_t nextComponentIndex; @@ -276,6 +315,12 @@ namespace Hop::Object std::unordered_map> componentData; + template + uint32_t getComponentId() + { + const char * handle = typeid(T).name(); + return registeredComponents[handle]; + } }; } diff --git a/include/System/Rendering/sRender.h b/include/System/Rendering/sRender.h index d0f6fe34..b9ef1304 100644 --- a/include/System/Rendering/sRender.h +++ b/include/System/Rendering/sRender.h @@ -3,13 +3,18 @@ #include #include +#include #include #include +#include +#include +#include #include #include #include +#include #include @@ -29,25 +34,29 @@ namespace Hop::System::Rendering using jLog::Log; using Hop::World::AbstractWorld; using Hop::Debugging::CollisionMeshDebug; - + using Hop::Util::Assets::TextureAssetStore; + using Hop::Object::Component::ComponentArray; + using Hop::Object::Component::cSprite; + using Hop::Object::Component::cRenderable; + /** + * @brief System to handle rendering. + * + */ class sRender : public System { public: + /** + * @brief Construct a new Renderer. + * + */ sRender() - : accumulatedTime(0.0), - projection(0.0f), + : accumulatedTime(0.0), + projection(0.0f), drawCollisionMeshPoints(false), clock(std::chrono::high_resolution_clock::now()), - collisionMeshDebug(nullptr) - {} - - sRender(std::shared_ptr jgl) - : accumulatedTime(0.0), - projection(0.0f), - drawCollisionMeshPoints(false), - clock(std::chrono::high_resolution_clock::now()), - collisionMeshDebug(std::move(std::make_unique(jgl))) + collisionMeshDebug(nullptr), + textures(nullptr) {} void setProjection(glm::mat4 proj) { projection = proj; } @@ -55,25 +64,53 @@ namespace Hop::System::Rendering double draw ( std::shared_ptr jgl, - EntityComponentSystem * ecs = nullptr, + EntityComponentSystem * ecs = nullptr, AbstractWorld * world = nullptr ); + /** + * @brief Draw debug meshes. + * + * @param b switch to draw debug messhes. + */ void setDrawMeshes(bool b) { drawCollisionMeshPoints = b; } + /** + * @brief Set the TextureAssetStore for the rendering system. + * + * @param textureStore the TextureAssetStore. + * @remark draw will reference textures from here. + */ + void setTextureAssetStore(std::shared_ptr textureStore){ textures = textureStore; } + + /** + * @brief Set the SpriteRenderer for the rendering system. + * + * @param spriteRenderer a jGL::SpriteRenderer. + * @remark draw will reference sprites from here. + */ + void setSpriteRenderer(std::shared_ptr spriteRenderer) { sprites = spriteRenderer; } + + /** + * @brief Update the renderer from the ecs. + * + * @param ecs EntityComponentSystem. + * @remark Currently changes to Hop::Object::Component::cSprite, and Hop::Object::Component::cRenderable + * require updating manually. + * @remark Sprites already track Hop::Object::Component::cTransform. + */ + void update(EntityComponentSystem * ecs); + private: double accumulatedTime; glm::mat4 projection; - bool drawCollisionMeshPoints; - std::chrono::time_point clock; - std::unique_ptr collisionMeshDebug; - - void update(EntityComponentSystem * ecs); - + std::shared_ptr sprites = nullptr; + std::unique_ptr collisionMeshDebug = nullptr; + std::shared_ptr textures = nullptr; }; } diff --git a/include/System/systemManager.h b/include/System/systemManager.h index 55ed575b..c4ccea8e 100644 --- a/include/System/systemManager.h +++ b/include/System/systemManager.h @@ -1,7 +1,9 @@ #ifndef SYSTEMMANAGER_H #define SYSTEMMANAGER_H +#include #include + #include #include #include @@ -9,11 +11,9 @@ namespace Hop::System { - - const uint32_t MAX_COMPONENTS = 64; typedef std::bitset Signature; - class SystemNotRegistered: public std::exception + class SystemNotRegistered: public std::exception { public: @@ -33,14 +33,23 @@ namespace Hop::System }; - - class SystemManager + /** + * @brief Registers and manages systems signatures. + * + */ + class SystemManager { public: SystemManager(){} + /** + * @brief Register T as a system. + * + * @tparam T the system class. + * @remark Gives T the catch all Signature. + */ template void registerSystem() { @@ -55,6 +64,12 @@ namespace Hop::System systems[handle] = s; } + /** + * @brief Set the Signature for system T. + * + * @tparam T the registered System class. + * @param signature object Signature. + */ template void setSignature(Signature signature) { @@ -67,6 +82,12 @@ namespace Hop::System signatures[handle] = signature; } + /** + * @brief Return the given system T. + * + * @tparam T the registered system class. + * @return T& the system object. + */ template T & getSystem() { @@ -79,11 +100,15 @@ namespace Hop::System return *(std::static_pointer_cast(systems[handle]).get()); } - void objectFreed(Id i); - + /** + * @brief Refresh object i's Signature. + * + * @param i Id of the changed object. + * @param s the new Signature. + */ void objectSignatureChanged(Id i, Signature s); - + private: bool isRegistered(const char * s){return systems.find(s) != systems.end();} diff --git a/include/Util/assetStore.h b/include/Util/assetStore.h index 3da7c380..81bf6b9c 100644 --- a/include/Util/assetStore.h +++ b/include/Util/assetStore.h @@ -11,16 +11,32 @@ namespace Hop::Util::Assets { + /** + * @brief A data store for a general asset T. + * + * @tparam T type of the asset. + * @remark Assets are loading from relative paths to a supplied root, seet AssetStore::AssetStore. + */ template - class AssetStore + class AssetStore { public: + /** + * @brief Construct a new AssetStore. + * + * @param root the relative path for all assets. + */ AssetStore(std::filesystem::path root) - : root(root) + : root(root) {} - void scan() + /** + * @brief Caches all matching asset paths relative to root. + * @remark Specialised AssetStores overloads a method to check if a path is an asset of type T. + * This is done by file extensions (.png, .mp3, ...). + */ + void scan() { if (std::filesystem::is_directory(root)) { @@ -28,9 +44,40 @@ namespace Hop::Util::Assets } }; + /** + * @brief Loads the asset at this relative path. + * + * @param assetPath relative path to an asset. + */ virtual void load(std::filesystem::path assetPath) = 0; - std::shared_ptr get(std::filesystem::path relative_path) { return assets[relative_path]; } + /** + * @brief Loads all assets in the asset store. + * @remark Use with scan. + */ + void loadAll() + { + for (const auto & p : assets) + { + load(p); + } + } + + /** + * @brief Return the asset. + * + * @param relative_path path to asset. + * @return std::shared_ptr the asset. + * @remark Will attempt to load an unloaded asset. + */ + std::shared_ptr get(std::filesystem::path relative_path) + { + if (assets[relative_path] == nullptr) + { + load(relative_path); + } + return assets[relative_path]; + } typename std::map>::const_iterator begin() { return assets.cbegin(); } typename std::map>::const_iterator end() { return assets.cend(); } @@ -47,7 +94,7 @@ namespace Hop::Util::Assets { if (entry.is_regular_file()) { - if (matchesAssetType(entry)) { load(entry); } + if (matchesAssetType(entry) && assets.find(entry) == assets.end()) { assets[entry] = nullptr; } } else { @@ -57,30 +104,54 @@ namespace Hop::Util::Assets } }; + /** + * @brief AssetStore specialisation to store texture assets. + * + */ class TextureAssetStore : public AssetStore { public: - TextureAssetStore(std::filesystem::path root, std::unique_ptr & instance) + /** + * @brief Construct a new TextureAssetStore + * + * @param root relative path for textures. + * @param instance jGLInstance for creating textures. + * @remark Currently supports .png, .jpg files. + */ + TextureAssetStore(std::filesystem::path root, std::shared_ptr & instance) : AssetStore(root), instance(instance) {} - void load(std::filesystem::path assetPath) + /** + * @brief Load a texture. + * + * @param assetPath path relative to root. + */ + void load(std::filesystem::path assetPath) { - std::filesystem::path relative = std::filesystem::relative(assetPath, root); - assets[relative] = instance->createTexture - ( - assetPath.generic_string(), - jGL::Texture::Type::RGBA - ); + if (matchesAssetType(assetPath)) + { + std::filesystem::path relative = std::filesystem::relative(assetPath, root); + assets[relative] = instance->createTexture + ( + assetPath.generic_string(), + jGL::Texture::Type::RGBA + ); + } }; + /** + * @brief Supported texture extension. + * @remark These will be loaded as RGBA textures. + */ + const std::vector extensions = {".png, .jpg"}; + protected: - std::unique_ptr & instance; + std::shared_ptr & instance; - bool matchesAssetType(std::filesystem::path file) - { - static std::vector extensions = {".png"}; + bool matchesAssetType(std::filesystem::path file) + { return std::find(extensions.begin(), extensions.end(), file.extension().generic_string()) != extensions.end(); } }; diff --git a/include/constants.h b/include/constants.h new file mode 100644 index 00000000..c1ad6c9c --- /dev/null +++ b/include/constants.h @@ -0,0 +1,20 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#include + +namespace Hop +{ + /** + * @brief Maximum objects in the Hop::Object::EntityComponentSystem. + * + */ + const uint32_t MAX_OBJECTS = 100000; + /** + * @brief Maximum components in the Hop::Object::EntityComponentSystem. + * + */ + const uint32_t MAX_COMPONENTS = 64; +}; + +#endif /* CONSTANTS_H */ diff --git a/src/Object/LuaBindings/lua_objectIO.cpp b/src/Object/LuaBindings/lua_objectIO.cpp index 50721789..8cd26707 100644 --- a/src/Object/LuaBindings/lua_objectIO.cpp +++ b/src/Object/LuaBindings/lua_objectIO.cpp @@ -7,6 +7,8 @@ ["transform"] = {x,y,0.0,1.0}, ["colour"] = {200/255,200/255,250/255,1.0}, + ["texturePath"] = "some/relative/path/to.png", + ["textureRegion"] = {0, 0, 16, 16}, ["shader"] = "circleObjectShader", ["moveable"] = false, ["collisionMesh"] = @@ -61,12 +63,12 @@ namespace Hop::Object int EntityComponentSystem::lua_loadObject(lua_State * lua) { - LuaArray<4> colour, transform, util; + LuaArray<4> colour, transform, util, textureRegion; LuaArray<3> meshParameters; LuaNumber transDrag, rotDrag, bodyMass, bodyInertia, bodyFriction, priority; - LuaString shader, name; + LuaString shader, name, texturePath; LuaBool isMoveable, isGhost; @@ -74,6 +76,8 @@ namespace Hop::Object bool hasColour = false; bool hasTransform = false; + bool hasTexture = false; + bool hasTextureRegion = false; bool isRenderable = false; bool isPhysics = false; @@ -93,7 +97,7 @@ namespace Hop::Object // elements on stack int n = lua_gettop(lua); - + if (!lua_istable(lua,1)) { lua_pushliteral(lua,"non table argument"); @@ -111,14 +115,13 @@ namespace Hop::Object if (hasTransform && hasColour) { isRenderable = true; } shader.readField(lua, "shader"); - + hasTextureRegion = textureRegion.readField(lua, "textureRegion"); + hasTexture = texturePath.readField(lua, "texturePath"); priority.readField(lua, "renderPriority"); isMoveable.readField(lua, "moveable"); isGhost.readField(lua, "ghost"); - isPhysics = collisionMesh.readField(lua, "collisionMesh"); - meshParameters.readField(lua, "meshParameters"); name.readField(lua, "name"); @@ -132,7 +135,7 @@ namespace Hop::Object // now create the object Id pid; - + if (name.characters != "") { pid = createObject(name.characters); @@ -191,7 +194,7 @@ namespace Hop::Object ub = param[1]; uc = param[2]; ud = param[3]; - + } else if (returnType == LUA_TNONE || returnType == LUA_TNIL) { @@ -199,7 +202,6 @@ namespace Hop::Object } lua_pop(lua,1); - } addComponent @@ -207,6 +209,30 @@ namespace Hop::Object pid, cRenderable(shader.characters,r,g,b,a,ua,ub,uc,ud,priority.n) ); + + if (hasTexture) + { + jGL::TextureRegion region; + if (hasTextureRegion) + { + region.tx = textureRegion.elements[0]; + region.ty = textureRegion.elements[1]; + region.lx = textureRegion.elements[2]; + region.ly = textureRegion.elements[3]; + } + + addComponent + ( + pid, + cSprite( + texturePath.characters, + region.tx, + region.ty, + region.lx, + region.ty + ) + ); + } } if (isPhysics) @@ -220,7 +246,6 @@ namespace Hop::Object cPhysics & data = getComponent(pid); data.isMoveable = isMoveable.bit; data.isGhost = isGhost.bit; - if (collisionMesh.size() > 0) { diff --git a/src/Object/LuaBindings/lua_textureIO.cpp b/src/Object/LuaBindings/lua_textureIO.cpp new file mode 100644 index 00000000..121582d6 --- /dev/null +++ b/src/Object/LuaBindings/lua_textureIO.cpp @@ -0,0 +1,99 @@ +#include +#include + +#include + +namespace Hop::Object +{ + using Hop::Object::Component::cSprite; + + int EntityComponentSystem::lua_setTextureRegion(lua_State * lua) + { + LuaString sid; + LuaNumber tx, ty, lx, ly; + + int n = lua_gettop(lua); + if (n != 5) + { + lua_pushliteral(lua,"expected id, tx, ty, lx, ly as argument"); + return lua_error(lua); + } + + sid.read(lua, 1); + + Id id(sid.characters); + cSprite & s = getComponent(id); + tx.read(lua, 2); + ty.read(lua, 3); + lx.read(lua, 4); + ly.read(lua, 5); + + s.tx = tx; + s.ty = ty; + s.lx = lx; + s.ly = ly; + + return 0; + } + + int EntityComponentSystem::lua_getTextureRegion(lua_State * lua) + { + LuaString sid; + + int n = lua_gettop(lua); + if (n != 1) + { + lua_pushliteral(lua,"expected id as argument"); + return lua_error(lua); + } + + sid.read(lua, 1); + + Id id(sid.characters); + const cSprite & s = getComponent(id); + lua_pushnumber(lua, s.tx); + lua_pushnumber(lua, s.ty); + lua_pushnumber(lua, s.lx); + lua_pushnumber(lua, s.ly); + return 4; + } + + int EntityComponentSystem::lua_setTexturePath(lua_State * lua) + { + LuaString sid, path; + + int n = lua_gettop(lua); + if (n != 2) + { + lua_pushliteral(lua,"expected id and path as argument"); + return lua_error(lua); + } + + sid.read(lua, 1); + path.read(lua, 2); + + Id id(sid.characters); + cSprite & s = getComponent(id); + s.texturePath = path; + return 0; + } + + int EntityComponentSystem::lua_getTexturePath(lua_State * lua) + { + LuaString sid; + + int n = lua_gettop(lua); + if (n != 1) + { + lua_pushliteral(lua,"expected id as argument"); + return lua_error(lua); + } + + sid.read(lua, 1); + + Id id(sid.characters); + const cSprite & s = getComponent(id); + lua_pushstring(lua, s.texturePath.c_str()); + return 1; + } +} diff --git a/src/Object/entityComponentSystem.cpp b/src/Object/entityComponentSystem.cpp index ba61dba1..65a0b30c 100644 --- a/src/Object/entityComponentSystem.cpp +++ b/src/Object/entityComponentSystem.cpp @@ -7,8 +7,6 @@ namespace Hop::Object std::shared_ptr o = std::make_shared(); objects[o->id] = o; idToSignature[o->id] = Signature(); - //handleToId[Hop::Object::to_string(o->id)] = o->id; - return o->id; } @@ -18,9 +16,7 @@ namespace Hop::Object objects[o->id] = o; idToSignature[o->id] = Signature(); - handleToId[handle] = o->id; - return o->id; } @@ -48,14 +44,12 @@ namespace Hop::Object void EntityComponentSystem::remove(std::string handle){} - // do nothing callback - void identityCallback(Id & i, Id & j){return;} - void EntityComponentSystem::initialiseBaseECS() { registerComponent(); registerComponent(); + registerComponent(); registerComponent(); registerComponent(); //registerComponent(); @@ -74,23 +68,19 @@ namespace Hop::Object uint32_t soundId = getComponentId(); Signature sRenderSig = Signature(); - sRenderSig.set ( rId, true ); - sRenderSig.set ( tId, true ); - systemManager.setSignature(sRenderSig); Signature sPhysicsSig = Signature(); - sPhysicsSig.set ( pId, @@ -101,11 +91,9 @@ namespace Hop::Object tId, true ); - systemManager.setSignature(sPhysicsSig); - - Signature sCollisionSig = Signature(); + Signature sCollisionSig = Signature(); sCollisionSig.set ( pId, @@ -116,19 +104,15 @@ namespace Hop::Object cId, true ); - systemManager.setSignature(sCollisionSig); Signature sSoundSig = Signature(); - sSoundSig.set ( soundId, true ); - systemManager.setSignature(sSoundSig); - } } @@ -137,4 +121,5 @@ namespace Hop::Object #include #include #include -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/src/System/Rendering/sRender.cpp b/src/System/Rendering/sRender.cpp index a17a2fb2..a4490078 100644 --- a/src/System/Rendering/sRender.cpp +++ b/src/System/Rendering/sRender.cpp @@ -5,7 +5,7 @@ namespace Hop::System::Rendering double sRender::draw ( std::shared_ptr jgl, - EntityComponentSystem * ecs, + EntityComponentSystem * ecs, AbstractWorld * world ) { @@ -25,6 +25,8 @@ namespace Hop::System::Rendering collisionMeshDebug->drawMeshes(ecs, projection); } + sprites->draw(); + auto t = std::chrono::high_resolution_clock::now(); accumulatedTime += std::chrono::duration_cast>(t-clock).count(); clock = t; @@ -34,5 +36,38 @@ namespace Hop::System::Rendering void sRender::update(EntityComponentSystem * ecs) { + ComponentArray & spriteComponents = ecs->getComponentArray(); + ComponentArray & renderables = ecs->getComponentArray(); + for (const auto & object : objects) + { + if (renderables.hasComponent(object) && spriteComponents.hasComponent(object)) + { + const cSprite & oSprite = spriteComponents.get(object); + const cRenderable & oRenderable = renderables.get(object); + std::string sid = to_string(object); + if (sprites->hasId(sid)) + { + auto & sprite = sprites->getSprite(sid); + auto tex = textures->get(oSprite.texturePath); + if (!(tex->getId() == sprite.texture->getId())) + { + sprites->remove(sid); + sprites->add(sprite, sid, oRenderable.priority); + } + sprites->updatePriority(sid, oRenderable.priority); + sprite.setAlpha(oRenderable.a); + sprite.setTextureRegion + ( + jGL::TextureRegion + ( + oSprite.tx, + oSprite.ty, + oSprite.lx, + oSprite.ly + ) + ); + } + } + } } } \ No newline at end of file diff --git a/src/System/systemManager.cpp b/src/System/systemManager.cpp index cc69bc32..2e6f1175 100644 --- a/src/System/systemManager.cpp +++ b/src/System/systemManager.cpp @@ -4,16 +4,6 @@ namespace Hop::System { - - void SystemManager::objectFreed(Id i) - { - for (auto const& pair : systems) - { - auto const& system = pair.second; - system->objects.erase(i); - } - } - void SystemManager::objectSignatureChanged(Id i, Signature es) { for (auto const& pair : systems) From 610e90e9abab94e4a15661510f20a13f481bbf32 Mon Sep 17 00:00:00 2001 From: Jerboa-app Date: Thu, 22 Aug 2024 07:51:46 +0100 Subject: [PATCH 2/5] Fix sprites, add demo --- .github/workflows/release.yml | 44 ++--- .../{build-and-run.yml => run-tests.yml} | 12 +- CMakeLists.txt | 6 +- demo/desktop/CMakeLists.txt | 3 +- demo/desktop/perlinWorld/CMakeLists.txt | 25 ++- .../perlinWorld/{standalone => }/main.cpp | 0 .../perlinWorld/{standalone => }/main.h | 0 demo/desktop/softBodyTetris/CMakeLists.txt | 34 +++- .../softBodyTetris/{standalone => }/main.cpp | 0 .../softBodyTetris/{standalone => }/main.h | 0 .../softBodyTetris/standalone/CMakeLists.txt | 33 ---- .../standalone => sprites}/CMakeLists.txt | 7 +- demo/desktop/sprites/assets/HEART.png | Bin 0 -> 6158 bytes demo/desktop/sprites/assets/Pi.png | Bin 0 -> 2664 bytes demo/desktop/sprites/assets/random.png | Bin 0 -> 2587 bytes demo/desktop/sprites/config.lua | 48 +++++ demo/desktop/sprites/main.cpp | 174 ++++++++++++++++++ demo/desktop/sprites/main.h | 102 ++++++++++ include/Console/console.h | 113 +++++++++--- include/Console/lua.h | 9 + include/System/Rendering/sRender.h | 1 + include/Util/assetStore.h | 36 ++-- include/jGL | 2 +- src/Console/console.cpp | 32 +--- src/Console/lua.cpp | 12 +- src/Object/LuaBindings/lua_meshIO.cpp | 28 +-- src/Object/LuaBindings/lua_objectIO.cpp | 34 ++-- src/Object/LuaBindings/lua_renderableIO.cpp | 20 +- src/Object/LuaBindings/lua_textureIO.cpp | 36 +--- src/Object/LuaBindings/lua_transformIO.cpp | 11 +- src/System/Rendering/sRender.cpp | 52 ++++-- 31 files changed, 626 insertions(+), 248 deletions(-) rename .github/workflows/{build-and-run.yml => run-tests.yml} (94%) rename demo/desktop/perlinWorld/{standalone => }/main.cpp (100%) rename demo/desktop/perlinWorld/{standalone => }/main.h (100%) rename demo/desktop/softBodyTetris/{standalone => }/main.cpp (100%) rename demo/desktop/softBodyTetris/{standalone => }/main.h (100%) delete mode 100644 demo/desktop/softBodyTetris/standalone/CMakeLists.txt rename demo/desktop/{perlinWorld/standalone => sprites}/CMakeLists.txt (77%) create mode 100644 demo/desktop/sprites/assets/HEART.png create mode 100644 demo/desktop/sprites/assets/Pi.png create mode 100644 demo/desktop/sprites/assets/random.png create mode 100644 demo/desktop/sprites/config.lua create mode 100644 demo/desktop/sprites/main.cpp create mode 100644 demo/desktop/sprites/main.h diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 95f2d53a..8e9c6607 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,7 +56,7 @@ jobs: include/vendored/ogg/include/ogg \ include/vendored/sparsehash; do cp -r $inc headers; done - + ls headers - name: pack headers mingw @@ -74,7 +74,7 @@ jobs: with: name: headers path: headers - + - name: build header-mingw artifact uses: actions/upload-artifact@v4 with: @@ -88,7 +88,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: 'recursive' - + - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y build-essential xorg-dev mesa-common-dev libx11-dev libxrandr-dev libgl1-mesa-dev libglu1-mesa-dev libfreetype6-dev libopenal-dev libsndfile1-dev libudev-dev libxinerama-dev libxcursor-dev vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools @@ -96,7 +96,7 @@ jobs: run: | git submodule update --recursive ./build.sh -t -d -r - mkdir linuxbuild + mkdir linuxbuild cp build/libHop.a linuxbuild/libHop-linux-x86_64.a cp build/libjGL.a linuxbuild/libjGL-linux-x86_64.a cp LICENSE* linuxbuild/ @@ -126,7 +126,7 @@ jobs: with: name: demoLinux path: demos.zip - + linuxXwindows: runs-on: ubuntu-22.04 @@ -134,7 +134,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: 'recursive' - + - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y xorg-dev build-essential mesa-common-dev libx11-dev libxrandr-dev libgl1-mesa-dev libglu1-mesa-dev libfreetype6-dev libopenal-dev libsndfile1-dev libudev-dev g++-mingw-w64-x86-64-posix gcc-mingw-w64-x86-64-posix libxinerama-dev libxcursor-dev vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools wine64 @@ -152,7 +152,7 @@ jobs: cp -r build/PerlinWorld demos/ cp build/*.dll demos/PerlinWorld/ cd demos && zip -r ../demos.zip * && cd .. - cp build/*.dll build/TestScriptPack/ + cp build/*.dll build/TestScriptPack/ - name: Tests (wine64) working-directory: ${{github.workspace}}/build @@ -164,7 +164,7 @@ jobs: sudo Xvfb :99 -screen 0 800x600x24 & sleep 5 MESA_GL_VERSION_OVERRIDE=3.3 ctest --output-on-failure --verbose --exclude-regex Vulkan - + - name: buildArtifact uses: actions/upload-artifact@v4 with: @@ -204,7 +204,7 @@ jobs: cp build/libHop.a macosbuild/libHop-macos.a cp build/libjGL.a macosbuild/libjGL-macos.a cp LICENSE* macosbuild/ - + mkdir demos cp -r build/PerlinWorld demos/ cd demos && zip -r ../demos.zip * && cd .. @@ -214,7 +214,7 @@ jobs: # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: MESA_GL_VERSION_OVERRIDE=3.3 ctest --output-on-failure --verbose --exclude-regex Vulkan --exclude-regex assetStore - + - name: buildArtifact uses: actions/upload-artifact@v4 with: @@ -226,11 +226,11 @@ jobs: with: name: demomacos path: demos.zip - + linuxRun: needs: linuxNative runs-on: ubuntu-20.04 - + steps: - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y xvfb x11-apps imagemagick @@ -258,8 +258,7 @@ jobs: sleep 10 xwd -root -silent | convert xwd:- png:screenshot-map.png sleep 5 && kill $PID - - + - name: upload artifact uses: actions/upload-artifact@v4 with: @@ -280,13 +279,13 @@ jobs: - uses: actions/checkout@v4 with: submodules: 'recursive' - + - name: Install dependencies run: | sudo apt-get update && sudo apt-get install -y build-essential mesa-common-dev libx11-dev libxrandr-dev libgl1-mesa-dev libglu1-mesa-dev libfreetype6-dev libopenal-dev libsndfile1-dev libudev-dev vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools wget https://dl.google.com/android/repository/android-ndk-r25c-linux.zip unzip android-ndk-r25c-linux.zip - wget https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip + wget https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip unzip commandlinetools-linux-9477386_latest.zip export ANDROID_SDK_ROOT=~/ mv cmdline-tools latest @@ -297,12 +296,12 @@ jobs: ./cmdline-tools/latest/bin/sdkmanager --install "system-images;android-34;google_apis;x86_64" ./cmdline-tools/latest/bin/sdkmanager "platform-tools" "platforms;android-34" echo no | ./cmdline-tools/latest/bin/avdmanager create avd --name android34 --package "system-images;android-34;google_apis;x86_64" - + - name: build hop run: | git submodule update --recursive ./build.sh -r --android android-ndk-r25c - mkdir androidbuild + mkdir androidbuild cp build/libHop* androidbuild/ cp build/libjGL* androidbuild/ cp LICENSE* androidbuild/ @@ -359,7 +358,6 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 with: submodules: 'true' @@ -396,7 +394,6 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 with: submodules: 'true' @@ -431,7 +428,6 @@ jobs: runs-on: macos-12 steps: - - uses: actions/checkout@v4 with: submodules: 'true' @@ -474,14 +470,14 @@ jobs: needs: [linuxNative, linuxXwindows, linuxXandroid, macosNative, headers] if: github.ref_type == 'tag' runs-on: ubuntu-20.04 - + steps: - name: get linux build uses: actions/download-artifact@v4 with: name: linuxbuild path: linux - + - name: get windows build uses: actions/download-artifact@v4 with: @@ -493,7 +489,7 @@ jobs: with: name: macosbuild path: macos - + - name: get android build uses: actions/download-artifact@v4 with: diff --git a/.github/workflows/build-and-run.yml b/.github/workflows/run-tests.yml similarity index 94% rename from .github/workflows/build-and-run.yml rename to .github/workflows/run-tests.yml index e4e66e9c..f8424759 100644 --- a/.github/workflows/build-and-run.yml +++ b/.github/workflows/run-tests.yml @@ -1,4 +1,4 @@ -name: Hop run tests +name: Hop demos on: pull_request: @@ -10,13 +10,13 @@ jobs: strategy: matrix: - example: [PerlinWorld, SoftBodyTetris, MeshEditor] + example: [PerlinWorld, SoftBodyTetris, Sprites, MeshEditor] steps: - uses: actions/checkout@v3 with: submodules: 'recursive' - + - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y build-essential xorg-dev mesa-common-dev libx11-dev libxrandr-dev libgl1-mesa-dev libglu1-mesa-dev libfreetype6-dev libopenal-dev libsndfile1-dev libudev-dev libxinerama-dev libxcursor-dev xvfb x11-apps vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools @@ -46,16 +46,16 @@ jobs: wineRunTest: if: ${{ github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-22.04 - + strategy: matrix: - example: [PerlinWorld, SoftBodyTetris, MeshEditor] + example: [PerlinWorld, SoftBodyTetris, Sprites, MeshEditor] steps: - uses: actions/checkout@v3 with: submodules: 'recursive' - + - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y xorg-dev build-essential mesa-common-dev libx11-dev libxrandr-dev libgl1-mesa-dev libglu1-mesa-dev libfreetype6-dev libopenal-dev libsndfile1-dev libudev-dev g++-mingw-w64-x86-64-posix gcc-mingw-w64-x86-64-posix libxinerama-dev libxcursor-dev xvfb x11-apps vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools wine64 - name: linux-windows diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b4ff60b..97d2db31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,7 +178,7 @@ IF (TEST_SUITE) file(GLOB TEST_SRC "tests/*.cpp" "src/Maths/*.cpp") include_directories(include "tests/") - add_executable(testSuite + add_executable(testSuite ${TEST_SRC} "src/World/mapFile.cpp" "src/Util/z.cpp" @@ -187,7 +187,7 @@ IF (TEST_SUITE) target_compile_definitions(testSuite PUBLIC GLSL_VERSION="330") target_link_libraries(testSuite zlibstatic stduuid glm) - + include(CTest) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/tests/cmake/) include(Catch) @@ -195,7 +195,7 @@ IF (TEST_SUITE) add_subdirectory("${PROJECT_SOURCE_DIR}/tests/regression") endif() - + ENDIF(TEST_SUITE) endif() diff --git a/demo/desktop/CMakeLists.txt b/demo/desktop/CMakeLists.txt index ebfe92e3..9e68d241 100644 --- a/demo/desktop/CMakeLists.txt +++ b/demo/desktop/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(perlinWorld) -add_subdirectory(softBodyTetris) \ No newline at end of file +add_subdirectory(softBodyTetris) +add_subdirectory(sprites) diff --git a/demo/desktop/perlinWorld/CMakeLists.txt b/demo/desktop/perlinWorld/CMakeLists.txt index 0f490bc4..61b5f825 100644 --- a/demo/desktop/perlinWorld/CMakeLists.txt +++ b/demo/desktop/perlinWorld/CMakeLists.txt @@ -1 +1,24 @@ -add_subdirectory(standalone) \ No newline at end of file +set(OUTPUT_NAME PerlinWorld) + +if (WINDOWS) + add_compile_definitions(WINDOWS) + + if (RELEASE) + # launch as windows, not console app - so cmd does not open as well + add_link_options(-mwindows) + endif () +else () + add_link_options(-no-pie) +endif() + +add_executable(${OUTPUT_NAME} "main.cpp") + +target_link_libraries(${OUTPUT_NAME} Hop) + +set_target_properties(${OUTPUT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") + +file(GLOB LUA "*.lua") +file(GLOB MAP "*.hmap") + +file(COPY ${LUA} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") +file(COPY ${MAP} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") \ No newline at end of file diff --git a/demo/desktop/perlinWorld/standalone/main.cpp b/demo/desktop/perlinWorld/main.cpp similarity index 100% rename from demo/desktop/perlinWorld/standalone/main.cpp rename to demo/desktop/perlinWorld/main.cpp diff --git a/demo/desktop/perlinWorld/standalone/main.h b/demo/desktop/perlinWorld/main.h similarity index 100% rename from demo/desktop/perlinWorld/standalone/main.h rename to demo/desktop/perlinWorld/main.h diff --git a/demo/desktop/softBodyTetris/CMakeLists.txt b/demo/desktop/softBodyTetris/CMakeLists.txt index 0f490bc4..21e4658f 100644 --- a/demo/desktop/softBodyTetris/CMakeLists.txt +++ b/demo/desktop/softBodyTetris/CMakeLists.txt @@ -1 +1,33 @@ -add_subdirectory(standalone) \ No newline at end of file +set(OUTPUT_NAME SoftBodyTetris) + +include_directories(.) + +if (WINDOWS) + add_compile_definitions(WINDOWS) + + if (RELEASE) + # launch as windows, not console app - so cmd does not open as well + add_link_options(-mwindows) + endif () +else () + add_link_options(-no-pie) +endif() + +if (PROFILE) + # apt-get install google-perftools libgoogle-perftools-dev google-pprof + # CPUPROFILE=prof.out ./SoftBodyTetris + # google-pprof --pdf SoftBodyTetris prof.out > sbt.pdf + add_link_options("-Wl,--no-as-needed,-lprofiler,--as-needed") +endif() + +add_executable(${OUTPUT_NAME} "main.cpp") + +target_link_libraries(${OUTPUT_NAME} Hop) + +set_target_properties(${OUTPUT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}") + +file(GLOB LUA "*.lua") +file(GLOB MAP "*.hmap") + +file(COPY ${LUA} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") +file(COPY ${MAP} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") \ No newline at end of file diff --git a/demo/desktop/softBodyTetris/standalone/main.cpp b/demo/desktop/softBodyTetris/main.cpp similarity index 100% rename from demo/desktop/softBodyTetris/standalone/main.cpp rename to demo/desktop/softBodyTetris/main.cpp diff --git a/demo/desktop/softBodyTetris/standalone/main.h b/demo/desktop/softBodyTetris/main.h similarity index 100% rename from demo/desktop/softBodyTetris/standalone/main.h rename to demo/desktop/softBodyTetris/main.h diff --git a/demo/desktop/softBodyTetris/standalone/CMakeLists.txt b/demo/desktop/softBodyTetris/standalone/CMakeLists.txt deleted file mode 100644 index a9fc8284..00000000 --- a/demo/desktop/softBodyTetris/standalone/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -set(OUTPUT_NAME SoftBodyTetris) - -include_directories(.) - -if (WINDOWS) - add_compile_definitions(WINDOWS) - - if (RELEASE) - # launch as windows, not console app - so cmd does not open as well - add_link_options(-mwindows) - endif () -else () - add_link_options(-no-pie) -endif() - -if (PROFILE) - # apt-get install google-perftools libgoogle-perftools-dev google-pprof - # CPUPROFILE=prof.out ./SoftBodyTetris - # google-pprof --pdf SoftBodyTetris prof.out > sbt.pdf - add_link_options("-Wl,--no-as-needed,-lprofiler,--as-needed") -endif() - -add_executable(${OUTPUT_NAME} "main.cpp") - -target_link_libraries(${OUTPUT_NAME} Hop) - -set_target_properties(${OUTPUT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}") - -file(GLOB LUA "../*.lua") -file(GLOB MAP "../*.hmap") - -file(COPY ${LUA} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") -file(COPY ${MAP} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") \ No newline at end of file diff --git a/demo/desktop/perlinWorld/standalone/CMakeLists.txt b/demo/desktop/sprites/CMakeLists.txt similarity index 77% rename from demo/desktop/perlinWorld/standalone/CMakeLists.txt rename to demo/desktop/sprites/CMakeLists.txt index a3c01319..e2a0a34b 100644 --- a/demo/desktop/perlinWorld/standalone/CMakeLists.txt +++ b/demo/desktop/sprites/CMakeLists.txt @@ -1,4 +1,4 @@ -set(OUTPUT_NAME PerlinWorld) +set(OUTPUT_NAME Sprites) if (WINDOWS) add_compile_definitions(WINDOWS) @@ -17,8 +17,7 @@ target_link_libraries(${OUTPUT_NAME} Hop) set_target_properties(${OUTPUT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") -file(GLOB LUA "../*.lua") -file(GLOB MAP "../*.hmap") +file(GLOB LUA "*.lua") file(COPY ${LUA} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") -file(COPY ${MAP} DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") \ No newline at end of file +file(COPY "assets" DESTINATION "${CMAKE_BINARY_DIR}/${OUTPUT_NAME}/") \ No newline at end of file diff --git a/demo/desktop/sprites/assets/HEART.png b/demo/desktop/sprites/assets/HEART.png new file mode 100644 index 0000000000000000000000000000000000000000..9d44ab97cfc2cb61acd666ef9bcdfdd1fcbba86e GIT binary patch literal 6158 zcmV+p81d(cP)XbA`rBm|X3*>Ou0W1OftlT30lXR@5h zoXk09Vswm4;zW%nMkhLqaT#O8n79PGK|zTEiYTI>f@ni8wcYvScJ1$V)7@3oRZyRE zIET9Ty<5NP`+N7@<$HfuC;)25jtWAdS%^$Qsd0#m1%?5YKm|}mB=Q-CaRS3=1l~nt z4@$j(QacdYDuF<_5VqzD_1tp~di4qbeqcOGjRi&!i&YVeRp4;+0vdr6z;WPxM0TUp z9t>j#vDnKJ2sGu}PRUon>Xlc<5RI+@767#<<)X0>KK&FL8{xzWIDQ-=5&bV=k$}Si zZZ}j`LPZ7i>eWi`-Y-#E`54jY@1(Z&P`>Q$4r<4a0ffV=Xlh!@v14_7{<(*yCjEO` zTOpj`!w!f37yq4=m2k!x(5n|f2-pJr5qMAnfw%Kvb50#VJ@=f4s;c#fT!~V3#A0yx zFnstS9617^koA2hP7phK6cq}gT3R3)1&0Iico2^VqhCKH?hpe8#27H(Mf&%@g_@d8 zA`;8xZ|E#aDT8g>F5=j+n>ci6Hir)z96yd~Z6$W(2&$z;|E5R;OjG|RmrMU9pU=8b zmkav!gCRp;zyL4|1-yt-_tK}&12SezYp(3ii36w|J1Pi=zY2T{7)nzU?Ar$)e30$+ zkqD9Z-Xr?XJ4D`nm)J)ip_-dJHnge=bKpSC5hHM%eKzK}aZp|T3B!i{fY#Q#WZt|; zhlS)2)zIK164}6k1OLi_1B0V)yg_9Dexm#L6aDZ*)bZmTmLXm*#()7hMvTB5ITA;8 zwQdnoaXMk>P#8H9w8MOWQa9sr-7Qn6p6KrH=#~R0rG)L<*P+zSz(7u%fW3Ql#VeI| zZS>uD3GLWHWY;eJM06AB)eGm8DY$BDF@nL5sII<3X3u`A+XbHl>Mwt}fP)9`i`CZ; z3~${^c;`-HpMT!%a>e7pIcXBksZ%k}Ix8bnv?GijtzQ@LA@Gk92>iBN-`Uk0)s`(| zG0nSx^N7XZ?YH5rw;-0%A}d8?&mLNzf1c>UgWa*SUCgu2!o6q_js*)|VC>ixGIi=l z`S>2y(9oZQ2Oo+)^UVC#KmL)(-o06lo-52jgK*86gLA?JUHNfDVEAwtH!j{cIA7zc}cewy(1?Rk4T+QsR_J%2v#Yp%IlR;<{Viz3yd zkKWOG=bhKKZr+?eVks0NxB>y(3l}0TS9;#qvHGO{#6Jmo@R^q$<`ghF@8^+4SiPmFK8`Q2{uIK{~{JrVcTSuuA-R^AX z3~@T~EMKns2C4Mv1HqskLc$h8p~X^HceKOuI=VnLH24sC2BqoaRr0v z=~Y!QYnC25iqzxr%$JE1+Z~S@?PaQl1}92Al9<$~ug|XhmtUski6@G(@&QyRMAMyj z4h=v5{LYiTCw$#?uQuO)dvR7iKrBYfCvL!veu@Saz)e~t-1!-ydAGK?j%eoLv zyAA-{j>saEg6-S0oBf?TX?gnTuKa|;5{=Sw_uUi1-}uH89bFo}>82-I?zv|Q(UWQ{ zdX$!@o+7+sM|$G1WAMr=`hisHe43ko)?OL54xqMeTM1kZ=-&R}!)f`^_ukX*{33nw zGg09%&G+21IQoMhTxWMp=)2#&y7{iV7Au=6>!L#`njd?N==<-dryoA7XJR$isfLEN zc12h^fZDcgG)nynfTKrY&z|)B=4P57d4y7UN>WiLPSAYcegCQMxMOHm-fg!H2|f7W zovJDC3vjt55~2CwhqI^CckfPZv45fJ>(92j-MR&c#cl(th(`4!PsUT;ylE4$W5>E_ zdCw4i=N)Nz^wF)E=`EW!HAMIC@933Sl*B&!jF!hAPft_|UVSw_Gus=HJFM=_`oXHc zel;SC06n#v@kB)4e3MAVdFFj-4$wB_`zfH;>yz&hogWU<@>D_ATk=aZO8D7l6P=^*=FPVj)BHtO zX?g0Y?0J~C-%dWnO5LKKd(M-Zo!J6h4GaOY7j}SfeSOI`{h35|?{e(GY~cT(pDQd@wvfL?^&w=etY-?@|6XP@QX;vOWj zXOA=T)?3b=wj-CsKKqRDu3hPgO2Iqt#6MNj)U+!8A?W}jS0*mDSi29s@=DH)Et4O@ zufCd{c<^9yG$(RJJlOzH+qVx#sV@NV(MMU@z1Xp1MBjTaPv(}%HIaS$vK309Q0nUK zd1~v{YKXT0vDn(g|1F;W$Qy5z%#2?dv=Yl|sGjWC8JOm3{U6Q3#6?GrWZf6Z7!H;x zexk{Dev(w3hEfXvjJ9#%OhB(DWzK`gV&&$)1c~h5pWSMQLV7QT=3KRRuiK!qawecB z2aaaz2V$RoniCaonZlx)nyg1{$vXDY*f_&LWNISQLdzbrcqNo64J_*}RnHNPPBDOS zi3BSL_~es3m{z6`Sk_&tyv;Dir8|Iy_N|!oaAi7&W!n^>HtC9|&g@oBR7$vEZCk0$VgM8Dpbb_)2lrFY)muwlD40Mn{DZ&}bl%l>Ss!S{Gu|KPXegh+ycg#hUGnu(W7%`S($?17&Xc|Beh>3@|uCjOMsp;tfrJiSR$5zMHrk?5Cbvpiz3)vkJ0L-sqQyCBQtDVg$(d)SetKEz>YC#N z|7Q}(nZbzSg$9G=(LgEC7Ej2M)VfvbPY~AxiaZGDg@Atjz@qnP4jNSM3zPtk@#8TD z49L##dZBOM_$P(P@1V^A#P5F#9hX)=<->+$7XY~D&MmhB#f%8fn-bMDC0KH|YS!kKcz5 zKdR@8tE(-)#B;#~))Ne6dKB?`@tl9Yb>{HlsZ+p*Xl;EU{vqK2GH+fB@bkn?qefY_ z0#aFt=SyG8iP2?phiCC(#9}5Fr&HHulAEQjF0oTIefcjExdYI<2i$HQh0+4&v}rh} zP3x}BWpaem@5ec1igo7Lv8hl0VZ7eEQnS+>KxWST9HqXKNEk69et1C^o-cnHW6+>3 z8(k(h7(<5OwQG@k_tte7N2zaR#tqCC00aWRZkrv{y~cP5(hS7q!nbl|xj)c@h}Vnn z(n~Yf_%)`fgGncOfk5Da%*(PIKtvR=*hWCVCn_sp;zUaWjDG#_u3T9j8ukEUn)oii z9K&Y)hDnoB7k-)$xkf~?M4y(5PYDKJN94vtLUlD{9$?UhW7H_TD^_&Q`ZC?aG^x1y zYRthlajk|APoK*XxnBJKH>@tTmHdj|e|LPg2!P3xEd?V0&dHN;fANbaV|tlxB2Fh2 z8#iLuRerBt=`FU%Z^ZBawOx7bYrb1suL6?cChF>}7a0KeoH;nBPj9!lGTp@GqGIF5 z>~QgM+-_Y*$yf4Dl)ARPBHMKUsjF)y7P|<2ww>;5%$Z}mSHOGWg_xu6A`+P@GiL0uz9F5H-uETJ;Qu1>%|yb`p?cBC zs?amf#JhZXd3e}e+FDfGW%$ZUIQQJtC%=(!c%saldD5p^b!y|E`2Dv4$)LmI$LsTI zEO3k;k9*#{&Jl8PkM7zcpA>f_Qp_dgB%QzD_dI(_*u z1#|FVJmryrEzW7v?1eUlq0a<8N@vdHt z*eoxf4w%D+;a#)FzVatb$W&&3Ujl)fb8SaXLx4$5&EJ8`0e##^|Nd~!Io4m?yEneo ztL^^)r!dCAf%w+1w_h(AHxAObci$?3z>o4`ORfu)KwuN_{Y1jZk+y0gv$`7Zg%{@9 zgrdec;|wY;y9}||g$?MxSNh!lz4-k%T3?(4d-77M-~VIaw~5b_CRy(~Mh|~nb#-|$ zqu4Nd_r`bm<@T?>;lp*)A4lX7_U-$sm6k7OHszyG5m7WYeudQihJL?g2pRy-!i6|& z_8^=pNJRy{%PzBy+y#1dHC@W}7)q@<*(2|}O5VbNw(T@p2I!NGold=GVD-)y!F$Oi z*1K9y0mS3Mw_$^Q#I=C~wZ0&5rSP29^1TF@&EUB_m&kvrQ?yViPpQwbw37ru4t?A1K|`)7`pw$ReDwCw@PJ9!TTEP=pwl)9X_nrOfPts}59 zrf*+-t5(?xPfHG`6Ysip_G+HKeKQx)ULzD*EVE}fTHla+3K9ugg2CSdKTaf!8fClt z*c?6_?~)~jFe|^9Ccc#`aoCAud-c-u`^i`0UShF@Z7Zz>qi~_X{r-Oe9!`9oG$}P= zMHJB;tg!FcR#fPfz2r>k0Sse-)Ycv5{EQFYhOaCYZ3{A2ipdt zF#7f_i8TZFym`21&$iBVICSMFm<@>SC#_tuK^)cJ$bJFcJ*j5BxNdFlLN)1Pjcw z&MNAWfos+*+~=KVooSl7@>A73aH#}?e=dk|9niA}0{Q*l29nB_Y16=Fs?<4sdQq+! zIBRO~TyTMPX1t@D9PLCA*&u1=mOHNjt}&d zcem7;P0 z0Q~-MA@W$_^OPy}YX*}h;r_xG3SyQyXpoM3V0Ref*s+-rIq${qzo8Jeb%&yJ01=7N z+`JypN7=+j1~w;_xaZH$`#u9>zyK}fYEQ>EW=v|z@AEC?$`wWD0MIrvFpP_cuNk;p z?W>8FF2%HYRdknxh|})KoMFS#b$qai#>Tu$xpGBOIskyw)V!OvW>8h7$JJIio%q(Q z$@vcCgox8-mlH#W>Q_{fXXxE~wal9rvA&`BC|U=AwlxEh%ZRIq&OFmrO_bPyZ1;}t z>~~jIwlCrwG$?bZ`XWx}G8r?bH75oXh@y4?0P*`D27Z!A7&Xd%pTXe4c$O{e_Q*gg zDyX>P3VRXfnP=*Wo^&1Gmt^YH6W#ja9-!zQ006)LdnlEhLTzuK!GsC+3o|Eycs%&l zueXoK*T28+k0d97b{1O4mrF{*0YpR*4qu5#eOp4i`wZN3=XNPJQ9{9Mw{bOF#JPu9 z?1Dn;_;N`}H~=KnL`%usXJEGjxwEl}I#Tdvi#XrLFy{4yjxU##i~|5jP0a^b?K7}? z=Q|vFWRP5kx2GcoZ?=f@eWK9?ZT6HjCFKB+*k_PFGO#(-R4OYw9vK)0-sQ{NSMbi7 zl`i5GStv7Rywl|$QACuS0{}=c_y{6DOeBmLk$x;%3g)0e`cMn2mAkfJjJ7k09*JH?I6Vp$|PQfu|O!j#O@nDR0okf>RD|j5TA9P4pZsL!F@(s);`jewKJ4#lO5Ong)Yh%j zFpR$f`td({6t--ESS{)s&9r3%T(vs6PIr%r*%?GEH1GMpV;LkvZ=NSNcJwJU%(sv~g_(dM= zD=JPo2arG@Of-54@D`9f&%i1s-{i^Zfht6PAc4TY7sk@!;FNO!Xp34ZauM(uV11s! z`0?qw0;O&dzyF7vW}K1^03d$<8;Gm|v^=YC-=utN+_-cFugHH92z)cUlvAHmVjiG9 zRDJzTh$QzKeDX==l=1!e{a1=e_N2jSz$x1T#F1d|XTY6_gw)Dc>QNdSzjC@(KAZ*) z(8f1V>e-C6r|HvYZ7C^u^TBE101^m<35Qn#`ZP_Yo~5yIX{jlA%XAY}Uq4PYH2gvB g*ijlmhYG;|1GuEfSvUmZ?*IS*07*qoM6N<$f*QsqA^-pY literal 0 HcmV?d00001 diff --git a/demo/desktop/sprites/assets/Pi.png b/demo/desktop/sprites/assets/Pi.png new file mode 100644 index 0000000000000000000000000000000000000000..c811289d59dedac843c4dcec639020b566e87b9c GIT binary patch literal 2664 zcmV-u3YYbXP)430THOLwH7Ib`ofwRNerNg#((e;|1pt2 z)EEP5z=XsY6BB|lAQ~hXf(hjzU>mJG+D0g_TSO>OOIxff*!KFz>DBAzclX|zd(N5P z-ri3#p}_8$ncnX`GjnF<+yQKv1FQf}1{MK}fd#5< zebAw6pHR3SchqbKpXQwsiQh8`uM30yrJ`4Y16jMIEj@ zkpH2s08R#e2b^HioDOd`=6|RofTh5_z>?5HJXALE`uw?crJABw!-{4`m+UQ*;l% zZR|&$>qONL4g%XrAFAw%P8kDk0G7~$UdzCXf#tn^IFf$@zXk3F{scS+>;+~b5yc+? z!;1CgYyz%Ff*$(~>=zjZ&I7JG@=psk^S}P=tMT(0^7kCf?dT})5Td-Q;L+!m>MNG( zsb1k&Fax+bqP-7yi2Ah|MQ;xB2PHeD z6d(9#LtEQ`I|F}b1bA=5dW$@!Xe*YB6m4x*wAGWM09H4&bxXwWTm&4`u-+n%DB6l; zt)eY+0pz@y=Ht~F5%u1vP;arEAJGO)mZR5~r#u>*dw_)v?L1Dn`<;QVyUc*CiuPhy zr)X=FqODSL0le7IPK^6s1svb7-Xc!}uPEA!VcH3x$UVfls@=#C63X`?>nkh2ifDr- z!@#TP^~Y*Yp_Ca3`tmAr9M7C$lxZih5?GHc&E_LJ zc9S`by!D%bTanOjC~pN$jrhH(cvRV5D4O$`hk<`7+Uq;6Lig>@NPAyl06A@=)tBqM z8lGay6m+A1Ad|mwWt$z`2U{HsR>ayak{g{mV(Y2e201J$u&xkhcKNLlR49k|8mLRA>v@ zJp$;-chO(|J?Ywm|7Q?*p`=|g_8@gZg>h{32>T$ z-INnRZTD|}0%$Ux0{Ezr-IM~*-2H==kNmticG04xOE+7-Zeu$lcI#wM>o9UiIK#=7MN-{$+0 z@6~IUR3YGn=x0U0&9w&wtcQTb#9bJvLn`-w3HnRVWbWTu02ZP z1)zOWw#Zfr`EDJt=#$$O@LpI6U=UjYqzD1O6Zvj}HtuHtidYHY9Be->kzxg~!NBG} zNqnWmW^vEA3MfBY>6Ij*~?W;P?S0V8qydUmOH25+eYw;1BpGg0RjzXf3c{Vg&FJ^;VSQ zeRj?|S<`Z3`@w_?U_O4)Kk&Z>X6*s2E}29VDu8tnztaToi=Y-M?TdJN&su~&Ot0NP z@IM6%_RF+0u{~@OOo#wxp`RmvDt6+(ZrOUL>^-pW1roN~_D3fzq( zjC>9m_VS@I?-_hTvQ_K^zL~laQ!u7sq)Gs5H7W_DpYG59kUmN1 z*aH^z*nSnYs{Bl=Bc2C5+r+KNVUF=c^^Ya0w__4>fLrkQ03Y+{ zTt|J@BX6b0!+(uFykXQK$H=~cq=B^*K)-KN9rX+WUq?1e_LvQ+yC zvTkqk;3t3|V~~_10000H$*# literal 0 HcmV?d00001 diff --git a/demo/desktop/sprites/assets/random.png b/demo/desktop/sprites/assets/random.png new file mode 100644 index 0000000000000000000000000000000000000000..8d5dc5b3c9fed68ad4cfcea36ccaeffbd3326595 GIT binary patch literal 2587 zcmZWrc|6ox8~@FivCJS#md3vClTb~A7|j^VG+bm~OUQB!a+9Sn*2`FurOUMoAvB`w zvLsorC6(+V;@Y#7_s9M7J)h6npL3q`Jm>o?vBqQ~8v=y@0Dw(j4{rkYpcTab^KotAAUOxK~kcj|uE)e~NVTUVcJ=l8-a@djvEkGY zrQXIC=QnWG<3+ijsZVORdI3T9==K>(M~pMqXAIQx$5c*MDe-csHBg}TrT}n*WbCOF zrMm!Exiz9wzKQ_9G~vR64iCKd{f>$^{>`8xnVHtR<9Du%bpqN^4&M=;z0C86N8ciq zLakb?-w8r6&_U%hG6C;ukh&T z=$AG;g62Hh1w+&0)whhxM)^^wgO;hfni>EwFfd5U&Q4fbaudAb3v+UED!1WLH2($fr<#Rz^uFsl4*?-r4fn+DmvMac=c<9SqBTo&?8G zrh&CD4MatwvQcp{F-XqU5b-p*OBpQ2rlwTC#eU8KuRC{eWHS4PZFMUiC>Vev9U4NOulsCyj}fSL}a*ibCT1pKgGpGnpe?MTjN82Kf7yxRv3*+~ zdv|qoRj5XB^*n zbBKB;dna`?A7K>E*xog%HOprl5cv$kwD!M+NW;+UXht?)uQ@gwMKn(r1)PKNi4bXH?<{H6!gZWwK9h$ZC zjHi226(X>iSY~tJZ*p{nOqOlrhTY=o1tY>P!$) zU!Q4b%6~nEPlDFe*3Qm$#+ki1JUsMS9+8v(IHsKh6}%eE&qxike&FOJriNmB8JxyU z4sC10nORtvR^$zT%ZP8N)}}xwnnMI6BqT;wCSLha1KD_)$$!0#M$t&_LwE|b z3Ux-{+_^CGvfCzc(zc;@OyYRMxgGN>9~TEHS%c(hbVzn~cCY)84h0H23)NDIRD+q> z**Ar}*I_c+o}P*+Sl`#S9L4!Y$HaApjg1WuAR{ZDpK4kABq=RTK17vsWC1{~ zNvWf&D^cm;RC5T$�)uccogM=kap$j}ho#Oo3^*`25EF$7BogZoDJUq& zw&9QK#;&YLbHK*NrexF|{3Y&pbUMAg$S}R?W+y`YzA3y7JcCA~ODZet_Mki`qvy}N z(v)nN{V(}*)Bvq@61)HWV*+9@^Jg0kFCM0o*P0?@B%1zS&fm=rb{<$?RShaKiA_u6 zEiscOJJC-VEOvIfjfx3a7sX<+gCipm zlauz_J3CHeE*@A!xI@10V^yloKDpG<@l*U zmK|DwyM0><6fSCH#LUdxoQz3#Q|4cvZewtEc6J=fC&(%)ItR`n(SVb#u5Ojb5|5@WD3A%2-7^D5X-*{p}@A&`AtVPLfOL zu`^JPH*RX;7ccU#v9aMd!B-_^Wax#kCnL3EKzo_x)?Zy+9e?S;H`FTv(&p0X+;BMD z?1hJiN2z^QI8qx(HGntS8z~(R=3V0#5GZ)m2d_%{@$b~!!On`A2Z(Ny24y&3tIqFV z>Iwd5f2!9+{q`E*HLEBL#aRiZyu)jxBOS$B>c5K0Z3k*HGBU<2`a%@( z#lzQEtZf0L)5UoCWIfQ0l27T%VHAJ=B9-rNKwhZ|7AmFOD3pQJ$qnUE_{-jtq|>os znqu|R?&TJ0QI%n{`9e9Go14LanQ_HWy1KWqQDgZYei6!nN2eD&ecCm93{!RO z?}$Y5C8ee5{-;!F6%{Vf4lSDkcM5CIu(05~yp(oK+nU?qxvh=&wCqxkN+~_x1v|cX#ujJwt%OZE0;S%Dk*I>x$p> zw{Nknt=gXBRgkc-F!OK8$W{Q1_Mm5b`^hUF`G5I=rGvxy7^I95QBg=VHKTgX8o0=N zW3I}DJv33vCalGiz|N;VpCQq@-9kuvHOR1cRF>MyIh_Mo%Y0#vzE}jrB%WnraAR(display.getRes())); + + jGLInstance->setTextProjection(glm::ortho(0.0,double(resX),0.0,double(resY))); + jGLInstance->setMSAA(1); + + jGL::OrthoCam camera(resX, resY, glm::vec2(0.0,0.0)); + + EntityComponentSystem manager; + + jLog::Log log; + + Hop::Console console(log); + + std::unique_ptr world; + + Hop::World::FiniteBoundary mapBounds(0,0,16,16, true, true, true, true); + Hop::World::FixedSource mapSource; + + world = std::make_unique + ( + 2, + &camera, + 16, + 1, + &mapSource, + &mapBounds + ); + + sRender & rendering = manager.getSystem(); + auto assets = std::make_shared( + std::filesystem::path("assets"), jGLInstance + ); + auto spriteRenderer = jGLInstance->createSpriteRenderer(8); + rendering.setSpriteRenderer(spriteRenderer); + rendering.setTextureAssetStore(assets); + + // setup physics system + sPhysics & physics = manager.getSystem(); + physics.setTimeStep(deltaPhysics); + physics.setGravity(9.81, 0.0, -1.0); + + sCollision & collisions = manager.getSystem(); + + auto det = std::make_unique(world.get()); + + auto res = std::make_unique + ( + deltaPhysics*10.0, + 0.66, + 0.0 + ); + + collisions.setDetector(std::move(det)); + collisions.setResolver(std::move(res)); + + Hop::LuaExtraSpace luaStore; + + luaStore.ecs = &manager; + luaStore.world = world.get(); + luaStore.physics = &physics; + luaStore.resolver = &collisions; + + console.luaStore(&luaStore); + + console.runFile("config.lua"); + std::string status = console.luaStatus(); + if (status != "LUA_OK") { WARN(status) >> log; } + + high_resolution_clock::time_point t0, t1, tp0, tp1, tr0, tr1; + + while (display.isOpen()) + { + jGLInstance->beginFrame(); + + jGLInstance->clear(); + + t0 = high_resolution_clock::now(); + + tp0 = high_resolution_clock::now(); + + collisions.centreOn(world.get()->getMapCenter()); + + physics.step(&manager, &collisions, world.get()); + + tp1 = high_resolution_clock::now(); + + tr0 = high_resolution_clock::now(); + + rendering.setProjection(camera.getVP()); + rendering.update(&manager); + rendering.draw(jGLInstance, &manager, world.get()); + + tr1 = high_resolution_clock::now(); + + if (debug) + { + double delta = 0.0; + for (int n = 0; n < 60; n++) + { + delta += deltas[n]; + } + delta /= 60.0; + std::stringstream debugText; + + double pdt = duration_cast>(tp1 - tp0).count(); + double rdt = duration_cast>(tr1 - tr0).count(); + + double mouseX, mouseY; + display.mousePosition(mouseX,mouseY); + + float cameraX = camera.getPosition().x; + float cameraY = camera.getPosition().y; + + glm::vec4 worldPos = camera.screenToWorld(mouseX,mouseY); + + Hop::World::TileData tile = world->getTileData(worldPos[0],worldPos[1]); + + debugText << "Delta: " << fixedLengthNumber(delta,6) << + " (FPS: " << fixedLengthNumber(1.0/delta,4) << ")" << + "\n" << + "Mouse (" << fixedLengthNumber(mouseX,4) << "," << fixedLengthNumber(mouseY,4) << ")" << + "\n" << + "Mouse [world] (" << fixedLengthNumber(worldPos[0],4) << "," << fixedLengthNumber(worldPos[1],4) << ")" << + "\n" << + "Mouse cell (" << fixedLengthNumber(tile.x,4) << ", " << fixedLengthNumber(tile.y,4) << ", " << tile.tileType << + "\n" << + "Camera [world] (" << fixedLengthNumber(cameraX,4) << ", " << fixedLengthNumber(cameraY,4) << ")" << + "\n" << + "update time: " << fixedLengthNumber(pdt+rdt,6) << + "\n" << + "Phys update / draw time: " << fixedLengthNumber(pdt,6) << "/" << fixedLengthNumber(rdt,6); + + jGLInstance->text + ( + debugText.str(), + glm::vec2(64.0f,resY-64.0f), + 0.5f, + glm::vec4(0.0f,0.0f,0.0f, 1.0f) + ); + } + + if (frameId == 30) + { + if (log.size() > 0) + { + std::cout << log.get() << "\n"; + } + } + + jGLInstance->endFrame(); + + display.loop(); + + t1 = high_resolution_clock::now(); + + deltas[frameId] = duration_cast>(t1 - t0).count(); + frameId = (frameId+1) % 60; + } + return 0; +} diff --git a/demo/desktop/sprites/main.h b/demo/desktop/sprites/main.h new file mode 100644 index 00000000..24f5ab00 --- /dev/null +++ b/demo/desktop/sprites/main.h @@ -0,0 +1,102 @@ +#ifndef MAIN_H +#define MAIN_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +using namespace std::chrono; + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +const int resX = 1000; +const int resY = 1000; +const float MAX_SPEED = 1.0/60.0; + +// for smoothing delta numbers +uint8_t frameId = 0; +double deltas[60]; + +bool debug = true; +bool grid = false; +bool paused = true; + +double pointSize = 1.0; +double primitiveSize = 0.5; + +std::pair activeSite(0.0, 0.0); +double radialTheta = 0.0; + +const double deltaPhysics = 1.0/900.0; + +using Hop::Object::Component::cTransform; +using Hop::Object::Component::cPhysics; +using Hop::Object::Component::cRenderable; +using Hop::Object::Component::cCollideable; +using Hop::Object::EntityComponentSystem; +using Hop::Object::Id; +using Hop::Object::Component::CollisionPrimitive; + +using Hop::System::Rendering::sRender; + +using Hop::System::Physics::CollisionDetector; +using Hop::System::Physics::CollisionResolver; +using Hop::System::Physics::sPhysics; +using Hop::System::Physics::sCollision; + +using Hop::System::Signature; + +using Hop::World::MapSource; +using Hop::World::Boundary; +using Hop::World::AbstractWorld; +using Hop::World::MarchingWorld; +using Hop::World::TileWorld; +using jLog::INFO; +using jLog::WARN; + +std::string fixedLengthNumber(double x, unsigned length) +{ + std::string d = std::to_string(x); + std::string dtrunc(length,' '); + for (unsigned c = 0; c < dtrunc.length(); c++/*ayy lmao*/) + { + + if (c >= d.length()) + { + dtrunc[c] = '0'; + } + else + { + dtrunc[c] = d[c]; + } + } + return dtrunc; +} + +std::shared_ptr jGLInstance; + +#endif /* MAIN_H */ diff --git a/include/Console/console.h b/include/Console/console.h index 4128e43a..c91dbc49 100644 --- a/include/Console/console.h +++ b/include/Console/console.h @@ -33,6 +33,11 @@ namespace Hop using jLog::Log; using jLog::ERRORCODE; + /** + * @brief Store for lua global state. + * For the console to have access to these classes they must + * be set into LuaExtraSpace and set via Console::luaStore. + */ struct LuaExtraSpace { EntityComponentSystem * ecs; @@ -43,7 +48,7 @@ namespace Hop Scriptz * scripts; }; - // ECS + // ECS typedef int (EntityComponentSystem::*EntityComponentSystemMember)(lua_State * lua); @@ -68,7 +73,7 @@ namespace Hop } // Physics - + typedef int (sPhysics::*sPhysicsMember)(lua_State * lua); template @@ -80,7 +85,7 @@ namespace Hop } // sCollision - + typedef int (sCollision::*sCollisionMember)(lua_State * lua); template @@ -92,7 +97,7 @@ namespace Hop } // Scriptz - + typedef int (Scriptz::*ScriptzMember)(lua_State * lua); template @@ -103,17 +108,49 @@ namespace Hop return ((*ptr).*function)(lua); } - + /** + * @brief Configure physics. + * @remark Takes a lua table: +{ + ["timeStep"] = 1.0/1800.0, + ["subSample"] = 5, + ["cofr"] = 0.9, + ["surfaceFriction"] = 0.5 +} + * @param lua lua_State. + * @return int lua return code. + */ int configure(lua_State * lua); + /** + * @brief Returns the current system clock time in lua. + * + * @param lua lua_State. + * @return int return code. + */ int timeMillis(lua_State * lua); + /** + * @brief Apply a force to an object. + * @remark Takes the string id, and forces in x and y. + * @param lua lua_State. + * @return int return code. + */ int lua_applyForce(lua_State * lua); - class Console + /** + * @brief Lua console. + * @remark Access to Hop classes is via LuaExtraSpace set by Console::luaStore. + */ + class Console { public: + /** + * @brief Construct a new Console with a logger. + * + * @param l Log outputting Lua's messages. + */ Console(Log & l) : lastCommandOrProgram(""), lastStatus(false), log(l) { @@ -125,6 +162,13 @@ namespace Hop ~Console(){ lua_close(lua); } + /** + * @brief Attempt to run a Lua script from a file on disc. + * + * @param file Lua script location. + * @return true Error occured. + * @return false OK. + */ bool runFile(std::string file) { if (luaIsOk()) @@ -141,6 +185,13 @@ namespace Hop return false; } + /** + * @brief Attempt to run a Lua script from std::string. + * + * @param file Lua script. + * @return true Error occured. + * @return false OK. + */ bool runString(std::string program) { if (luaIsOk()) @@ -153,6 +204,11 @@ namespace Hop bool luaIsOk(){ return lua_status(lua) == LUA_OK ? true : false; } + /** + * @brief Convert Lua's status to a std::string + * + * @return std::string Lua status name. + */ std::string luaStatus() { int s = lua_status(lua); @@ -186,26 +242,21 @@ namespace Hop return status; } - bool handleErrors() - { - if (lastStatus) - { - std::string msg = "Exited with error running "+lastCommandOrProgram+"\n"; - msg += stackTrace; - ERR(ERRORCODE::LUA_ERROR, msg) >> log; - return true; - } - else - { - return false; - } - } - + /** + * @brief Set the LuaExtraSpace holding Hop classes. + * @remark This gives Console access to Hop. + * @param ptr LuaExtraSpace. + */ void luaStore(LuaExtraSpace * ptr) { *static_cast(lua_getextraspace(lua)) = ptr; } + /** + * @brief Run a packed script from Scriptz in LuaExtraSpace. + * + * @param name The script name. + */ void runScript(std::string name) { @@ -221,14 +272,12 @@ namespace Hop } lastCommandOrProgram = name; - lastStatus = + lastStatus = ( luaL_loadstring(lua, body.c_str()) || lua_pcall(lua, 0, LUA_MULTRET, 0) ); - handleErrors(); - } double getNumber(const char * n) @@ -295,6 +344,22 @@ namespace Hop return 0; } + bool handleErrors() + { + if (lastStatus) + { + std::string msg = "Exited with error running "+lastCommandOrProgram+"\n"; + msg += stackTrace; + ERR(ERRORCODE::LUA_ERROR, msg) >> log; + return true; + } + else + { + return false; + } + } + + // register lib static int load_hopLib(lua_State * lua) diff --git a/include/Console/lua.h b/include/Console/lua.h index 47b3d08d..991b5a11 100644 --- a/include/Console/lua.h +++ b/include/Console/lua.h @@ -21,6 +21,15 @@ namespace Hop std::vector< std::vector > getLuaTableOfNumericLuaTable(lua_State * lua, int index); + /** + * @brief Check the argument count to the lua call. + * @param lua lua_State. + * @param expected argument count expected. + * @param msg Error string pushed if not LUA_OK. + * @return int return code. LUA_OK if the argument count matches. + */ + int lua_checkArgumentCount(lua_State * lua, int expected, std::string msg); + } #endif /* LUA */ diff --git a/include/System/Rendering/sRender.h b/include/System/Rendering/sRender.h index b9ef1304..9d91633b 100644 --- a/include/System/Rendering/sRender.h +++ b/include/System/Rendering/sRender.h @@ -38,6 +38,7 @@ namespace Hop::System::Rendering using Hop::Object::Component::ComponentArray; using Hop::Object::Component::cSprite; using Hop::Object::Component::cRenderable; + using Hop::Object::Component::cTransform; /** * @brief System to handle rendering. * diff --git a/include/Util/assetStore.h b/include/Util/assetStore.h index 81bf6b9c..da9cdc7a 100644 --- a/include/Util/assetStore.h +++ b/include/Util/assetStore.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace Hop::Util::Assets { @@ -47,9 +48,9 @@ namespace Hop::Util::Assets /** * @brief Loads the asset at this relative path. * - * @param assetPath relative path to an asset. + * @param relativePath relative path to an asset. */ - virtual void load(std::filesystem::path assetPath) = 0; + virtual void load(std::filesystem::path relativePath) = 0; /** * @brief Loads all assets in the asset store. @@ -66,17 +67,17 @@ namespace Hop::Util::Assets /** * @brief Return the asset. * - * @param relative_path path to asset. + * @param relativePath path to asset. * @return std::shared_ptr the asset. * @remark Will attempt to load an unloaded asset. */ - std::shared_ptr get(std::filesystem::path relative_path) + std::shared_ptr get(std::filesystem::path relativePath) { - if (assets[relative_path] == nullptr) + if (assets[relativePath] == nullptr) { - load(relative_path); + load(relativePath); } - return assets[relative_path]; + return assets[relativePath]; } typename std::map>::const_iterator begin() { return assets.cbegin(); } @@ -94,7 +95,8 @@ namespace Hop::Util::Assets { if (entry.is_regular_file()) { - if (matchesAssetType(entry) && assets.find(entry) == assets.end()) { assets[entry] = nullptr; } + std::filesystem::path relative = std::filesystem::relative(entry, root); + if (matchesAssetType(relative) && assets.find(relative) == assets.end()) { assets[relative] = nullptr; } } else { @@ -121,21 +123,23 @@ namespace Hop::Util::Assets */ TextureAssetStore(std::filesystem::path root, std::shared_ptr & instance) : AssetStore(root), instance(instance) - {} + { + scan(); + } /** * @brief Load a texture. * - * @param assetPath path relative to root. + * @param relativePath path relative to root. */ - void load(std::filesystem::path assetPath) + void load(std::filesystem::path relativePath) { - if (matchesAssetType(assetPath)) + if (matchesAssetType(relativePath)) { - std::filesystem::path relative = std::filesystem::relative(assetPath, root); - assets[relative] = instance->createTexture + std::filesystem::path path = root / relativePath; + assets[relativePath] = instance->createTexture ( - assetPath.generic_string(), + path.generic_string(), jGL::Texture::Type::RGBA ); } @@ -145,7 +149,7 @@ namespace Hop::Util::Assets * @brief Supported texture extension. * @remark These will be loaded as RGBA textures. */ - const std::vector extensions = {".png, .jpg"}; + const std::array extensions = {".png", ".jpg"}; protected: std::shared_ptr & instance; diff --git a/include/jGL b/include/jGL index 80147c4f..04563847 160000 --- a/include/jGL +++ b/include/jGL @@ -1 +1 @@ -Subproject commit 80147c4f20a08c4eb089967471581d28c26327d8 +Subproject commit 045638478207ab1a6e2ca952df62730c03c5fb17 diff --git a/src/Console/console.cpp b/src/Console/console.cpp index de0ca514..72402532 100644 --- a/src/Console/console.cpp +++ b/src/Console/console.cpp @@ -6,25 +6,19 @@ namespace Hop int configure(lua_State * lua) { - LuaExtraSpace * store = *static_cast(lua_getextraspace(lua)); - - sPhysics * phys = store->physics; - sCollision * col = store->resolver; - - LuaNumber dt, subSample, cor, sf; - - int n = lua_gettop(lua); - + int status = lua_checkArgumentCount(lua, 1, "expected table as argument"); + if (status != LUA_OK) { return status; } if (!lua_istable(lua, 1)) { lua_pushliteral(lua, "non table argument"); return lua_error(lua); } - else if (n != 1) - { - lua_pushliteral(lua, "more than one argument"); - return lua_error(lua); - } + LuaExtraSpace * store = *static_cast(lua_getextraspace(lua)); + + sPhysics * phys = store->physics; + sCollision * col = store->resolver; + + LuaNumber dt, subSample, cor, sf; if (dt.readField(lua, "timeStep")) { @@ -58,17 +52,11 @@ namespace Hop int lua_applyForce(lua_State * lua) { + int status = lua_checkArgumentCount(lua, 3, "expected id and force vector, fx, fy as argument"); + if (status != LUA_OK) { return status; } LuaNumber fx, fy; LuaString sid; - int n = lua_gettop(lua); - - if (n != 3) - { - lua_pushliteral(lua,"expected id and force vector, fx, fy as argument"); - return lua_error(lua); - } - sid.read(lua, 1); Hop::Object::Id id(sid.characters); diff --git a/src/Console/lua.cpp b/src/Console/lua.cpp index 6c68ca67..b9feef3d 100644 --- a/src/Console/lua.cpp +++ b/src/Console/lua.cpp @@ -2,7 +2,7 @@ namespace Hop { - + std::vector getNumericLuaTable(lua_State * lua, int index) { unsigned length = lua_rawlen(lua,index); @@ -42,4 +42,14 @@ namespace Hop return values; } + int lua_checkArgumentCount(lua_State * lua, int expected, std::string msg) + { + int n = lua_gettop(lua); + if (n != expected) + { + lua_pushlstring(lua, msg.c_str(), msg.length()); + return lua_error(lua); + } + return LUA_OK; + } } \ No newline at end of file diff --git a/src/Object/LuaBindings/lua_meshIO.cpp b/src/Object/LuaBindings/lua_meshIO.cpp index 415a5d8b..5e3f32b9 100644 --- a/src/Object/LuaBindings/lua_meshIO.cpp +++ b/src/Object/LuaBindings/lua_meshIO.cpp @@ -9,13 +9,8 @@ namespace Hop::Object { int EntityComponentSystem::lua_removeFromMeshByTag(lua_State * lua) { - int n = lua_gettop(lua); - - if (n != 2) - { - lua_pushliteral(lua, "expected id and tag as argument"); - return lua_error(lua); - } + int status = lua_checkArgumentCount(lua, 2, "expected id and tag as argument"); + if (status != LUA_OK) { return status; } LuaString sid; LuaNumber ltag; @@ -37,13 +32,8 @@ namespace Hop::Object int EntityComponentSystem::lua_meshBoundingBox(lua_State * lua) { - int n = lua_gettop(lua); - - if (n != 1) - { - lua_pushliteral(lua, "expected id as argument"); - return lua_error(lua); - } + int status = lua_checkArgumentCount(lua, 1, "expected id as argument"); + if (status != LUA_OK) { return status; } LuaString sid; @@ -96,13 +86,8 @@ namespace Hop::Object int EntityComponentSystem::lua_meshBoundingBoxByTag(lua_State * lua) { - int n = lua_gettop(lua); - - if (n != 2) - { - lua_pushliteral(lua, "expected id and tag as argument"); - return lua_error(lua); - } + int status = lua_checkArgumentCount(lua, 2, "expected id and tag as argument"); + if (status != LUA_OK) { return status; } LuaString sid; LuaNumber ltag; @@ -149,7 +134,6 @@ namespace Hop::Object lua_pushnumber(lua, bb.centre.y); lua_setfield(lua, -2, "y"); lua_setfield(lua, -2, "centre"); - return 1; } diff --git a/src/Object/LuaBindings/lua_objectIO.cpp b/src/Object/LuaBindings/lua_objectIO.cpp index 8cd26707..2c6527cc 100644 --- a/src/Object/LuaBindings/lua_objectIO.cpp +++ b/src/Object/LuaBindings/lua_objectIO.cpp @@ -42,16 +42,10 @@ namespace Hop::Object int EntityComponentSystem::lua_deleteObject(lua_State * lua) { + int status = lua_checkArgumentCount(lua, 1, "expected id as argument"); + if (status != LUA_OK) { return status; } LuaString sid; - int n = lua_gettop(lua); - - if (n != 1) - { - lua_pushliteral(lua,"expected id as argument"); - return lua_error(lua); - } - sid.read(lua, 1); Id id(sid.characters); @@ -63,6 +57,15 @@ namespace Hop::Object int EntityComponentSystem::lua_loadObject(lua_State * lua) { + int status = lua_checkArgumentCount(lua, 1, "expected table as argument"); + if (status != LUA_OK) { return status; } + + if (!lua_istable(lua,1)) + { + lua_pushliteral(lua,"non table argument"); + return lua_error(lua); + } + LuaArray<4> colour, transform, util, textureRegion; LuaArray<3> meshParameters; @@ -95,20 +98,6 @@ namespace Hop::Object priority.n = 0; - // elements on stack - int n = lua_gettop(lua); - - if (!lua_istable(lua,1)) - { - lua_pushliteral(lua,"non table argument"); - return lua_error(lua); - } - else if (n != 1) - { - lua_pushliteral(lua,"requires single argument"); - return lua_error(lua); - } - hasColour = colour.readField(lua, "colour"); hasTransform = transform.readField(lua, "transform"); @@ -220,7 +209,6 @@ namespace Hop::Object region.lx = textureRegion.elements[2]; region.ly = textureRegion.elements[3]; } - addComponent ( pid, diff --git a/src/Object/LuaBindings/lua_renderableIO.cpp b/src/Object/LuaBindings/lua_renderableIO.cpp index 0a0f4859..3da87d32 100644 --- a/src/Object/LuaBindings/lua_renderableIO.cpp +++ b/src/Object/LuaBindings/lua_renderableIO.cpp @@ -10,14 +10,8 @@ namespace Hop::Object int EntityComponentSystem::lua_getColour(lua_State * lua) { LuaString sid; - - int n = lua_gettop(lua); - - if (n != 1) - { - lua_pushliteral(lua,"expected id as argument"); - return lua_error(lua); - } + int status = lua_checkArgumentCount(lua, 1, "expected id as argument"); + if (status != LUA_OK) { return status; } sid.read(lua, 1); @@ -37,14 +31,8 @@ namespace Hop::Object { LuaString sid; LuaNumber r, g, b, a; - - int n = lua_gettop(lua); - - if (n != 5) - { - lua_pushliteral(lua,"expected id, and r, g, b, a as argument"); - return lua_error(lua); - } + int status = lua_checkArgumentCount(lua, 5, "expected id, and r, g, b, a as argument"); + if (status != LUA_OK) { return status; } sid.read(lua, 1); diff --git a/src/Object/LuaBindings/lua_textureIO.cpp b/src/Object/LuaBindings/lua_textureIO.cpp index 121582d6..1c1e0176 100644 --- a/src/Object/LuaBindings/lua_textureIO.cpp +++ b/src/Object/LuaBindings/lua_textureIO.cpp @@ -9,16 +9,11 @@ namespace Hop::Object int EntityComponentSystem::lua_setTextureRegion(lua_State * lua) { + int status = lua_checkArgumentCount(lua, 5, "expected id, tx, ty, lx, ly as argument"); + if (status != LUA_OK) { return status; } LuaString sid; LuaNumber tx, ty, lx, ly; - int n = lua_gettop(lua); - if (n != 5) - { - lua_pushliteral(lua,"expected id, tx, ty, lx, ly as argument"); - return lua_error(lua); - } - sid.read(lua, 1); Id id(sid.characters); @@ -38,15 +33,10 @@ namespace Hop::Object int EntityComponentSystem::lua_getTextureRegion(lua_State * lua) { + int status = lua_checkArgumentCount(lua, 1, "expected id as argument"); + if (status != LUA_OK) { return status; } LuaString sid; - int n = lua_gettop(lua); - if (n != 1) - { - lua_pushliteral(lua,"expected id as argument"); - return lua_error(lua); - } - sid.read(lua, 1); Id id(sid.characters); @@ -60,15 +50,10 @@ namespace Hop::Object int EntityComponentSystem::lua_setTexturePath(lua_State * lua) { + int status = lua_checkArgumentCount(lua, 2, "expected id and path as argument"); + if (status != LUA_OK) { return status; } LuaString sid, path; - int n = lua_gettop(lua); - if (n != 2) - { - lua_pushliteral(lua,"expected id and path as argument"); - return lua_error(lua); - } - sid.read(lua, 1); path.read(lua, 2); @@ -80,15 +65,10 @@ namespace Hop::Object int EntityComponentSystem::lua_getTexturePath(lua_State * lua) { + int status = lua_checkArgumentCount(lua, 1, "expected id as argument"); + if (status != LUA_OK) { return status; } LuaString sid; - int n = lua_gettop(lua); - if (n != 1) - { - lua_pushliteral(lua,"expected id as argument"); - return lua_error(lua); - } - sid.read(lua, 1); Id id(sid.characters); diff --git a/src/Object/LuaBindings/lua_transformIO.cpp b/src/Object/LuaBindings/lua_transformIO.cpp index efd5ef47..29ee28bc 100644 --- a/src/Object/LuaBindings/lua_transformIO.cpp +++ b/src/Object/LuaBindings/lua_transformIO.cpp @@ -9,17 +9,10 @@ namespace Hop::Object int EntityComponentSystem::lua_getTransform(lua_State * lua) { - + int status = lua_checkArgumentCount(lua, 1, "expected id as argument"); + if (status != LUA_OK) { return status; } LuaString sid; - int n = lua_gettop(lua); - - if (n != 1) - { - lua_pushliteral(lua,"expected id as argument"); - return lua_error(lua); - } - sid.read(lua, 1); Id id(sid.characters); diff --git a/src/System/Rendering/sRender.cpp b/src/System/Rendering/sRender.cpp index a4490078..9eaef464 100644 --- a/src/System/Rendering/sRender.cpp +++ b/src/System/Rendering/sRender.cpp @@ -9,6 +9,7 @@ namespace Hop::System::Rendering AbstractWorld * world ) { + sprites->setProjection(projection); if (world != nullptr) { @@ -38,33 +39,58 @@ namespace Hop::System::Rendering { ComponentArray & spriteComponents = ecs->getComponentArray(); ComponentArray & renderables = ecs->getComponentArray(); + ComponentArray & transforms = ecs->getComponentArray(); for (const auto & object : objects) { - if (renderables.hasComponent(object) && spriteComponents.hasComponent(object)) + if (renderables.hasComponent(object) && spriteComponents.hasComponent(object) && transforms.hasComponent(object)) { const cSprite & oSprite = spriteComponents.get(object); const cRenderable & oRenderable = renderables.get(object); + const cTransform & oTransform = transforms.get(object); std::string sid = to_string(object); + auto tex = textures->get(oSprite.texturePath); + auto region = jGL::TextureRegion + ( + oSprite.tx, + oSprite.ty, + oSprite.lx, + oSprite.ly + ); + if (sprites->hasId(sid)) { auto & sprite = sprites->getSprite(sid); - auto tex = textures->get(oSprite.texturePath); if (!(tex->getId() == sprite.texture->getId())) { sprites->remove(sid); - sprites->add(sprite, sid, oRenderable.priority); + sprites->add( + jGL::Sprite(oTransform, region, tex, oRenderable.a), + sid, + oRenderable.priority + ); } - sprites->updatePriority(sid, oRenderable.priority); - sprite.setAlpha(oRenderable.a); - sprite.setTextureRegion - ( - jGL::TextureRegion + else + { + sprites->updatePriority(sid, oRenderable.priority); + sprite.setAlpha(oRenderable.a); + sprite.setTextureRegion ( - oSprite.tx, - oSprite.ty, - oSprite.lx, - oSprite.ly - ) + jGL::TextureRegion + ( + oSprite.tx, + oSprite.ty, + oSprite.lx, + oSprite.ly + ) + ); + } + } + else + { + sprites->add( + jGL::Sprite(oTransform, region, tex, oRenderable.a), + sid, + oRenderable.priority ); } } From d12666fa494cf2b29800441874f74558a514cd68 Mon Sep 17 00:00:00 2001 From: Jerboa-app Date: Thu, 22 Aug 2024 07:56:38 +0100 Subject: [PATCH 3/5] Review --- src/System/Rendering/sRender.cpp | 55 +++++++++++++++++--------------- tests/regression/assets/main.cpp | 2 +- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/System/Rendering/sRender.cpp b/src/System/Rendering/sRender.cpp index 9eaef464..4f326601 100644 --- a/src/System/Rendering/sRender.cpp +++ b/src/System/Rendering/sRender.cpp @@ -2,40 +2,44 @@ namespace Hop::System::Rendering { - double sRender::draw - ( - std::shared_ptr jgl, - EntityComponentSystem * ecs, - AbstractWorld * world - ) + double sRender::draw + ( + std::shared_ptr jgl, + EntityComponentSystem * ecs, + AbstractWorld * world + ) + { + if (world != nullptr) { - sprites->setProjection(projection); + world->draw(); + } - if (world != nullptr) + if (drawCollisionMeshPoints) + { + if (collisionMeshDebug == nullptr) { - world->draw(); - } - - if (drawCollisionMeshPoints) - { - if (collisionMeshDebug == nullptr) - { - collisionMeshDebug = std::move(std::make_unique(jgl)); - } - collisionMeshDebug->refreshMeshes(); - collisionMeshDebug->drawMeshes(ecs, projection); + collisionMeshDebug = std::move(std::make_unique(jgl)); } + collisionMeshDebug->refreshMeshes(); + collisionMeshDebug->drawMeshes(ecs, projection); + } + if (sprites != nullptr) + { + sprites->setProjection(projection); sprites->draw(); + } - auto t = std::chrono::high_resolution_clock::now(); - accumulatedTime += std::chrono::duration_cast>(t-clock).count(); - clock = t; + auto t = std::chrono::high_resolution_clock::now(); + accumulatedTime += std::chrono::duration_cast>(t-clock).count(); + clock = t; - return accumulatedTime; - } + return accumulatedTime; + } - void sRender::update(EntityComponentSystem * ecs) + void sRender::update(EntityComponentSystem * ecs) + { + if (sprites != nullptr) { ComponentArray & spriteComponents = ecs->getComponentArray(); ComponentArray & renderables = ecs->getComponentArray(); @@ -96,4 +100,5 @@ namespace Hop::System::Rendering } } } + } } \ No newline at end of file diff --git a/tests/regression/assets/main.cpp b/tests/regression/assets/main.cpp index afe44d1c..e063512c 100644 --- a/tests/regression/assets/main.cpp +++ b/tests/regression/assets/main.cpp @@ -10,7 +10,7 @@ int main(int argc, char ** argv) jGL::DesktopDisplay display(glm::ivec2(1,1),"Test TextureAssetStore", conf); glewInit(); - std::unique_ptr jGLInstance = std::move(std::make_unique(display.getRes())); + std::shared_ptr jGLInstance = std::move(std::make_shared(display.getRes())); Hop::Util::Assets::TextureAssetStore textureStore(std::filesystem::path("resource"), jGLInstance); textureStore.scan(); for (auto tex : textureStore) From 5cf7d254d3891bce6a3ea9744e807541e5287204 Mon Sep 17 00:00:00 2001 From: Jerboa-app Date: Thu, 22 Aug 2024 08:01:39 +0100 Subject: [PATCH 4/5] uint16_t --- include/Component/cSprite.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/Component/cSprite.h b/include/Component/cSprite.h index cbc0e7cf..9231aa2f 100644 --- a/include/Component/cSprite.h +++ b/include/Component/cSprite.h @@ -21,10 +21,10 @@ namespace Hop::Object::Component cSprite ( std::string path, - u_int16_t tx, - u_int16_t ty, - u_int16_t lx, - u_int16_t ly + uint16_t tx, + uint16_t ty, + uint16_t lx, + uint16_t ly ) : texturePath(path), tx(tx), ty(ty), lx(lx), ly(ly) {} From ab22df5a7fc434af43d883e707412bc25c8bd844 Mon Sep 17 00:00:00 2001 From: Jerboa <84378622+Jerboa-app@users.noreply.github.com> Date: Thu, 22 Aug 2024 08:25:25 +0100 Subject: [PATCH 5/5] Update README.md --- README.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 405d452e..794b489c 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,70 @@ # Hop -A lightweight 2D game engine, in C++ with embedded Lua +#### A lightweight 2D game engine, in C++ with embedded Lua ### Features -- Free, MIT open sourced -- Use as a standalone (GLFW based) engine or as a drop in component (e.g. with SFML) -- Entity component system (ECS) based -- Rigid and soft body physics (Discrete element method) -- OpenGL rendering (provided by jGL, Vulkan is a WIP) -- Perlin (marching squares) and Tile map, editable tile based worlds -- Lua console, interoperating with the ECS, physics, and rendering systems +- Free, MIT open sourced.. +- Use as a standalone engine or as a drop in component (e.g. with SFML).. +- Entity component system (ECS) based. +- Physics (Discrete element method): + - [x] collision primitives (circles, rects). + - [x] collision meshes built from primitives (rigid and soft). + - [x] configurable friction, gravity, drag, and restitution. + - [x] super-sampling. + - [ ] (good) multithreading. + - [x] Cell list collision detection. + - [ ] Quad tree collision detection. + - [x] Object-object and object-world collisions. + - [ ] collision islands and other optimisations. +- Rendering (provided by jGL, Vulkan is a WIP): + - [x] OpenGL. + - [ ] Vulkan. + - [x] sprites (atlasing, and animateable atlases). + - [x] collision primitives (circles/rects). + - [x] Freetype fonts. + - [ ] shapes (it is in jGL). + - [ ] lightmaps and shadows. + - [x] msaa. + - [ ] particle effects (it is in jGL). + - [x] texture management. + - [ ] (compressed) texture asset packs. + - [ ] Engine UI (Dear ImGui). +- Window management: + - [x] Single window creation. + - [ ] Multi-window. + - [x] Key and mouse events. + - [x] Frame limiting. + - [ ] Snapping and resizing. + - [x] Screenspace bbs. +- Worlds: + - [x] Perlin (marching squares). + - [x] Tile maps. + - [x] object-world collisions. + - [ ] editable. + - [x] saveable. + - [ ] tile textures. +- Lua console + - [x] ECS bindings (object management). + - [x] Compressed script asset archive support. + - [ ] Live in game console +- Cross platform: + - [x] Linux. + - [x] Windows. + - [x] macOS. + - [x] Android. + - [ ] IOS (mostly held up by jGL rendering). +- Tooling + - [x] mesh editor. + - [x] Lua script packer. + - [ ] World editor. + - [ ] Texture packer. -### Setup +### Documentation + +Checkout the docs [here](https://jerboaburrow.github.io/Hop/), and also the jGL docs [here](https://jerboaburrow.github.io/jGL/) + +### Setup - clone, and init the submodules (you can use ```submodules.sh```) - the ```build.sh``` can be used to build @@ -21,7 +73,7 @@ A lightweight 2D game engine, in C++ with embedded Lua - Freetype is licensed under the The FreeType Project LICENSE - GLEW is licensed under aModified BSD License, the Mesa 3-D License (MIT) and the Khronos License (MIT). -- GLFW is licensed under the zlib/libpng +- GLFW is licensed under the zlib/libpng - GLM is licensed under the MIT License (but also, no bunnies have been made unhappy) - Lua is licensed under the MIT license - Miniaudio is licensed under the MIT-0 license @@ -29,4 +81,4 @@ A lightweight 2D game engine, in C++ with embedded Lua - vorbis and ogg is licensed under a BSD license - zlib is licensed under the zlib license -We thank: David Turner, Robert Wilhelm, and Werner Lemberg (Freetype), Milan Ikits , Marcelo E. Magallon , and Lev Povalahev Brian Paul, The Khronos Group Inc (GLEW), Marcus Geelnard and Camilla Löwy (GLFW), G-Truc Creation (GLM), Lua.org, PUC-Rio (Lua), David Reid (Miniaudio), Marius Bancila https://github.com/mariusbancila/stduuid#MIT-1-ov-file (stduuid), Xiph.org Foundation (vorbis, ogg), and Jean-loup Gailly and Mark Adler (zlib). +Thanks to all the OSS developers: David Turner, Robert Wilhelm, and Werner Lemberg (Freetype), Milan Ikits , Marcelo E. Magallon , and Lev Povalahev Brian Paul, The Khronos Group Inc (GLEW), Marcus Geelnard and Camilla Löwy (GLFW), G-Truc Creation (GLM), Lua.org, PUC-Rio (Lua), David Reid (Miniaudio), Marius Bancila https://github.com/mariusbancila/stduuid#MIT-1-ov-file (stduuid), Xiph.org Foundation (vorbis, ogg), and Jean-loup Gailly and Mark Adler (zlib).