]> code.bitgloo.com Git - clyne/gamedev.git/commitdiff
component reorginization; entity flashes
authorClyne Sullivan <tullivan99@gmail.com>
Wed, 14 Jun 2017 01:01:08 +0000 (21:01 -0400)
committerClyne Sullivan <tullivan99@gmail.com>
Wed, 14 Jun 2017 01:01:08 +0000 (21:01 -0400)
35 files changed:
Makefile
include/components.hpp
include/components/aggro.hpp [new file with mode: 0644]
include/components/all.hpp
include/components/animate.hpp [new file with mode: 0644]
include/components/dialog.hpp [new file with mode: 0644]
include/components/direction.hpp [new file with mode: 0644]
include/components/flash.hpp [new file with mode: 0644]
include/components/grounded.hpp [new file with mode: 0644]
include/components/health.hpp [new file with mode: 0644]
include/components/hit.hpp [new file with mode: 0644]
include/components/hop.hpp [new file with mode: 0644]
include/components/itemdrop.hpp [new file with mode: 0644]
include/components/name.hpp [new file with mode: 0644]
include/components/physics.hpp [new file with mode: 0644]
include/components/player.hpp [new file with mode: 0644]
include/components/portal.hpp [new file with mode: 0644]
include/components/position.hpp [new file with mode: 0644]
include/components/solid.hpp [new file with mode: 0644]
include/components/sprite.hpp [new file with mode: 0644]
include/components/trigger.hpp [new file with mode: 0644]
include/components/visible.hpp [new file with mode: 0644]
include/components/wander.hpp [new file with mode: 0644]
include/systems/dialog.hpp [new file with mode: 0644]
include/systems/movement.hpp [new file with mode: 0644]
include/systems/physics.hpp [new file with mode: 0644]
include/systems/render.hpp [new file with mode: 0644]
src/components.cpp [deleted file]
src/components/animate.cpp [new file with mode: 0644]
src/components/sprite.cpp [new file with mode: 0644]
src/engine.cpp
src/systems/dialog.cpp [new file with mode: 0644]
src/systems/movement.cpp [new file with mode: 0644]
src/systems/physics.cpp [new file with mode: 0644]
src/systems/render.cpp [new file with mode: 0644]

index 6aa05e2ebebf196561d5ec0b9119eea302955353..4372c312168b43be00f74b85c439d004d9e439aa 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -18,8 +18,12 @@ CXXWARN  = -Wall -Wextra -Werror -pedantic
 
 CXXSRCDIR = src
 CXXOUTDIR = out
