aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2017-06-13 21:01:08 -0400
committerClyne Sullivan <tullivan99@gmail.com>2017-06-13 21:01:08 -0400
commit316df0931c66e43e69f21bda28c77b9bdb1e8bca (patch)
treed98231e4b41d046a2a60ee9c6f1cc724a9e3837d
parent11b8e727e04ed6095164bb826541409f88047625 (diff)
component reorginization; entity flashes
-rw-r--r--Makefile29
-rw-r--r--include/components.hpp666
-rw-r--r--include/components/aggro.hpp25
-rw-r--r--include/components/all.hpp19
-rw-r--r--include/components/animate.hpp64
-rw-r--r--include/components/dialog.hpp31
-rw-r--r--include/components/direction.hpp42
-rw-r--r--include/components/flash.hpp15
-rw-r--r--include/components/grounded.hpp27
-rw-r--r--include/components/health.hpp34
-rw-r--r--include/components/hit.hpp19
-rw-r--r--include/components/hop.hpp14
-rw-r--r--include/components/itemdrop.hpp13
-rw-r--r--include/components/name.hpp24
-rw-r--r--include/components/physics.hpp31
-rw-r--r--include/components/player.hpp6
-rw-r--r--include/components/portal.hpp23
-rw-r--r--include/components/position.hpp37
-rw-r--r--include/components/solid.hpp45
-rw-r--r--include/components/sprite.hpp64
-rw-r--r--include/components/trigger.hpp25
-rw-r--r--include/components/visible.hpp30
-rw-r--r--include/components/wander.hpp16
-rw-r--r--include/systems/dialog.hpp16
-rw-r--r--include/systems/movement.hpp11
-rw-r--r--include/systems/physics.hpp11
-rw-r--r--include/systems/render.hpp23
-rw-r--r--src/components.cpp418
-rw-r--r--src/components/animate.cpp106
-rw-r--r--src/components/sprite.cpp155
-rw-r--r--src/engine.cpp1
-rw-r--r--src/systems/dialog.cpp161
-rw-r--r--src/systems/movement.cpp98
-rw-r--r--src/systems/physics.cpp15
-rw-r--r--src/systems/render.cpp146
35 files changed, 1370 insertions, 1090 deletions
diff --git a/Makefile b/Makefile
index 6aa05e2..4372c31 100644
--- 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
diff --git a/include/components.hpp b/include/components.hpp
index fe8e7a6..93d7196 100644
--- a/include/components.hpp
+++ b/include/components.hpp
@@ -8,669 +8,11 @@
#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
index 0000000..17d646c
--- /dev/null
+++ b/include/components/aggro.hpp
@@ -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_
diff --git a/include/components/all.hpp b/include/components/all.hpp
index 2fb3c8d..dda8938 100644
--- a/include/components/all.hpp
+++ b/include/components/all.hpp
@@ -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
index 0000000..116ee3f
--- /dev/null
+++ b/include/components/animate.hpp
@@ -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
index 0000000..8d26b92
--- /dev/null
+++ b/include/components/dialog.hpp
@@ -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
index 0000000..1229e49
--- /dev/null
+++ b/include/components/direction.hpp
@@ -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
index 0000000..e53c41c
--- /dev/null
+++ b/include/components/flash.hpp
@@ -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
index 0000000..017c118
--- /dev/null
+++ b/include/components/grounded.hpp
@@ -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
index 0000000..eacaaa5
--- /dev/null
+++ b/include/components/health.hpp
@@ -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
index 0000000..d2e80ca
--- /dev/null
+++ b/include/components/hit.hpp
@@ -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
index 0000000..f114265
--- /dev/null
+++ b/include/components/hop.hpp
@@ -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
index 0000000..681c0d6
--- /dev/null
+++ b/include/components/itemdrop.hpp
@@ -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
index 0000000..423a484
--- /dev/null
+++ b/include/components/name.hpp
@@ -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
index 0000000..8e462a9
--- /dev/null
+++ b/include/components/physics.hpp
@@ -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
index 0000000..afcaa90
--- /dev/null
+++ b/include/components/player.hpp
@@ -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
index 0000000..ca153e1
--- /dev/null
+++ b/include/components/portal.hpp
@@ -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
index 0000000..f040bec
--- /dev/null
+++ b/include/components/position.hpp
@@ -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
index 0000000..35bfcf7
--- /dev/null
+++ b/include/components/solid.hpp
@@ -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
index 0000000..35a13b8
--- /dev/null
+++ b/include/components/sprite.hpp
@@ -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
index 0000000..c9a53f6
--- /dev/null
+++ b/include/components/trigger.hpp
@@ -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
index 0000000..4785fb0
--- /dev/null
+++ b/include/components/visible.hpp
@@ -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
index 0000000..2001e89
--- /dev/null
+++ b/include/components/wander.hpp
@@ -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
index 0000000..407f043
--- /dev/null
+++ b/include/systems/dialog.hpp
@@ -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
index 0000000..fd37665
--- /dev/null
+++ b/include/systems/movement.hpp
@@ -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
index 0000000..9fd6981
--- /dev/null
+++ b/include/systems/physics.hpp
@@ -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
index 0000000..012c6fd
--- /dev/null
+++ b/include/systems/render.hpp
@@ -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
index 056d48b..0000000
--- a/src/components.cpp
+++ /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
index 0000000..2ac1465
--- /dev/null
+++ b/src/components/animate.cpp
@@ -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
index 0000000..053d36a
--- /dev/null
+++ b/src/components/sprite.cpp
@@ -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;
+}
diff --git a/src/engine.cpp b/src/engine.cpp
index 07b453c..b596c6e 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -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
index 0000000..0be0acb
--- /dev/null
+++ b/src/systems/dialog.cpp
@@ -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
index 0000000..00baa40
--- /dev/null
+++ b/src/systems/movement.cpp
@@ -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
index 0000000..4cee110
--- /dev/null
+++ b/src/systems/physics.cpp
@@ -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
index 0000000..ce79522
--- /dev/null
+++ b/src/systems/render.cpp
@@ -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>();
+ });
+}
+