-CXXSRC    = $(wildcard $(CXXSRCDIR)/*.cpp)
-CXXOBJ    = $(patsubst $(CXXSRCDIR)/%.cpp, $(CXXOUTDIR)/%.o, $(CXXSRC))
+CXXSRC    = $(wildcard $(CXXSRCDIR)/*.cpp) \
+                       $(wildcard $(CXXSRCDIR)/systems/*.cpp) \
+                       $(wildcard $(CXXSRCDIR)/components/*.cpp)
+CXXOBJ    = $(patsubst $(CXXSRCDIR)/%.cpp, $(CXXOUTDIR)/%.o, $(CXXSRC)) \
+                       $(patsubst $(CXXSRCDIR)/systems/%.cpp, $(CXXOUTDIR)/systems/%.o, $(CXXSRC)) \
+                       $(patsubst $(CXXSRCDIR)/components/%.cpp, $(CXXOUTDIR)/components/%.o, $(CXXSRC))
 
 EXEC = main
 
@@ -28,18 +32,23 @@ all: SPECIAL:=-ggdb game
 game: $(EXEC)
 
 clean:
-       rm -f $(EXEC)
-       rm -f out/*.o
+       @echo "  CLEAN"
+       @rm -f $(EXEC)
+       @rm -rf out
+       @mkdir out
+       @mkdir out/systems
+       @mkdir out/components
 
 $(EXEC): $(CXXOUTDIR)/$(CXXOBJ) main.cpp
-       g++ -I. -std=c++11 -c entityx/help/Pool.cc -o out/Pool.o
-       g++ -I. -std=c++11 -c entityx/help/Timer.cc -o out/Timer.o
-       g++ -I. -std=c++11 -c entityx/Event.cc -o out/Event.o
-       g++ -I. -std=c++11 -c entityx/Entity.cc -o out/Entity.o
-       g++ -I. -std=c++11 -c entityx/System.cc -o out/System.o
+       @echo "  CXX     entityx"
+       @g++ -I. -std=c++11 -c entityx/help/Pool.cc -o out/Pool.o
+       @g++ -I. -std=c++11 -c entityx/help/Timer.cc -o out/Timer.o
+       @g++ -I. -std=c++11 -c entityx/Event.cc -o out/Event.o
+       @g++ -I. -std=c++11 -c entityx/Entity.cc -o out/Entity.o
+       @g++ -I. -std=c++11 -c entityx/System.cc -o out/System.o
        
        @echo "  CXX/LD  main"
-       @$(CXX) $(SPECIAL) $(CXXFLAGS) $(CXXINC) $(CXXWARN) -o $(EXEC) main.cpp out/*.o $(LIBS)
+       @$(CXX) $(SPECIAL) $(CXXFLAGS) $(CXXINC) $(CXXWARN) -o $(EXEC) main.cpp out/components/*.o out/systems/*.o out/*.o $(LIBS)
        @rm -rf xml/*.dat
        @rm -rf storyXML/*.dat
 
index fe8e7a60f6f49d2a64bed521e2c27f913bb36068..93d7196b0a84cd0637aff9f2446cdad66fcbafc9 100644 (file)
 #ifndef COMPONENTS_HPP
 #define COMPONENTS_HPP
 
-#include <string>
-#include <vector>
-
-#include <error.hpp>
-#include <events.hpp>
-#include <inventory.hpp>
-#include <random.hpp>
-#include <texture.hpp>
-#include <vector2.hpp>
-
-#include <entityx/entityx.h>
-#include <tinyxml2.h>
-using namespace tinyxml2;
-
-//  TODO heyyy guys
 #include <components/all.hpp>
 
-/**
- * @struct Position
- * @brief Stores the position of an entity on the xy plane.
- */
-struct Position : public Component {
-       /**
-        * Constructor that sets the position of the object, if nothing is passed it will default to 0.
-        * @param x The x position the object will be placed at.
-        * @param y the y position the object will be placed at.
-        */
-       Position(float x = 0.0f, float y = 0.0f): x(x), y(y) {}
-       Position(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       float x; /**< The x position in the world */
-       float y; /**< The y position in the world */
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               vec2 c;
-               if (imp->Attribute("position") != nullptr)
-                       c = imp->StrAttribute("position");
-               else
-                       c = def->StrAttribute("value");
-
-               x = c.x, y = c.y;
-       }
-};
-
-/**
- * @struct Direction
- * @brief Store an entities velocity.
- * This allows the entity to move throughout the world.
- */
-struct Direction : public Component {
-       /**
-        * Constructor that sets the velocity, if no position is passed, it defaults to (0,0).
-        * @param x The velocity of the object on the x axis.
-        * @param y The velocity of the object on the y axis.
-        */
-       Direction(float x = 0.0f, float y = 0.0f): x(x), y(y), grounded(false) {}
-       Direction(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       float x; /**< Velocity the object is moving in the x direction, this is added to the position */
-       float y; /**< Velocity the object is moving in the y direction, this is added to the position */
-       bool grounded;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               vec2 c;
-               if (imp->Attribute("direction") != nullptr) {
-                       c = imp->StrAttribute("direction");
-               } else if (def->Attribute("value") != nullptr) {
-                       c = def->StrAttribute("value");
-               } else {
-                       c = vec2(0, 0);
-               }
-
-               x = c.x, y = c.y, grounded = false;
-       }
-};
-
-/**
- * @struct Physics
- * @brief Allows and entity to react to gravity and frictions.
- * When an entity inherits this component it will react with gravity and move with friction.
- */
-struct Physics : public Component {
-       /**
-        * Constructor that sets the gravity constant, if not specified it becomes 0.
-        * @param g The non default gravity constant.
-        */
-       Physics(float g = 0.2f): g(g) {}
-       Physics(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       float g; /**< The gravity constant, how fast the object falls */
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               if (imp->QueryFloatAttribute("gravity", &g) != XML_NO_ERROR) {
-                       if (def->QueryFloatAttribute("value", &g) != XML_NO_ERROR)
-                               g = 0.2f;
-               }
-       }
-};
-
-/**
- * @struct Grounded
- * @brief Places an entity without physics on the ground.
- * This is used so we don't have to update the physics of a non-moving object every loop.
- */
-struct Grounded : public Component {
-       Grounded(bool g = false)
-               : grounded(g) {}
-       Grounded(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       bool grounded;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               (void)def;
-               grounded = false;
-       }
-};
-
-/**
- * @struct Health
- * @brief Gives and entity health and stuff.
- */
-struct Health : public Component {
-       /**
-        * Constructor that sets the variables, with 1 health as default.
-        */
-       Health(int m = 1, int h = 0)
-               : health(h != 0 ? h : m), maxHealth(m) {}
-       Health(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       int health; /**< The current amount of health */
-       int maxHealth; /**< The maximum amount of health */
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               (void)def;
-               // TODO
-               if (def->QueryIntAttribute("value", &health) != XML_NO_ERROR)
-                       health = 1;
-               maxHealth = health;
-       }
-};
-
-struct Portal : public Component {
-       Portal(std::string tf = "")
-               : toFile(tf) {}
-       Portal(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       std::string toFile;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)def;
-               toFile = imp->StrAttribute("inside");
-       }
-};
-
-struct Name : public Component {
-       Name(std::string n = "")
-               : name(n) {}
-       Name(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       std::string name;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               auto n = imp->Attribute("name");
-
-               // TODO check def's nullness    
-               name = n != nullptr ? n : def->Attribute("value");
-       }
-};
-
-struct Player {};
-
-struct ItemDrop {
-       ItemDrop(InventoryEntry& ie)
-               : item(ie) {}
-
-       InventoryEntry item;
-};
-
-/**
- * @struct Solid
- * @brief Allows an entity to collide with other objects.
- * When an entity has this component it can collide with the world and other objects.
- */
-struct Solid : public Component {
-       /**
-        * Constructor that sets the entities dimensions based on what is passed.
-        * @param w The desired width of the entity.
-        * @param h The desired height of the entity.
-        */
-       Solid(float w = 0.0f, float h = 0.0f)
-               : width(w), height(h), offset(0), passable(true) {}
-       Solid(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       void Passable(bool v) { passable = v; }
-       bool Passable(void)   { return passable; }
-
-       float width; /**< The width of the entity in units */
-       float height; /**< The height of the entity in units */
-       vec2 offset; /**< This allows us to make the hitbox in any spot */
-       bool passable; /**< This determines whether or not one can pass by the entity */
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               vec2 c;
-               if (def->Attribute("value") != nullptr)
-                       c = def->StrAttribute("value");
-               else
-                       c = vec2(0, 0);
-
-               width = c.x, height = c.y, offset = 0, passable = true;
-       }
-};
-
-struct SpriteData {
-       SpriteData(void) = default;
-       
-       SpriteData(std::string path, vec2 off):
-               offset(off)     {
-                       tex = Texture(path);
-                       size = tex.getDim();
-
-                       size_tex = vec2(1.0, 1.0);
-                       
-                       offset_tex.x = offset.x/size.x;
-                       offset_tex.y = offset.y/size.y;
-       }
-
-       SpriteData(std::string path, vec2 off, vec2 si):
-               size(si), offset(off) {
-                       tex = Texture(path);
-                       vec2 tmpsize = tex.getDim();
-
-                       size_tex.x = size.x/tmpsize.x;
-                       size_tex.y = size.y/tmpsize.y;
-                       
-                       offset_tex.x = offset.x/tmpsize.x;
-                       offset_tex.y = offset.y/tmpsize.y;
-       }
-
-       SpriteData(Texture t)
-               : tex(t) {
-               size_tex = 1;
-               offset_tex = 0;
-               size = tex.getDim();
-               offset = 0;
-       }
-
-       Texture tex;
-       vec2 size;
-       vec2 offset;
-       
-       vec2 offset_tex;
-       vec2 size_tex;
-
-       unsigned int limb;
-};
-
-using Frame = std::vector<std::pair<SpriteData, vec2>>;
-
-std::vector<Frame> developFrame(XMLElement*);
-
-/**
- * @struct Sprite
- * @brief If an entity is visible we want to be able to see it.
- * Each entity is given a sprite, a sprite can consist of manu frames or pieces to make one.
- */
-struct Sprite : public Component {
-       Sprite(bool left = false)
-               : faceLeft(left) {}
-       Sprite(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       Frame getSprite() {
-               return sprite;
-       }
-
-       int clearSprite() {
-               if (sprite.empty())
-                       return 0;
-
-               sprite.clear();
-               return 1;
-       }
-
-       int addSpriteSegment(SpriteData data, vec2 loc) {
-               //TODO if sprite is in this spot, do something
-               sprite.push_back(std::make_pair(data, loc));
-               return 1;
-       }
-
-       int changeSpriteSegment(SpriteData data, vec2 loc) {
-               for (auto &s : sprite) {
-                       if (s.second == loc) {
-                               s.first = data;
-
-                               return 1;
-                       }
-               }
-               addSpriteSegment(data, loc);
-               return 0;
-       }
-
-       vec2 getSpriteSize() {
-               vec2 st; /** the start location of the sprite (bottom left)*/
-               vec2 ed; /** the end ofthe location of the sprite (bottom right)*/
-               vec2 dim; /** how wide the sprite is */
-
-               if (sprite.size()) {
-                       st.x = sprite[0].second.x;
-                       st.y = sprite[0].second.y;
-
-                       ed.x = sprite[0].second.x + sprite[0].first.size.x;
-                       ed.y = sprite[0].second.y + sprite[0].first.size.y;
-               } else {
-                       return vec2(0.0f, 0.0f);
-               }
-
-               for (auto &s : sprite) {
-                       if (s.second.x < st.x)
-                               st.x = s.second.x;
-                       if (s.second.y < st.y)
-                               st.y = s.second.y;
-
-                       if (s.second.x + s.first.size.x > ed.x)
-                               ed.x = s.second.x + s.first.size.x;
-                       if (s.second.y + s.first.size.y > ed.y)
-                               ed.y = s.second.y + s.first.size.y;
-               }
-
-               dim = vec2(ed.x - st.x, ed.y - st.y);
-               dim.x *= game::HLINE;
-               dim.y *= game::HLINE;
-               return dim;
-       }
-
-       Frame sprite;
-       bool faceLeft;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               auto frames = developFrame(def);
-               if (!frames.empty())
-                       sprite = frames.at(0);
-       }
-};
-
-/**
- * @struct Limb
- * @brief Storage of frames for the limbs of a sprite.
- * This will allow us to only update a certain limb. This was we can do mulitple animation types at once.
- */
-struct Limb {
-       Limb() {
-       }
-
-       // adds frame to the back of the frame stack
-       void addFrame(Frame fr) {
-               frame.push_back(fr);
-       }
-
-       void firstFrame(Frame& duckmyass) {
-               // loop through the spritedata of the sprite we wanna change
-               for (auto &d : duckmyass) {
-                       // if the sprite data is the same limb as this limb
-                       if (d.first.limb == limbID) {
-                               // rotate through (for safety) the first frame to set the limb
-                               for (auto &fa : frame.at(0)) {
-                                       if (fa.first.limb == limbID) {
-                                               d.first = fa.first;
-                                               d.second = fa.second;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       void nextFrame(Frame& duckmyass, float dt) {
-               updateCurrent -= dt;
-               if (updateCurrent <= 0) {
-                       updateCurrent = updateRate;
-               } else {
-                       return;
-               }
-
-
-               if (index < frame.size() - 1)
-                       index++;
-               else
-                       index = 0;
-               
-               for (auto &d : duckmyass) {
-                       if (d.first.limb == limbID) {
-                               for (auto &fa : frame.at(index)) {
-                                       if (fa.first.limb == limbID) {
-                                               d.first = fa.first;
-                                               d.second = fa.second;
-                                       }
-                               }
-                       }
-               }
-
-       }
-
-       float updateRate; /**< How often we will change each frame. */
-       float updateCurrent = 0; /**< How much has been updated in the current frame. */
-       unsigned int updateType; /**< What the updateRate will base it's updates off of.
-                                               ie: Movement, attacking, jumping. */
-       unsigned int limbID; /**< The id of the limb we will be updating */
-       
-       unsigned int index = 0; /**< The current sprite being used for the limb. */
-
-       std::vector<Frame> frame; /**< The multiple frames of each limb. */
-};
-
-//TODO kill clyne
-struct Animate : public Component {
-       // COMMENT
-       std::vector<Limb> limb;
-       // COMMENT      
-       unsigned int index;
-
-       Animate(){
-               index = 0;
-       }
-
-       Animate(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       // COMMENT
-
-       void firstFrame(unsigned int updateType, Frame &sprite) {
-               unsigned int upid = updateType; //^see todo
-               for (auto &l : limb) {
-                       if (l.updateType == upid) {
-                               l.firstFrame(sprite);
-                       }
-               }
-       }
-        //TODO make updateType an enum
-       void updateAnimation(unsigned int updateType, Frame& sprite, float dt) {
-               unsigned int upid = updateType; //^see todo
-               for (auto &l : limb) {
-                       if (l.updateType == upid) {
-                               l.nextFrame(sprite, dt);
-                       }
-               }
-       }
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-
-               auto animx = def->FirstChildElement();
-               uint limbid = 0;
-               float limbupdate = 0;
-               uint limbupdatetype = 0;
-
-               while (animx != nullptr) {
-                       if (std::string(animx->Name()) == "movement") {
-                               limbupdatetype = 1;
-
-                               auto limbx = animx->FirstChildElement();
-                               while (limbx != nullptr) {
-                                       if (std::string(limbx->Name()) == "limb") {
-                                               auto frames = developFrame(limbx);
-                                               limb.push_back(Limb());
-                                               auto& newLimb = limb.back();
-                                               newLimb.updateType = limbupdatetype;
-
-                                               if (limbx->QueryUnsignedAttribute("id", &limbid) == XML_NO_ERROR)
-                                                       newLimb.limbID = limbid;
-                                               if (limbx->QueryFloatAttribute("update", &limbupdate) == XML_NO_ERROR)
-                                                       newLimb.updateRate = limbupdate;
-                                                               
-                                               // place our newly developed frames in the entities animation stack
-                                               for (auto &f : frames) {
-                                                       newLimb.addFrame(f);
-                                                       for (auto &fr : newLimb.frame) {
-                                                               for (auto &sd : fr)
-                                                                       sd.first.limb = limbid;
-                                                       }
-                                               }
-                                       }
-
-                                       limbx = limbx->NextSiblingElement();
-                               }
-                       }
-                               
-                       animx = animx->NextSiblingElement();
-               }
-       }
-};
-
-/**
- * @struct Visible
- * @brief If an entity is visible we want to be able to draw it.
- */
-struct Visible : public Component {
-       /**
-        * @brief Decide what layer to draw the entity on.
-        * When stuff is drawn, it is drawn on a "layer". This layer gives more of a 3D effect to the world.
-        * @param z The desired "layer" of the entity.
-        */
-       Visible(float z = 0.0f): z(z) {}
-       Visible(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       float z; /**< The value along the z axis the entity will be drawn on */
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               if (def->QueryFloatAttribute("value", &z) != XML_NO_ERROR)
-                       z = 0;
-       }
-};
-
-struct Dialog : public Component {
-       Dialog(int idx = 0)
-               : index(idx), rindex((idx == 9999) ? randGet() : idx), talking(false) {}
-       Dialog(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       int index;
-       int rindex;
-       bool talking;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)def;
-               bool hasDialog;
-               if (imp->QueryBoolAttribute("hasDialog", &hasDialog) != XML_NO_ERROR)
-                       hasDialog = false;
-
-               index = hasDialog ? 0 : 9999;
-               rindex = (index == 9999) ? randGet() : index;
-               talking = false;
-       }
-};
-
-// movement styles
-
-/**
- * Causes the entity to hop around.
- */
-struct Hop {
-       Hop(float r = 0)
-               : hopRatio(r) {}
-
-       float hopRatio;
-};
-
-/**
- * Causes the entity to wander about.
- */
-struct Wander {
-       Wander(float ix = 0, float r = 0)
-               : initialX(ix), range(r), countdown(0) {}
-
-       float initialX;
-       float range;
-       int countdown;
-};
-
-/**
- * Causes the entity to get mad at the player, charge and fight.
- */
-struct Aggro : public Component {
-       Aggro(const std::string& a)
-               : arena(a) {}
-       Aggro(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       std::string arena;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               // TODO null check..?, imp given
-               arena = def->StrAttribute("arena");
-       }
-};
-
-struct Hit : public Component {
-       Hit(int d, bool p = false)
-               : damage(d), pierce(p) {}
-
-       int damage;
-       bool pierce;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               (void)def;
-       }
-};
-
-struct Trigger : public Component {
-       Trigger(const std::string& t)
-               : text(t) {}
-       Trigger(XMLElement* imp, XMLElement* def) {
-               fromXML(imp, def);
-       }
-
-       std::string text;
-
-       void fromXML(XMLElement* imp, XMLElement* def) final {
-               (void)imp;
-               (void)def;
-               text = "You got me!";
-       }
-};
-
-/**
- * SYSTEMS
- */
-
-class MovementSystem : public entityx::System<MovementSystem> {
-public:
-       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
-};
-
-class PhysicsSystem : public entityx::System<PhysicsSystem> {
-public:
-       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
-};
-
-class RenderSystem : public entityx::System<RenderSystem> {
-private:
-       static std::string loadTexString;
-       static Texture loadTexResult;
-
-public:
-       static Texture loadTexture(const std::string& file);
-       static void render(void);
-
-       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override
-       { (void)en; (void)ev; (void)dt; }
-};
-
-class DialogSystem : public entityx::System<DialogSystem>, public entityx::Receiver<DialogSystem> {
-public:
-       void configure(entityx::EventManager&);
-       void receive(const MouseClickEvent&);
-       void update(entityx::EntityManager&, entityx::EventManager&, entityx::TimeDelta) override;
-};
+#include <systems/dialog.hpp>
+#include <systems/movement.hpp>
+#include <systems/physics.hpp>
+#include <systems/render.hpp>
 
 #endif //COMPONENTS_HPP
diff --git a/include/components/aggro.hpp b/include/components/aggro.hpp
new file mode 100644 (file)
index 0000000..17d646c
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef COMPONENTS_AGGRO_HPP_
+#define COMPONENTS_AGGRO_HPP_
+
+#include "base.hpp"
+
+/**
+ * Causes the entity to get mad at the player, charge and fight.
+ */
+struct Aggro : public Component {
+       Aggro(const std::string& a)
+               : arena(a) {}
+       Aggro(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       std::string arena;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               // TODO null check..?, imp given
+               arena = def->StrAttribute("arena");
+       }
+};
+
+#endif // COMPONENTS_AGGRO_HPP_
index 2fb3c8d083fda48f4622a160328b645e18e8d67b..dda89382660efb14d447070332a5419e75b86ddb 100644 (file)
@@ -1,7 +1,26 @@
 #ifndef COMPONENTS_ALL_HPP_
 #define COMPONENTS_ALL_HPP_
 
+#include "aggro.hpp"
+#include "animate.hpp"
 #include "damage.hpp"
+#include "dialog.hpp"
+#include "direction.hpp"
 #include "drop.hpp"
+#include "grounded.hpp"
+#include "health.hpp"
+#include "hit.hpp"
+#include "hop.hpp"
+#include "itemdrop.hpp"
+#include "name.hpp"
+#include "physics.hpp"
+#include "player.hpp"
+#include "portal.hpp"
+#include "position.hpp"
+#include "solid.hpp"
+#include "sprite.hpp"
+#include "trigger.hpp"
+#include "visible.hpp"
+#include "wander.hpp"
 
 #endif // COMPONENTS_ALL_HPP_
diff --git a/include/components/animate.hpp b/include/components/animate.hpp
new file mode 100644 (file)
index 0000000..116ee3f
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef COMPONENTS_ANIMATE_HPP_
+#define COMPONENTS_ANIMATE_HPP_
+
+#include "base.hpp"
+
+#include <components/sprite.hpp>
+
+#include <vector>
+
+/**
+ * @struct Limb
+ * @brief Storage of frames for the limbs of a sprite.
+ * This will allow us to only update a certain limb. This was we can do mulitple animation types at once.
+ */
+struct Limb {
+       Limb(void) {} // TODO necessary?
+
+       // adds frame to the back of the frame stack
+       inline void addFrame(Frame fr) {
+               frame.push_back(fr);
+       }
+
+       void firstFrame(Frame& duckmyass);
+       void nextFrame(Frame& duckmyass, float dt); 
+
+       /**< How often we will change each frame. */
+       float updateRate;
+
+       /**< How much has been updated in the current frame. */
+       float updateCurrent = 0; 
+
+       /**< What the updateRate will base it's updates off of. ie: Movement, attacking, jumping. */
+       unsigned int updateType;
+
+       /**< The id of the limb we will be updating */
+       unsigned int limbID;
+       
+       /**< The current sprite being used for the limb. */
+       unsigned int index = 0;
+
+       /**< The multiple frames of each limb. */
+       std::vector<Frame> frame;
+};
+
+struct Animate : public Component {
+       // COMMENT
+       unsigned int index;
+       // COMMENT      
+       std::vector<Limb> limb;
+
+       Animate(void)
+               : index(0) {}
+       Animate(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       // COMMENT
+       void firstFrame(unsigned int updateType, Frame &sprite);
+       //TODO make updateType an enum
+       void updateAnimation(unsigned int updateType, Frame& sprite, float dt);
+       void fromXML(XMLElement* imp, XMLElement* def) final;
+};
+
+#endif // COMPONENTS_ANIMATE_HPP_
diff --git a/include/components/dialog.hpp b/include/components/dialog.hpp
new file mode 100644 (file)
index 0000000..8d26b92
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef COMPONENTS_DIALOG_HPP_
+#define COMPONENTS_DIALOG_HPP_
+
+#include "base.hpp"
+
+#include <random.hpp>
+
+struct Dialog : public Component {
+       Dialog(int idx = 0)
+               : index(idx), rindex((idx == 9999) ? randGet() : idx), talking(false) {}
+       Dialog(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       int index;
+       int rindex;
+       bool talking;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)def;
+               bool hasDialog;
+               if (imp->QueryBoolAttribute("hasDialog", &hasDialog) != XML_NO_ERROR)
+                       hasDialog = false;
+
+               index = hasDialog ? 0 : 9999;
+               rindex = (index == 9999) ? randGet() : index;
+               talking = false;
+       }
+};
+
+#endif // COMPONENTS_DIALOG_HPP_
diff --git a/include/components/direction.hpp b/include/components/direction.hpp
new file mode 100644 (file)
index 0000000..1229e49
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef COMPONENTS_DIRECTION_HPP_
+#define COMPONENTS_DIRECTION_HPP_
+
+#include "base.hpp"
+
+#include <vector2.hpp>
+
+/**
+ * @struct Direction
+ * @brief Store an entities velocity.
+ * This allows the entity to move throughout the world.
+ */
+struct Direction : public Component {
+       /**
+        * Constructor that sets the velocity, if no position is passed, it defaults to (0,0).
+        * @param x The velocity of the object on the x axis.
+        * @param y The velocity of the object on the y axis.
+        */
+       Direction(float x = 0.0f, float y = 0.0f): x(x), y(y), grounded(false) {}
+       Direction(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       float x; /**< Velocity the object is moving in the x direction, this is added to the position */
+       float y; /**< Velocity the object is moving in the y direction, this is added to the position */
+       bool grounded;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               vec2 c;
+               if (imp->Attribute("direction") != nullptr) {
+                       c = imp->StrAttribute("direction");
+               } else if (def->Attribute("value") != nullptr) {
+                       c = def->StrAttribute("value");
+               } else {
+                       c = vec2(0, 0);
+               }
+
+               x = c.x, y = c.y, grounded = false;
+       }
+};
+
+#endif // COMPONENTS_DIRECTION_HPP_
diff --git a/include/components/flash.hpp b/include/components/flash.hpp
new file mode 100644 (file)
index 0000000..e53c41c
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef COMPONENTS_FLASH_HPP_
+#define COMPONENTS_FLASH_HPP_
+
+#include <color.hpp>
+
+struct Flash
+{
+       Flash(Color c, int _ms = 500)
+               : color(c), ms(_ms), totalMs(_ms) {}
+
+       Color color;
+       int ms, totalMs;
+};
+
+#endif // COMPONENTS_FLASH_HPP_
diff --git a/include/components/grounded.hpp b/include/components/grounded.hpp
new file mode 100644 (file)
index 0000000..017c118
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef COMPONENTS_GROUNDED_HPP_
+#define COMPONENTS_GROUNDED_HPP_
+
+#include "base.hpp"
+
+/**
+ * @struct Grounded
+ * @brief Places an entity without physics on the ground.
+ * This is used so we don't have to update the physics of a non-moving object every loop.
+ */
+struct Grounded : public Component {
+       Grounded(bool g = false)
+               : grounded(g) {}
+       Grounded(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       bool grounded;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               (void)def;
+               grounded = false;
+       }
+};
+
+#endif // COMPONENTS_GROUNDED_HPP_
diff --git a/include/components/health.hpp b/include/components/health.hpp
new file mode 100644 (file)
index 0000000..eacaaa5
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef COMPONENTS_HEALTH_HPP_
+#define COMPONENTS_HEALTH_HPP_
+
+#include "base.hpp"
+
+/**
+ * @struct Health
+ * @brief Gives and entity health and stuff.
+ */
+struct Health : public Component {
+       /**
+        * Constructor that sets the variables, with 1 health as default.
+        */
+       Health(int m = 1, int h = 0)
+               : health(h != 0 ? h : m), maxHealth(m) {}
+       Health(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       int health; /**< The current amount of health */
+       int maxHealth; /**< The maximum amount of health */
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               (void)def;
+               // TODO
+               if (def->QueryIntAttribute("value", &health) != XML_NO_ERROR)
+                       health = 1;
+               maxHealth = health;
+       }
+};
+
+
+#endif // COMPONENTS_HEALTH_HPP_
diff --git a/include/components/hit.hpp b/include/components/hit.hpp
new file mode 100644 (file)
index 0000000..d2e80ca
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef COMPONENTS_HIT_HPP_
+#define COMPONENTS_HIT_HPP_
+
+#include "base.hpp"
+
+struct Hit : public Component {
+       Hit(int d, bool p = false)
+               : damage(d), pierce(p) {}
+
+       int damage;
+       bool pierce;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               (void)def;
+       }
+};
+
+#endif // COMPONENTS_HIT_HPP_
diff --git a/include/components/hop.hpp b/include/components/hop.hpp
new file mode 100644 (file)
index 0000000..f114265
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef COMPONENTS_HOP_HPP_
+#define COMPONENTS_HOP_HPP_
+
+/**
+ * Causes the entity to hop around.
+ */
+struct Hop {
+       Hop(float r = 0)
+               : hopRatio(r) {}
+
+       float hopRatio;
+};
+
+#endif // COMPONENTS_HOP_HPP
diff --git a/include/components/itemdrop.hpp b/include/components/itemdrop.hpp
new file mode 100644 (file)
index 0000000..681c0d6
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef COMPONENTS_ITEMDROP_HPP_
+#define COMPONENTS_ITEMDROP_HPP_
+
+#include <inventory.hpp>
+
+struct ItemDrop {
+       ItemDrop(InventoryEntry& ie)
+               : item(ie) {}
+
+       InventoryEntry item;
+};
+
+#endif // COMPONENTS_ITEMDROP_HPP_
diff --git a/include/components/name.hpp b/include/components/name.hpp
new file mode 100644 (file)
index 0000000..423a484
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef COMPONENTS_NAME_HPP_
+#define COMPONENTS_NAME_HPP_
+
+#include "base.hpp"
+
+#include <string>
+
+struct Name : public Component {
+       Name(std::string n = "")
+               : name(n) {}
+       Name(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       std::string name;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               auto n = imp->Attribute("name");
+
+               // TODO check def's nullness    
+               name = n != nullptr ? n : def->Attribute("value");
+       }
+};
+#endif // COMPONENTS_NAME_HPP_
diff --git a/include/components/physics.hpp b/include/components/physics.hpp
new file mode 100644 (file)
index 0000000..8e462a9
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef COMPONENTS_PHYSICS_HPP_
+#define COMPONENTS_PHYSICS_HPP_
+
+#include "base.hpp"
+
+/**
+ * @struct Physics
+ * @brief Allows and entity to react to gravity and frictions.
+ * When an entity inherits this component it will react with gravity and move with friction.
+ */
+struct Physics : public Component {
+       /**
+        * Constructor that sets the gravity constant, if not specified it becomes 0.
+        * @param g The non default gravity constant.
+        */
+       Physics(float g = 0.2f): g(g) {}
+       Physics(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       float g; /**< The gravity constant, how fast the object falls */
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               if (imp->QueryFloatAttribute("gravity", &g) != XML_NO_ERROR) {
+                       if (def->QueryFloatAttribute("value", &g) != XML_NO_ERROR)
+                               g = 0.2f;
+               }
+       }
+};
+
+#endif // COMPONENTS_PHYSICS_HPP_
diff --git a/include/components/player.hpp b/include/components/player.hpp
new file mode 100644 (file)
index 0000000..afcaa90
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef COMPONENTS_PLAYER_HPP_
+#define COMPONENTS_PLAYER_HPP_
+
+struct Player {};
+
+#endif // COMPONENTS_PLAYER_HPP_
diff --git a/include/components/portal.hpp b/include/components/portal.hpp
new file mode 100644 (file)
index 0000000..ca153e1
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef COMPONENTS_PORTAL_HPP_
+#define COMPONENTS_PORTAL_HPP_
+
+#include "base.hpp"
+
+#include <string>
+
+struct Portal : public Component {
+       Portal(std::string tf = "")
+               : toFile(tf) {}
+       Portal(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       std::string toFile;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)def;
+               toFile = imp->StrAttribute("inside");
+       }
+};
+
+#endif // COMPONENTS_PORTAL_HPP_
diff --git a/include/components/position.hpp b/include/components/position.hpp
new file mode 100644 (file)
index 0000000..f040bec
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef COMPONENTS_POSITION_HPP_
+#define COMPONENTS_POSITION_HPP_
+
+#include "base.hpp"
+
+#include <vector2.hpp>
+
+/**
+ * @struct Position
+ * @brief Stores the position of an entity on the xy plane.
+ */
+struct Position : public Component {
+       /**
+        * Constructor that sets the position of the object, if nothing is passed it will default to 0.
+        * @param x The x position the object will be placed at.
+        * @param y the y position the object will be placed at.
+        */
+       Position(float x = 0.0f, float y = 0.0f): x(x), y(y) {}
+       Position(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       float x; /**< The x position in the world */
+       float y; /**< The y position in the world */
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               vec2 c;
+               if (imp->Attribute("position") != nullptr)
+                       c = imp->StrAttribute("position");
+               else
+                       c = def->StrAttribute("value");
+
+               x = c.x, y = c.y;
+       }
+};
+
+#endif // COMPONENTS_POSITION_HPP_
diff --git a/include/components/solid.hpp b/include/components/solid.hpp
new file mode 100644 (file)
index 0000000..35bfcf7
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef COMPONENTS_SOLID_HPP_
+#define COMPONENTS_SOLID_HPP_
+
+#include "base.hpp"
+
+#include <vector2.hpp>
+
+/**
+ * @struct Solid
+ * @brief Allows an entity to collide with other objects.
+ * When an entity has this component it can collide with the world and other objects.
+ */
+struct Solid : public Component {
+       /**
+        * Constructor that sets the entities dimensions based on what is passed.
+        * @param w The desired width of the entity.
+        * @param h The desired height of the entity.
+        */
+       Solid(float w = 0.0f, float h = 0.0f)
+               : width(w), height(h), offset(0), passable(true) {}
+       Solid(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       void Passable(bool v) { passable = v; }
+       bool Passable(void)   { return passable; }
+
+       float width; /**< The width of the entity in units */
+       float height; /**< The height of the entity in units */
+       vec2 offset; /**< This allows us to make the hitbox in any spot */
+       bool passable; /**< This determines whether or not one can pass by the entity */
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               vec2 c;
+               if (def->Attribute("value") != nullptr)
+                       c = def->StrAttribute("value");
+               else
+                       c = vec2(0, 0);
+
+               width = c.x, height = c.y, offset = 0, passable = true;
+       }
+};
+
+#endif // COMPONENTS_SOLID_HPP_
diff --git a/include/components/sprite.hpp b/include/components/sprite.hpp
new file mode 100644 (file)
index 0000000..35a13b8
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef COMPONENTS_SPRITE_HPP_
+#define COMPONENTS_SPRITE_HPP_
+
+#include "base.hpp"
+
+#include <texture.hpp>
+#include <vector2.hpp>
+
+#include <vector>
+
+struct SpriteData {
+       SpriteData(void) = default;     
+       SpriteData(Texture t);
+       SpriteData(std::string path, vec2 off);
+       SpriteData(std::string path, vec2 off, vec2 si);
+
+       Texture tex;
+       vec2 size;
+       vec2 offset;
+       
+       vec2 offset_tex;
+       vec2 size_tex;
+
+       unsigned int limb;
+};
+
+using Frame = std::vector<std::pair<SpriteData, vec2>>;
+
+std::vector<Frame> developFrame(XMLElement*);
+
+/**
+ * @struct Sprite
+ * @brief If an entity is visible we want to be able to see it.
+ * Each entity is given a sprite, a sprite can consist of manu frames or pieces to make one.
+ */
+struct Sprite : public Component {
+       Sprite(bool left = false)
+               : faceLeft(left) {}
+       Sprite(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       inline Frame getSprite(void) {
+               return sprite;
+       }
+
+       int clearSprite(void);
+       int addSpriteSegment(SpriteData data, vec2 loc);
+       int changeSpriteSegment(SpriteData data, vec2 loc);
+       vec2 getSpriteSize(); 
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               auto frames = developFrame(def);
+               if (!frames.empty())
+                       sprite = frames.at(0);
+       }
+
+       Frame sprite;
+       bool faceLeft;
+};
+
+
+#endif // COMPONENTS_SPRITE_HPP_
diff --git a/include/components/trigger.hpp b/include/components/trigger.hpp
new file mode 100644 (file)
index 0000000..c9a53f6
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef COMPONENTS_TRIGGER_HPP_
+#define COMPONENTS_TRIGGER_HPP_
+
+#include "base.hpp"
+
+#include <string>
+
+struct Trigger : public Component {
+       Trigger(const std::string& t)
+               : text(t) {}
+       Trigger(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       std::string text;
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               (void)def;
+               text = "You got me!";
+       }
+};
+
+
+#endif // COMPONENTS_TRIGGER_HPP_
diff --git a/include/components/visible.hpp b/include/components/visible.hpp
new file mode 100644 (file)
index 0000000..4785fb0
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef COMPONENTS_VISIBLE_HPP_
+#define COMPONENTS_VISIBLE_HPP_
+
+#include "base.hpp"
+
+/**
+ * @struct Visible
+ * @brief If an entity is visible we want to be able to draw it.
+ */
+struct Visible : public Component {
+       /**
+        * @brief Decide what layer to draw the entity on.
+        * When stuff is drawn, it is drawn on a "layer". This layer gives more of a 3D effect to the world.
+        * @param z The desired "layer" of the entity.
+        */
+       Visible(float z = 0.0f): z(z) {}
+       Visible(XMLElement* imp, XMLElement* def) {
+               fromXML(imp, def);
+       }
+
+       float z; /**< The value along the z axis the entity will be drawn on */
+
+       void fromXML(XMLElement* imp, XMLElement* def) final {
+               (void)imp;
+               if (def->QueryFloatAttribute("value", &z) != XML_NO_ERROR)
+                       z = 0;
+       }
+};
+
+#endif // COMPONENTS_VISIBLE_HPP_
diff --git a/include/components/wander.hpp b/include/components/wander.hpp
new file mode 100644 (file)
index 0000000..2001e89
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef COMPONENTS_WANDER_HPP_
+#define COMPONENTS_WANDER_HPP_
+
+/**
+ * Causes the entity to wander about.
+ */
+struct Wander {
+       Wander(float ix = 0, float r = 0)
+               : initialX(ix), range(r), countdown(0) {}
+
+       float initialX;
+       float range;
+       int countdown;
+};
+
+#endif // COMPONENTS_WANDER_HPP_
diff --git a/include/systems/dialog.hpp b/include/systems/dialog.hpp
new file mode 100644 (file)
index 0000000..407f043
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef SYSTEM_DIALOG_HPP_
+#define SYSTEM_DIALOG_HPP_
+
+#include <entityx/entityx.h>
+
+#include <events.hpp>
+
+class DialogSystem : public entityx::System<DialogSystem>, public entityx::Receiver<DialogSystem> {
+public:
+       void configure(entityx::EventManager&);
+       void receive(const MouseClickEvent&);
+       void update(entityx::EntityManager&, entityx::EventManager&, entityx::TimeDelta) override;
+};
+
+
+#endif // SYSTEM_DIALOG_HPP_
diff --git a/include/systems/movement.hpp b/include/systems/movement.hpp
new file mode 100644 (file)
index 0000000..fd37665
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef SYSTEM_MOVEMENT_HPP_
+#define SYSTEM_MOVEMENT_HPP_
+
+#include <entityx/entityx.h>
+
+class MovementSystem : public entityx::System<MovementSystem> {
+public:
+       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
+};
+
+#endif // SYSTEM_MOVEMENT_HPP_
diff --git a/include/systems/physics.hpp b/include/systems/physics.hpp
new file mode 100644 (file)
index 0000000..9fd6981
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef SYSTEM_PHYSICS_HPP_
+#define SYSTEM_PHYSICS_HPP_
+
+#include <entityx/entityx.h>
+
+class PhysicsSystem : public entityx::System<PhysicsSystem> {
+public:
+       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
+};
+
+#endif // SYSTEM_PHYSICS_HPP_
diff --git a/include/systems/render.hpp b/include/systems/render.hpp
new file mode 100644 (file)
index 0000000..012c6fd
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef SYSTEM_RENDER_HPP_
+#define SYSTEM_RENDER_HPP_
+
+#include <entityx/entityx.h>
+
+#include <texture.hpp>
+
+#include <string>
+
+class RenderSystem : public entityx::System<RenderSystem> {
+private:
+       static std::string loadTexString;
+       static Texture loadTexResult;
+
+public:
+       static Texture loadTexture(const std::string& file);
+       static void render(void);
+
+       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
+};
+
+
+#endif // SYSTEM_RENDER_HPP_
diff --git a/src/components.cpp b/src/components.cpp
deleted file mode 100644 (file)
index 056d48b..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-#include <components.hpp>
-
-#include <entityx/entityx.h>
-#include <events.hpp>
-
-#include <attack.hpp>
-#include <render.hpp>
-#include <ui.hpp>
-#include <engine.hpp>
-#include <error.hpp>
-#include <font.hpp>
-#include <world.hpp>
-#include <brice.hpp>
-#include <quest.hpp>
-#include <glm.hpp>
-#include <fileio.hpp>
-#include <player.hpp>
-
-#include <atomic>
-
-using namespace std::literals::chrono_literals;
-
-std::string RenderSystem::loadTexString;
-Texture     RenderSystem::loadTexResult;
-
-static std::vector<std::string> randomDialog (readFileA("assets/dialog_en-us"));
-
-void MovementSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
-{
-       //bool fight = false;
-       entityx::Entity toFight;
-
-       (void)ev;
-       en.each<Position, Direction>([&](entityx::Entity entity, Position &position, Direction &direction) {
-               position.x += HLINES(direction.x) * dt;
-               position.y += HLINES(direction.y) * dt;
-
-               if (entity.has_component<Animate>() && entity.has_component<Sprite>()) {
-                       auto animate = entity.component<Animate>();
-                       auto sprite =  entity.component<Sprite>();
-               
-                       if (direction.x)        
-                               animate->updateAnimation(1, sprite->sprite, dt);
-                       else
-                               animate->firstFrame(1, sprite->sprite);
-               }
-               if (entity.has_component<Dialog>() && entity.component<Dialog>()->talking) {
-                       direction.x = 0;
-               } else {
-                       if (entity.has_component<Sprite>()) {
-                               auto& fl = entity.component<Sprite>()->faceLeft;
-                               if (direction.x != 0)
-                                       fl = (direction.x < 0);
-                       }
-
-                       auto ppos = PlayerSystem::getPosition();
-                       if (ppos.x > position.x && ppos.x < position.x + entity.component<Solid>()->width) {
-                               if (entity.has_component<Aggro>()) {
-                                       auto dim = entity.component<Solid>();
-                                       ev.emit<AttackEvent>(vec2(position.x + dim->width, position.y + dim->height),
-                                               AttackType::ShortSlash, false);
-                                       /*auto& h = entity.component<Health>()->health;
-                                       if (h > 0) {
-                                               fight = true;
-                                               toFight = entity;
-                                               h = 0;
-                                       }*/
-                               } else if (entity.has_component<Trigger>()) {
-                                       static bool triggering = false;
-                                       if (!triggering) {
-                                               triggering = true;
-                                               std::thread([&](entityx::Entity e) {
-                                                       UISystem::fadeToggle();
-                                                       UISystem::waitForCover();
-                                                       UISystem::dialogImportant(e.component<Trigger>()->text);
-                                                       UISystem::waitForDialog();
-                                                       UISystem::fadeToggle();
-                                                       e.destroy();
-                                                       triggering = false;
-                                               }, entity).detach();
-                                       }
-                                       return;
-                               }
-                       }
-
-                       // make the entity wander
-                       // TODO initialX and range?
-                       if (entity.has_component<Wander>()) {
-                               auto& countdown = entity.component<Wander>()->countdown;
-
-                               if (countdown > 0) {
-                                       countdown--;
-                               } else {
-                                       countdown = 5000 + randGet() % 10 * 100;
-                                       direction.x = (randGet() % 3 - 1) * 0.004f;
-                               }
-                       }
-               }
-       });
-
-//     if (fight) {
-//             UISystem::fadeToggleFast();
-//             UISystem::waitForCover();
-               //game::engine.getSystem<WorldSystem>()->fight(toFight);
-//             UISystem::fadeToggleFast();
-//     }
-}
-
-void PhysicsSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
-{
-       (void)ev;
-       en.each<Direction, Physics>([dt](entityx::Entity entity, Direction &direction, Physics &physics) {
-               (void)entity;
-               // TODO GET GRAVITY FROM WORLD
-               direction.y += physics.g * dt;
-       });
-}
-
-Texture RenderSystem::loadTexture(const std::string& file)
-{
-       loadTexString = file;
-       loadTexResult = Texture();
-       while (loadTexResult.isEmpty())
-               std::this_thread::sleep_for(1ms);
-       auto t = loadTexResult;
-       loadTexResult = Texture();
-       return t;
-}
-
-void RenderSystem::render(void)
-{      
-       if (!loadTexString.empty()) {
-               loadTexResult = Texture(loadTexString, false);
-               loadTexString.clear();
-       }
-
-       if (!loadTexResult.isEmpty())
-               return;
-
-       Render::worldShader.use();
-       Render::worldShader.enable();
-
-       game::entities.each<Visible, Sprite, Position>([](entityx::Entity entity, Visible &visible, Sprite &sprite, Position &pos) {
-               // Verticies and shit
-               float its = 0;
-               
-               float sz;
-               if (entity.has_component<Solid>())
-                       sz = entity.component<Solid>()->width;
-               else 
-                       sz = sprite.getSpriteSize().x;
-
-               if (sprite.faceLeft) {
-                       glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(-1.0f,1.0f,1.0f));
-                       glm::mat4 translate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f - sz - pos.x * 2.0f, 0.0f, 0.0f));
-
-                       glm::mat4 mov = scale * translate;
-                       glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(mov));
-               }
-
-               for (auto &S : sprite.sprite) {
-                       auto sp = S.first;
-                       auto size = sp.size * game::HLINE;
-                       vec2 drawOffset (HLINES(S.second.x), HLINES(S.second.y));
-                       vec2 loc (pos.x + drawOffset.x, pos.y + drawOffset.y);
-
-                       GLfloat verts[] = {
-                               loc.x,          loc.y,          visible.z + its, sp.offset_tex.x,                 sp.offset_tex.y,
-                               loc.x + size.x, loc.y,          visible.z + its, sp.offset_tex.x + sp.size_tex.x, sp.offset_tex.y,
-                               loc.x + size.x, loc.y + size.y, visible.z + its, sp.offset_tex.x + sp.size_tex.x, sp.offset_tex.y + sp.size_tex.y,
-                               loc.x,          loc.y,          visible.z + its, sp.offset_tex.x,                 sp.offset_tex.y,
-                               loc.x + size.x, loc.y + size.y, visible.z + its, sp.offset_tex.x + sp.size_tex.x, sp.offset_tex.y + sp.size_tex.y,
-                               loc.x,          loc.y + size.y, visible.z + its, sp.offset_tex.x,                 sp.offset_tex.y + sp.size_tex.y
-                       };
-
-                       // make the entity hit flash red
-                       // TODO
-                       /*if (maxHitDuration-hitDuration) {
-                               float flashAmt = 1-(hitDuration/maxHitDuration);
-                               glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, flashAmt, flashAmt, 1.0);
-                       }*/
-
-                       sp.tex.use();
-
-                       glUniform1i(Render::worldShader.uniform[WU_texture], 0);
-
-                       glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), verts);
-                       glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), verts + 3);
-                       glDrawArrays(GL_TRIANGLES, 0, 6);
-
-                       //glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0);
-
-                       its-=.01;
-               }
-               glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
-
-               if (entity.has_component<Health>()) {
-                       float width = entity.component<Solid>()->width;
-                       auto& health = *entity.component<Health>();
-                       width *= health.health / static_cast<float>(health.maxHealth);
-
-                       GLfloat health_coord[] = {
-                               pos.x, pos.y, -9, 0, 0,
-                               pos.x + width, pos.y, -9, 0, 0,
-                               pos.x + width, pos.y - 5, -9, 0, 0,
-                               pos.x + width, pos.y - 5, -9, 0, 0,
-                               pos.x, pos.y - 5, -9, 0, 0,
-                               pos.x, pos.y, -9, 0, 0,
-                       };
-
-                       Colors::red.use();
-                       glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), health_coord);
-                       glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), health_coord + 3);
-                       glDrawArrays(GL_TRIANGLES, 0, 6);
-               }
-       });
-
-       Render::worldShader.disable();
-       Render::worldShader.unuse();
-
-       game::entities.each<Visible, Position, Solid, Name>([](entityx::Entity e, Visible &v, Position &pos, Solid& dim, Name &name) {
-               (void)e;
-               (void)v;
-               FontSystem::setFontZ(-5.0f);
-               UISystem::putStringCentered(vec2(pos.x + dim.width / 2, pos.y - FontSystem::getSize() - HLINES(0.5)), name.name);
-       });
-}
-
-void DialogSystem::configure(entityx::EventManager &ev)
-{
-       ev.subscribe<MouseClickEvent>(*this);
-}
-
-void DialogSystem::receive(const MouseClickEvent &mce)
-{
-       game::entities.each<Position, Solid, Dialog, Name>(
-               [&](entityx::Entity e, Position &pos, Solid &dim, Dialog &d, Name &name) {
-                       static std::atomic_bool dialogRun;
-                       (void)e;
-                       (void)d;
-
-                       if (((mce.position.x > pos.x) & (mce.position.x < pos.x + dim.width)) &&
-                           ((mce.position.y > pos.y) & (mce.position.y < pos.y + dim.height))) {
-
-                       if (!dialogRun.load()) {
-                               // copy entity, windows destroys the original after thread detach
-                               std::thread([e, &pos, &dim, &d, &name] {
-                                       std::string questAssignedText;
-                                       int newIndex;
-
-                                       auto exml = WorldSystem::getXML()->FirstChildElement("Dialog");
-                                       dialogRun.store(true);
-
-                                       if (e.has_component<Direction>())
-                                               d.talking = true;
-
-                                       if (d.index == 9999) {
-                                               UISystem::dialogBox(name.name, /*"", false,*/ randomDialog[d.rindex % randomDialog.size()]);
-                                               UISystem::waitForDialog();
-                                       } else if (exml != nullptr) {
-                                               while (exml->StrAttribute("name") != name.name)
-                                                       exml = exml->NextSiblingElement();
-
-                                               exml = exml->FirstChildElement("text");
-                                               while (exml->IntAttribute("id") != d.index)
-                                                       exml = exml->NextSiblingElement();
-
-                                               auto oxml = exml->FirstChildElement("set");
-                                               if (oxml != nullptr) {
-                                                       do game::setValue(oxml->StrAttribute("id"), oxml->StrAttribute("value"));
-                                                       while ((oxml = oxml->NextSiblingElement()));
-                                                       game::briceUpdate();
-                                               }
-
-                                               auto ixml = exml->FirstChildElement("give");
-                                               if (ixml != nullptr) {
-                                                       do {
-                                                               InventorySystem::add(ixml->StrAttribute("name"), ixml->IntAttribute("count"));
-                                                               ixml = ixml->NextSiblingElement();
-                                                       } while (ixml != nullptr);
-                                               }
-
-                                               auto qxml = exml->FirstChildElement("quest");
-                                               if (qxml != nullptr) {
-                                                       const char *qname;
-
-                                                       do {
-                                                               // assign quest
-                                                               qname = qxml->Attribute("assign");
-                                                               if (qname != nullptr) {
-                                                                       questAssignedText = qname;
-                                                                       auto req = qxml->GetText();
-                                                                       QuestSystem::assign(qname, qxml->StrAttribute("desc"), req ? req : "");
-                                                               }
-
-                                                               // check / finish quest
-                                                               else {
-                                                                       qname = qxml->Attribute("check");
-                                                                       if (qname != nullptr) {
-                                                                               if (qname != nullptr && QuestSystem::finish(qname) == 0) {
-                                                                                       d.index = 9999;
-                                                                               } else {
-                                                                                       UISystem::dialogBox(name.name, /*"", false,*/ "Finish my quest u nug");
-                                                                                       UISystem::waitForDialog();
-                                                                                       return;
-                                                                               }
-                                                                       //      oldidx = d.index;
-                                                                       //      d.index = qxml->UnsignedAttribute("fail");
-                                                                       //      goto COMMONAIFUNC;
-                                                                       }
-                                                               }
-                                                       } while((qxml = qxml->NextSiblingElement()));
-                                               }
-
-                                               auto xxml = exml->FirstChildElement("option");
-                                               std::string options;
-                                               std::vector<int> optionNexts;
-                                               if (xxml != nullptr) {
-                                                       do {
-                                                               UISystem::dialogAddOption(xxml->StrAttribute("name"));
-
-                                                               options += '\"' + xxml->StrAttribute("name");
-                                                               optionNexts.emplace_back(xxml->IntAttribute("value"));
-                                                               xxml = xxml->NextSiblingElement();
-                                                       } while (xxml != nullptr);
-                                               }
-
-                                               auto cxml = exml->FirstChildElement("content");
-                                               const char *content;
-                                               if (cxml == nullptr) {
-                                                       content = randomDialog[d.rindex % randomDialog.size()].c_str();
-                                               } else {
-                                                       content = cxml->GetText() - 1;
-                                                       while (*++content && isspace(*content));
-                                               }
-
-                                               UISystem::dialogBox(name.name, /*options, false,*/ content);
-                                               UISystem::waitForDialog();
-                                               UISystem::waitForDialog();
-
-                                               if (!questAssignedText.empty())
-                                                       UISystem::dialogImportant("Quest assigned:\n\"" + questAssignedText + "\"");
-                                                       //passiveImportantText(5000, ("Quest assigned:\n\"" + questAssignedText + "\"").c_str());
-
-                                               if (exml->QueryIntAttribute("nextid", &newIndex) == XML_NO_ERROR)
-                                                       d.index = newIndex;
-                                       }
-
-                                       d.talking = false;
-                                       dialogRun.store(false);
-                               }).detach();
-                       }
-               }
-       });
-}
-
-void DialogSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
-{
-       (void)en;
-       (void)ev;
-       (void)dt;
-}
-
-std::vector<Frame> developFrame(XMLElement* xml)
-{
-       Frame tmpf;
-       std::vector<Frame> tmp;
-       SpriteData sd;  
-
-       unsigned int limb = 0;
-
-       vec2 foffset;
-       vec2 fsize;
-       vec2 fdraw;
-
-       tmp.clear();
-
-       // this is the xml elements first child. It will only be the <frame> tag
-       auto framexml = xml->FirstChildElement();
-       while (framexml) {
-               // this will always be frame. but if it isn't we don't wanna crash the game
-               std::string defframe = framexml->Name();
-               if (defframe == "frame") {
-                       tmpf.clear();
-                       // the xml element to parse each src of the frames
-                       auto sxml = framexml->FirstChildElement();
-                       while (sxml) {
-                               std::string sname = sxml->Name();
-                               if (sname == "src") {
-                                       foffset = (sxml->Attribute("offset") != nullptr) ? 
-                                               sxml->StrAttribute("offset") : vec2(0,0);
-                                       fdraw = (sxml->Attribute("drawOffset") != nullptr) ?
-                                               sxml->StrAttribute("drawOffset") : vec2(0,0);
-                                       
-                                       if (sxml->Attribute("size") != nullptr) {
-                                               fsize = sxml->StrAttribute("size");
-                                               sd = SpriteData(sxml->GetText(), foffset, fsize);
-                                       } else {
-                                               sd = SpriteData(sxml->GetText(), foffset);
-                                       }
-                                       if (sxml->QueryUnsignedAttribute("limb", &limb) == XML_NO_ERROR) 
-                                               sd.limb = limb;
-                                       tmpf.push_back(std::make_pair(sd, fdraw));
-                               }
-                               sxml = sxml->NextSiblingElement();
-                       }
-                       // we don't want segfault
-                       if (tmpf.size())
-                               tmp.push_back(tmpf);
-               }
-               // if it's not a frame we don't care
-
-               // parse next frame
-               framexml = framexml->NextSiblingElement();
-       }
-
-       return tmp;
-}
diff --git a/src/components/animate.cpp b/src/components/animate.cpp
new file mode 100644 (file)
index 0000000..2ac1465
--- /dev/null
@@ -0,0 +1,106 @@
+#include <components/animate.hpp>
+
+void Limb::firstFrame(Frame& duckmyass)
+{
+       // loop through the spritedata of the sprite we wanna change
+       for (auto &d : duckmyass) {
+               // if the sprite data is the same limb as this limb
+               if (d.first.limb == limbID) {
+                       // rotate through (for safety) the first frame to set the limb
+                       for (auto &fa : frame.at(0)) {
+                               if (fa.first.limb == limbID) {
+                                       d.first = fa.first;
+                                       d.second = fa.second;
+                               }
+                       }
+               }
+       }
+}
+
+void Limb::nextFrame(Frame& duckmyass, float dt) {
+       updateCurrent -= dt;
+       if (updateCurrent <= 0) {
+               updateCurrent = updateRate;
+       } else {
+               return;
+       }
+
+       if (index < frame.size() - 1)
+               index++;
+       else
+               index = 0;
+
+       for (auto &d : duckmyass) {
+               if (d.first.limb == limbID) {
+                       for (auto &fa : frame.at(index)) {
+                               if (fa.first.limb == limbID) {
+                                       d.first = fa.first;
+                                       d.second = fa.second;
+                               }
+                       }
+               }
+       }
+}
+
+void Animate::firstFrame(unsigned int updateType, Frame &sprite)
+{
+       unsigned int upid = updateType; //^see todo
+       for (auto &l : limb) {
+               if (l.updateType == upid) {
+                       l.firstFrame(sprite);
+               }
+       }
+}
+
+void Animate::updateAnimation(unsigned int updateType, Frame& sprite, float dt)
+{
+       unsigned int upid = updateType; //^see todo
+       for (auto &l : limb) {
+               if (l.updateType == upid) {
+                       l.nextFrame(sprite, dt);
+               }
+       }
+}
+
+void Animate::fromXML(XMLElement* imp, XMLElement* def) 
+{
+       (void)imp;
+
+       auto animx = def->FirstChildElement();
+       unsigned int limbid = 0;
+       float limbupdate = 0;
+       unsigned int limbupdatetype = 0;
+
+       while (animx != nullptr) {
+               if (std::string(animx->Name()) == "movement") {
+                       limbupdatetype = 1;
+
+                       auto limbx = animx->FirstChildElement();
+                       while (limbx != nullptr) {
+                               if (std::string(limbx->Name()) == "limb") {
+                                       auto frames = developFrame(limbx);
+                                       limb.push_back(Limb());
+                                       auto& newLimb = limb.back();
+                                       newLimb.updateType = limbupdatetype;
+                                               if (limbx->QueryUnsignedAttribute("id", &limbid) == XML_NO_ERROR)
+                                               newLimb.limbID = limbid;
+                                       if (limbx->QueryFloatAttribute("update", &limbupdate) == XML_NO_ERROR)
+                                               newLimb.updateRate = limbupdate;
+                                                       
+                                       // place our newly developed frames in the entities animation stack
+                                       for (auto &f : frames) {
+                                               newLimb.addFrame(f);
+                                               for (auto &fr : newLimb.frame) {
+                                                       for (auto &sd : fr)
+                                                               sd.first.limb = limbid;
+                                               }
+                                       }
+                               }
+                                       limbx = limbx->NextSiblingElement();
+                       }
+               }
+                       
+               animx = animx->NextSiblingElement();
+       }
+}
+
diff --git a/src/components/sprite.cpp b/src/components/sprite.cpp
new file mode 100644 (file)
index 0000000..053d36a
--- /dev/null
@@ -0,0 +1,155 @@
+#include <components/sprite.hpp>
+
+#include <config.hpp>
+
+SpriteData::SpriteData(std::string path, vec2 off)
+       : offset(off)
+{
+       tex = Texture(path);
+       size = tex.getDim();
+       size_tex = vec2(1.0, 1.0);
+       offset_tex.x = offset.x / size.x;
+       offset_tex.y = offset.y / size.y;
+}
+
+SpriteData::SpriteData(std::string path, vec2 off, vec2 si)
+       : size(si), offset(off)
+{
+       tex = Texture(path);
+       vec2 tmpsize = tex.getDim();
+
+       size_tex.x = size.x/tmpsize.x;
+       size_tex.y = size.y/tmpsize.y;
+                       
+       offset_tex.x = offset.x/tmpsize.x;
+       offset_tex.y = offset.y/tmpsize.y;
+}
+
+SpriteData::SpriteData(Texture t)
+       : tex(t)
+{
+       size_tex = 1;
+       offset_tex = 0;
+       size = tex.getDim();
+       offset = 0;
+}
+
+int Sprite::clearSprite(void)
+{
+       if (sprite.empty())
+               return 0;
+
+       sprite.clear();
+       return 1;
+}
+
+int Sprite::addSpriteSegment(SpriteData data, vec2 loc)
+{
+       //TODO if sprite is in this spot, do something
+       sprite.push_back(std::make_pair(data, loc));
+       return 1;
+}
+
+int Sprite::changeSpriteSegment(SpriteData data, vec2 loc)
+{
+       for (auto &s : sprite) {
+               if (s.second == loc) {
+                       s.first = data;
+
+                       return 1;
+               }
+       }
+
+       addSpriteSegment(data, loc);
+       return 0;
+}
+
+vec2 Sprite::getSpriteSize()
+{
+       vec2 st; /** the start location of the sprite (bottom left)*/
+       vec2 ed; /** the end ofthe location of the sprite (bottom right)*/
+       vec2 dim; /** how wide the sprite is */
+
+       if (sprite.size()) {
+               st.x = sprite[0].second.x;
+               st.y = sprite[0].second.y;
+
+               ed.x = sprite[0].second.x + sprite[0].first.size.x;
+               ed.y = sprite[0].second.y + sprite[0].first.size.y;
+       } else {
+               return vec2(0.0f, 0.0f);
+       }
+
+       for (auto &s : sprite) {
+               if (s.second.x < st.x)
+                       st.x = s.second.x;
+               if (s.second.y < st.y)
+                       st.y = s.second.y;
+
+               if (s.second.x + s.first.size.x > ed.x)
+                       ed.x = s.second.x + s.first.size.x;
+               if (s.second.y + s.first.size.y > ed.y)
+                       ed.y = s.second.y + s.first.size.y;
+       }
+
+       dim = vec2(ed.x - st.x, ed.y - st.y);
+       dim.x *= game::HLINE;
+       dim.y *= game::HLINE;
+       return dim;
+}
+
+std::vector<Frame> developFrame(XMLElement* xml)
+{
+       Frame tmpf;
+       std::vector<Frame> tmp;
+       SpriteData sd;  
+
+       unsigned int limb = 0;
+
+       vec2 foffset;
+       vec2 fsize;
+       vec2 fdraw;
+
+       tmp.clear();
+
+       // this is the xml elements first child. It will only be the <frame> tag
+       auto framexml = xml->FirstChildElement();
+       while (framexml) {
+               // this will always be frame. but if it isn't we don't wanna crash the game
+               std::string defframe = framexml->Name();
+               if (defframe == "frame") {
+                       tmpf.clear();
+                       // the xml element to parse each src of the frames
+                       auto sxml = framexml->FirstChildElement();
+                       while (sxml) {
+                               std::string sname = sxml->Name();
+                               if (sname == "src") {
+                                       foffset = (sxml->Attribute("offset") != nullptr) ? 
+                                               sxml->StrAttribute("offset") : vec2(0,0);
+                                       fdraw = (sxml->Attribute("drawOffset") != nullptr) ?
+                                               sxml->StrAttribute("drawOffset") : vec2(0,0);
+                                       
+                                       if (sxml->Attribute("size") != nullptr) {
+                                               fsize = sxml->StrAttribute("size");
+                                               sd = SpriteData(sxml->GetText(), foffset, fsize);
+                                       } else {
+                                               sd = SpriteData(sxml->GetText(), foffset);
+                                       }
+                                       if (sxml->QueryUnsignedAttribute("limb", &limb) == XML_NO_ERROR) 
+                                               sd.limb = limb;
+                                       tmpf.push_back(std::make_pair(sd, fdraw));
+                               }
+                               sxml = sxml->NextSiblingElement();
+                       }
+                       // we don't want segfault
+                       if (tmpf.size())
+                               tmp.push_back(tmpf);
+               }
+               // if it's not a frame we don't care
+
+               // parse next frame
+               framexml = framexml->NextSiblingElement();
+       }
+
+       return tmp;
+}
index 07b453cf17c5f7da76abf68ab84853703c23a9f2..b596c6e7323796e94c90a86065740431e0aa91b0 100644 (file)
@@ -68,6 +68,7 @@ void Engine::update(entityx::TimeDelta dt)
        systems.update<WeatherSystem>(dt);
        systems.update<ParticleSystem>(dt);
        systems.update<AttackSystem>(dt);
+       systems.update<RenderSystem>(dt);
        //systems.update<UISystem>(dt);
 }
 
diff --git a/src/systems/dialog.cpp b/src/systems/dialog.cpp
new file mode 100644 (file)
index 0000000..0be0acb
--- /dev/null
@@ -0,0 +1,161 @@
+#include <systems/dialog.hpp>
+
+#include <components/position.hpp>
+#include <components/solid.hpp>
+#include <components/dialog.hpp>
+#include <components/flash.hpp>
+#include <components/name.hpp>
+#include <components/direction.hpp>
+
+#include <brice.hpp>
+#include <engine.hpp>
+#include <fileio.hpp>
+#include <quest.hpp>
+#include <thread.hpp>
+#include <ui.hpp>
+#include <world.hpp>
+
+#include <string>
+#include <vector>
+
+static std::vector<std::string> randomDialog (readFileA("assets/dialog_en-us"));
+
+void DialogSystem::configure(entityx::EventManager &ev)
+{
+       ev.subscribe<MouseClickEvent>(*this);
+}
+
+void DialogSystem::receive(const MouseClickEvent &mce)
+{
+       game::entities.each<Position, Solid, Dialog, Name>(
+               [&](entityx::Entity e, Position &pos, Solid &dim, Dialog &d, Name &name) {
+                       static std::atomic_bool dialogRun;
+                       (void)e;
+                       (void)d;
+
+                       if (((mce.position.x > pos.x) & (mce.position.x < pos.x + dim.width)) &&
+                           ((mce.position.y > pos.y) & (mce.position.y < pos.y + dim.height))) {
+
+                       if (e.has_component<Flash>())
+                               e.remove<Flash>();
+                       e.assign<Flash>(Color(0, 255, 255));
+
+                       if (!dialogRun.load()) {
+                               // copy entity, windows destroys the original after thread detach
+                               std::thread([e, &pos, &dim, &d, &name] {
+                                       std::string questAssignedText;
+                                       int newIndex;
+
+                                       auto exml = WorldSystem::getXML()->FirstChildElement("Dialog");
+                                       dialogRun.store(true);
+
+                                       if (e.has_component<Direction>())
+                                               d.talking = true;
+
+                                       if (d.index == 9999) {
+                                               UISystem::dialogBox(name.name, /*"", false,*/ randomDialog[d.rindex % randomDialog.size()]);
+                                               UISystem::waitForDialog();
+                                       } else if (exml != nullptr) {
+                                               while (exml->StrAttribute("name") != name.name)
+                                                       exml = exml->NextSiblingElement();
+
+                                               exml = exml->FirstChildElement("text");
+                                               while (exml->IntAttribute("id") != d.index)
+                                                       exml = exml->NextSiblingElement();
+
+                                               auto oxml = exml->FirstChildElement("set");
+                                               if (oxml != nullptr) {
+                                                       do game::setValue(oxml->StrAttribute("id"), oxml->StrAttribute("value"));
+                                                       while ((oxml = oxml->NextSiblingElement()));
+                                                       game::briceUpdate();
+                                               }
+
+                                               auto ixml = exml->FirstChildElement("give");
+                                               if (ixml != nullptr) {
+                                                       do {
+                                                               InventorySystem::add(ixml->StrAttribute("name"), ixml->IntAttribute("count"));
+                                                               ixml = ixml->NextSiblingElement();
+                                                       } while (ixml != nullptr);
+                                               }
+
+                                               auto qxml = exml->FirstChildElement("quest");
+                                               if (qxml != nullptr) {
+                                                       const char *qname;
+
+                                                       do {
+                                                               // assign quest
+                                                               qname = qxml->Attribute("assign");
+                                                               if (qname != nullptr) {
+                                                                       questAssignedText = qname;
+                                                                       auto req = qxml->GetText();
+                                                                       QuestSystem::assign(qname, qxml->StrAttribute("desc"), req ? req : "");
+                                                               }
+
+                                                               // check / finish quest
+                                                               else {
+                                                                       qname = qxml->Attribute("check");
+                                                                       if (qname != nullptr) {
+                                                                               if (qname != nullptr && QuestSystem::finish(qname) == 0) {
+                                                                                       d.index = 9999;
+                                                                               } else {
+                                                                                       UISystem::dialogBox(name.name, /*"", false,*/ "Finish my quest u nug");
+                                                                                       UISystem::waitForDialog();
+                                                                                       return;
+                                                                               }
+                                                                       //      oldidx = d.index;
+                                                                       //      d.index = qxml->UnsignedAttribute("fail");
+                                                                       //      goto COMMONAIFUNC;
+                                                                       }
+                                                               }
+                                                       } while((qxml = qxml->NextSiblingElement()));
+                                               }
+
+                                               auto xxml = exml->FirstChildElement("option");
+                                               std::string options;
+                                               std::vector<int> optionNexts;
+                                               if (xxml != nullptr) {
+                                                       do {
+                                                               UISystem::dialogAddOption(xxml->StrAttribute("name"));
+
+                                                               options += '\"' + xxml->StrAttribute("name");
+                                                               optionNexts.emplace_back(xxml->IntAttribute("value"));
+                                                               xxml = xxml->NextSiblingElement();
+                                                       } while (xxml != nullptr);
+                                               }
+
+                                               auto cxml = exml->FirstChildElement("content");
+                                               const char *content;
+                                               if (cxml == nullptr) {
+                                                       content = randomDialog[d.rindex % randomDialog.size()].c_str();
+                                               } else {
+                                                       content = cxml->GetText() - 1;
+                                                       while (*++content && isspace(*content));
+                                               }
+
+                                               UISystem::dialogBox(name.name, /*options, false,*/ content);
+                                               UISystem::waitForDialog();
+                                               UISystem::waitForDialog();
+
+                                               if (!questAssignedText.empty())
+                                                       UISystem::dialogImportant("Quest assigned:\n\"" + questAssignedText + "\"");
+                                                       //passiveImportantText(5000, ("Quest assigned:\n\"" + questAssignedText + "\"").c_str());
+
+                                               if (exml->QueryIntAttribute("nextid", &newIndex) == XML_NO_ERROR)
+                                                       d.index = newIndex;
+                                       }
+
+                                       d.talking = false;
+                                       dialogRun.store(false);
+                               }).detach();
+                       }
+               }
+       });
+}
+
+void DialogSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
+{
+       (void)en;
+       (void)ev;
+       (void)dt;
+}
+
diff --git a/src/systems/movement.cpp b/src/systems/movement.cpp
new file mode 100644 (file)
index 0000000..00baa40
--- /dev/null
@@ -0,0 +1,98 @@
+#include <systems/movement.hpp>
+
+#include <components/position.hpp>
+#include <components/direction.hpp>
+#include <components/solid.hpp>
+#include <components/animate.hpp>
+#include <components/sprite.hpp>
+#include <components/aggro.hpp>
+#include <components/dialog.hpp>
+
+#include <thread>
+
+#include <attack.hpp>
+#include <events.hpp>
+#include <player.hpp>
+#include <ui.hpp>
+
+void MovementSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
+{
+       //bool fight = false;
+       entityx::Entity toFight;
+
+       (void)ev;
+       en.each<Position, Direction>([&](entityx::Entity entity, Position &position, Direction &direction) {
+               position.x += HLINES(direction.x) * dt;
+               position.y += HLINES(direction.y) * dt;
+
+               if (entity.has_component<Animate>() && entity.has_component<Sprite>()) {
+                       auto animate = entity.component<Animate>();
+                       auto sprite =  entity.component<Sprite>();
+               
+                       if (direction.x)        
+                               animate->updateAnimation(1, sprite->sprite, dt);
+                       else
+                               animate->firstFrame(1, sprite->sprite);
+               }
+               if (entity.has_component<Dialog>() && entity.component<Dialog>()->talking) {
+                       direction.x = 0;
+               } else {
+                       if (entity.has_component<Sprite>()) {
+                               auto& fl = entity.component<Sprite>()->faceLeft;
+                               if (direction.x != 0)
+                                       fl = (direction.x < 0);
+                       }
+
+                       auto ppos = PlayerSystem::getPosition();
+                       if (ppos.x > position.x && ppos.x < position.x + entity.component<Solid>()->width) {
+                               if (entity.has_component<Aggro>()) {
+                                       auto dim = entity.component<Solid>();
+                                       ev.emit<AttackEvent>(vec2(position.x + dim->width, position.y + dim->height),
+                                               AttackType::ShortSlash, false);
+                                       /*auto& h = entity.component<Health>()->health;
+                                       if (h > 0) {
+                                               fight = true;
+                                               toFight = entity;
+                                               h = 0;
+                                       }*/
+                               } else if (entity.has_component<Trigger>()) {
+                                       static bool triggering = false;
+                                       if (!triggering) {
+                                               triggering = true;
+                                               std::thread([&](entityx::Entity e) {
+                                                       UISystem::fadeToggle();
+                                                       UISystem::waitForCover();
+                                                       UISystem::dialogImportant(e.component<Trigger>()->text);
+                                                       UISystem::waitForDialog();
+                                                       UISystem::fadeToggle();
+                                                       e.destroy();
+                                                       triggering = false;
+                                               }, entity).detach();
+                                       }
+                                       return;
+                               }
+                       }
+
+                       // make the entity wander
+                       // TODO initialX and range?
+                       if (entity.has_component<Wander>()) {
+                               auto& countdown = entity.component<Wander>()->countdown;
+
+                               if (countdown > 0) {
+                                       countdown--;
+                               } else {
+                                       countdown = 5000 + randGet() % 10 * 100;
+                                       direction.x = (randGet() % 3 - 1) * 0.004f;
+                               }
+                       }
+               }
+       });
+
+//     if (fight) {
+//             UISystem::fadeToggleFast();
+//             UISystem::waitForCover();
+               //game::engine.getSystem<WorldSystem>()->fight(toFight);
+//             UISystem::fadeToggleFast();
+//     }
+}
+
diff --git a/src/systems/physics.cpp b/src/systems/physics.cpp
new file mode 100644 (file)
index 0000000..4cee110
--- /dev/null
@@ -0,0 +1,15 @@
+#include <systems/physics.hpp>
+
+#include <components/direction.hpp>
+#include <components/physics.hpp>
+
+void PhysicsSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
+{
+       (void)ev;
+       en.each<Direction, Physics>([dt](entityx::Entity entity, Direction &direction, Physics &physics) {
+               (void)entity;
+               // TODO GET GRAVITY FROM WORLD
+               direction.y += physics.g * dt;
+       });
+}
+
diff --git a/src/systems/render.cpp b/src/systems/render.cpp
new file mode 100644 (file)
index 0000000..ce79522
--- /dev/null
@@ -0,0 +1,146 @@
+#include <systems/render.hpp>
+
+#include <components/visible.hpp>
+#include <components/sprite.hpp>
+#include <components/position.hpp>
+#include <components/solid.hpp>
+#include <components/flash.hpp>
+
+#include <thread>
+#include <chrono>
+using namespace std::literals::chrono_literals;
+
+#include <glm.hpp>
+#include <render.hpp>
+#include <engine.hpp>
+#include <font.hpp>
+#include <ui.hpp>
+
+std::string RenderSystem::loadTexString;
+Texture     RenderSystem::loadTexResult;
+
+Texture RenderSystem::loadTexture(const std::string& file)
+{
+       loadTexString = file;
+       loadTexResult = Texture();
+       while (loadTexResult.isEmpty())
+               std::this_thread::sleep_for(1ms);
+       auto t = loadTexResult;
+       loadTexResult = Texture();
+       return t;
+}
+
+void RenderSystem::render(void)
+{      
+       if (!loadTexString.empty()) {
+               loadTexResult = Texture(loadTexString, false);
+               loadTexString.clear();
+       }
+
+       if (!loadTexResult.isEmpty())
+               return;
+
+       Render::worldShader.use();
+       Render::worldShader.enable();
+
+       game::entities.each<Visible, Sprite, Position>([](entityx::Entity entity, Visible &visible, Sprite &sprite, Position &pos) {
+               // Verticies and shit
+               float its = 0;
+               
+               float sz;
+               if (entity.has_component<Solid>())
+                       sz = entity.component<Solid>()->width;
+               else 
+                       sz = sprite.getSpriteSize().x;
+
+               if (sprite.faceLeft) {
+                       glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(-1.0f,1.0f,1.0f));
+                       glm::mat4 translate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f - sz - pos.x * 2.0f, 0.0f, 0.0f));
+
+                       glm::mat4 mov = scale * translate;
+                       glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(mov));
+               }
+
+               for (auto &S : sprite.sprite) {
+                       auto sp = S.first;
+                       auto size = sp.size * game::HLINE;
+                       vec2 drawOffset (HLINES(S.second.x), HLINES(S.second.y));
+                       vec2 loc (pos.x + drawOffset.x, pos.y + drawOffset.y);
+
+                       GLfloat verts[] = {
+                               loc.x,          loc.y,          visible.z + its, sp.offset_tex.x,                 sp.offset_tex.y,
+                               loc.x + size.x, loc.y,          visible.z + its, sp.offset_tex.x + sp.size_tex.x, sp.offset_tex.y,
+                               loc.x + size.x, loc.y + size.y, visible.z + its, sp.offset_tex.x + sp.size_tex.x, sp.offset_tex.y + sp.size_tex.y,
+                               loc.x,          loc.y,          visible.z + its, sp.offset_tex.x,                 sp.offset_tex.y,
+                               loc.x + size.x, loc.y + size.y, visible.z + its, sp.offset_tex.x + sp.size_tex.x, sp.offset_tex.y + sp.size_tex.y,
+                               loc.x,          loc.y + size.y, visible.z + its, sp.offset_tex.x,                 sp.offset_tex.y + sp.size_tex.y
+                       };
+
+                       sp.tex.use();
+
+                       glUniform1i(Render::worldShader.uniform[WU_texture], 0);
+
+                       glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), verts);
+                       glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), verts + 3);
+                       glDrawArrays(GL_TRIANGLES, 0, 6);
+
+                       if (entity.has_component<Flash>()) {
+                               auto& f = *entity.component<Flash>();
+                               if (f.ms > 0) {
+                                       verts[2] = verts[7] = verts[12] = verts[17] = verts[22] = verts[27] = visible.z + its - 0.001f;
+                                       float alpha = static_cast<float>(f.ms) / static_cast<float>(f.totalMs);
+                                       glUniform4f(Render::worldShader.uniform[WU_tex_color], f.color.red, f.color.green, f.color.blue, alpha);
+                                       glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), verts);
+                                       glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), verts + 3);
+                                       glDrawArrays(GL_TRIANGLES, 0, 6);
+                                       glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0);
+                               }
+                       }
+
+                       its-=.01;
+               }
+               glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
+
+               if (entity.has_component<Health>()) {
+                       float width = entity.component<Solid>()->width;
+                       auto& health = *entity.component<Health>();
+                       width *= health.health / static_cast<float>(health.maxHealth);
+
+                       GLfloat health_coord[] = {
+                               pos.x, pos.y, -9, 0, 0,
+                               pos.x + width, pos.y, -9, 0, 0,
+                               pos.x + width, pos.y - 5, -9, 0, 0,
+                               pos.x + width, pos.y - 5, -9, 0, 0,
+                               pos.x, pos.y - 5, -9, 0, 0,
+                               pos.x, pos.y, -9, 0, 0,
+                       };
+
+                       Colors::red.use();
+                       glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), health_coord);
+                       glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), health_coord + 3);
+                       glDrawArrays(GL_TRIANGLES, 0, 6);
+               }
+       });
+
+       Render::worldShader.disable();
+       Render::worldShader.unuse();
+
+       game::entities.each<Visible, Position, Solid, Name>([](entityx::Entity e, Visible &v, Position &pos, Solid& dim, Name &name) {
+               (void)e;
+               (void)v;
+               FontSystem::setFontZ(-5.0f);
+               UISystem::putStringCentered(vec2(pos.x + dim.width / 2, pos.y - FontSystem::getSize() - HLINES(0.5)), name.name);
+       });
+}
+
+void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
+{
+       (void)ev;
+       (void)dt;
+
+       en.each<Flash>([](entityx::Entity e, Flash& flash) {
+               if (--flash.ms <= 0) // TODO delta time?
+                       e.remove<Flash>();
+       });
+}
+