diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/collision.h | 1 | ||||
-rw-r--r-- | src/components/mappable.h | 6 | ||||
-rw-r--r-- | src/components/playable.h | 2 | ||||
-rw-r--r-- | src/components/ponderable.h | 44 | ||||
-rw-r--r-- | src/game.cpp | 4 | ||||
-rw-r--r-- | src/game.h | 9 | ||||
-rw-r--r-- | src/map.h | 66 | ||||
-rw-r--r-- | src/prototype.cpp | 55 | ||||
-rw-r--r-- | src/prototype.h | 45 | ||||
-rw-r--r-- | src/prototype_manager.cpp | 71 | ||||
-rw-r--r-- | src/prototype_manager.h | 23 | ||||
-rw-r--r-- | src/systems/mapping.cpp | 14 | ||||
-rw-r--r-- | src/systems/playing.cpp | 33 | ||||
-rw-r--r-- | src/systems/playing.h | 2 | ||||
-rw-r--r-- | src/systems/pondering.cpp | 88 | ||||
-rw-r--r-- | src/systems/pondering.h | 9 | ||||
-rw-r--r-- | src/world.cpp | 67 | ||||
-rw-r--r-- | src/xml.cpp | 13 | ||||
-rw-r--r-- | src/xml.h | 8 |
20 files changed, 533 insertions, 30 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 34246ad..0309cd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -56,6 +56,9 @@ add_executable(Aromatherapy | |||
56 | src/world.cpp | 56 | src/world.cpp |
57 | src/util.cpp | 57 | src/util.cpp |
58 | src/collision.cpp | 58 | src/collision.cpp |
59 | src/prototype.cpp | ||
60 | src/prototype_manager.cpp | ||
61 | src/xml.cpp | ||
59 | src/renderer/renderer.cpp | 62 | src/renderer/renderer.cpp |
60 | src/renderer/mesh.cpp | 63 | src/renderer/mesh.cpp |
61 | src/renderer/shader.cpp | 64 | src/renderer/shader.cpp |
diff --git a/src/collision.h b/src/collision.h index e5371f8..0f62b98 100644 --- a/src/collision.h +++ b/src/collision.h | |||
@@ -15,6 +15,7 @@ public: | |||
15 | platform, | 15 | platform, |
16 | adjacency, | 16 | adjacency, |
17 | warp, | 17 | warp, |
18 | event, | ||
18 | danger | 19 | danger |
19 | }; | 20 | }; |
20 | 21 | ||
diff --git a/src/components/mappable.h b/src/components/mappable.h index 633cdf4..e26326d 100644 --- a/src/components/mappable.h +++ b/src/components/mappable.h | |||
@@ -125,6 +125,11 @@ public: | |||
125 | font_ = std::move(v); | 125 | font_ = std::move(v); |
126 | } | 126 | } |
127 | 127 | ||
128 | inline std::map<size_t, id_type>& getInstances() | ||
129 | { | ||
130 | return instances_; | ||
131 | } | ||
132 | |||
128 | private: | 133 | private: |
129 | 134 | ||
130 | size_t mapId_ = -1; | 135 | size_t mapId_ = -1; |
@@ -135,6 +140,7 @@ private: | |||
135 | asc_boundaries_type downBoundaries_; | 140 | asc_boundaries_type downBoundaries_; |
136 | Texture tileset_; | 141 | Texture tileset_; |
137 | Texture font_; | 142 | Texture font_; |
143 | std::map<size_t, id_type> instances_; | ||
138 | }; | 144 | }; |
139 | 145 | ||
140 | #endif /* end of include guard: MAPPABLE_H_0B0316FB */ | 146 | #endif /* end of include guard: MAPPABLE_H_0B0316FB */ |
diff --git a/src/components/playable.h b/src/components/playable.h index 86a7ee7..0d91929 100644 --- a/src/components/playable.h +++ b/src/components/playable.h | |||
@@ -18,6 +18,8 @@ public: | |||
18 | int checkpointMapId = -1; | 18 | int checkpointMapId = -1; |
19 | double checkpointX = 0; | 19 | double checkpointX = 0; |
20 | double checkpointY = 0; | 20 | double checkpointY = 0; |
21 | bool checkpointObjectActivated = false; | ||
22 | size_t checkpointObjectIndex = 0; | ||
21 | 23 | ||
22 | }; | 24 | }; |
23 | 25 | ||
diff --git a/src/components/ponderable.h b/src/components/ponderable.h index 78af25f..da509a2 100644 --- a/src/components/ponderable.h +++ b/src/components/ponderable.h | |||
@@ -2,22 +2,44 @@ | |||
2 | #define TANGIBLE_H_746DB3EE | 2 | #define TANGIBLE_H_746DB3EE |
3 | 3 | ||
4 | #include "component.h" | 4 | #include "component.h" |
5 | #include <functional> | ||
6 | #include <array> | ||
7 | |||
8 | class Game; | ||
5 | 9 | ||
6 | class PonderableComponent : public Component { | 10 | class PonderableComponent : public Component { |
7 | public: | 11 | public: |
8 | 12 | ||
9 | enum class Type { | 13 | enum class BodyType { |
10 | vacuumed, | 14 | vacuumed, |
11 | freefalling | 15 | freefalling |
12 | }; | 16 | }; |
13 | 17 | ||
14 | PonderableComponent(Type type) : type_(type) | 18 | enum class ColliderType { |
19 | player, | ||
20 | event | ||
21 | }; | ||
22 | |||
23 | static const size_t COLLIDER_TYPES = 2; | ||
24 | |||
25 | PonderableComponent( | ||
26 | BodyType bodyType, | ||
27 | ColliderType colliderType) : | ||
28 | bodyType_(bodyType), | ||
29 | colliderType_(colliderType) | ||
30 | { | ||
31 | } | ||
32 | |||
33 | using event_callback_type = std::function<void(Game& game)>; | ||
34 | |||
35 | inline BodyType getBodyType() const | ||
15 | { | 36 | { |
37 | return bodyType_; | ||
16 | } | 38 | } |
17 | 39 | ||
18 | inline Type getType() const | 40 | inline ColliderType getColliderType() const |
19 | { | 41 | { |
20 | return type_; | 42 | return colliderType_; |
21 | } | 43 | } |
22 | 44 | ||
23 | inline double getVelocityX() const | 45 | inline double getVelocityX() const |
@@ -90,16 +112,28 @@ public: | |||
90 | collidable_ = v; | 112 | collidable_ = v; |
91 | } | 113 | } |
92 | 114 | ||
115 | inline const event_callback_type& getEventCallback(ColliderType v) const | ||
116 | { | ||
117 | return eventCallbacks_[static_cast<size_t>(v)]; | ||
118 | } | ||
119 | |||
120 | inline void setEventCallback(ColliderType v, event_callback_type callback) | ||
121 | { | ||
122 | eventCallbacks_[static_cast<size_t>(v)] = std::move(callback); | ||
123 | } | ||
124 | |||
93 | private: | 125 | private: |
94 | 126 | ||
95 | double velX_ = 0.0; | 127 | double velX_ = 0.0; |
96 | double velY_ = 0.0; | 128 | double velY_ = 0.0; |
97 | double accelX_ = 0.0; | 129 | double accelX_ = 0.0; |
98 | double accelY_ = 0.0; | 130 | double accelY_ = 0.0; |
99 | Type type_ = Type::vacuumed; | 131 | BodyType bodyType_; |
132 | ColliderType colliderType_; | ||
100 | bool grounded_ = false; | 133 | bool grounded_ = false; |
101 | bool frozen_ = false; | 134 | bool frozen_ = false; |
102 | bool collidable_ = true; | 135 | bool collidable_ = true; |
136 | std::array<event_callback_type, COLLIDER_TYPES> eventCallbacks_; | ||
103 | }; | 137 | }; |
104 | 138 | ||
105 | #endif /* end of include guard: TANGIBLE_H_746DB3EE */ | 139 | #endif /* end of include guard: TANGIBLE_H_746DB3EE */ |
diff --git a/src/game.cpp b/src/game.cpp index 3da23a3..5259739 100644 --- a/src/game.cpp +++ b/src/game.cpp | |||
@@ -28,7 +28,9 @@ void key_callback(GLFWwindow* window, int key, int, int action, int) | |||
28 | game.systemManager_.input(key, action); | 28 | game.systemManager_.input(key, action); |
29 | } | 29 | } |
30 | 30 | ||
31 | Game::Game() : world_("res/maps.xml") | 31 | Game::Game() : |
32 | world_("res/maps.xml"), | ||
33 | prototypes_("res/entities.xml") | ||
32 | { | 34 | { |
33 | systemManager_.emplaceSystem<PlayingSystem>(*this); | 35 | systemManager_.emplaceSystem<PlayingSystem>(*this); |
34 | systemManager_.emplaceSystem<SchedulingSystem>(*this); | 36 | systemManager_.emplaceSystem<SchedulingSystem>(*this); |
diff --git a/src/game.h b/src/game.h index 43e08da..2dd7f91 100644 --- a/src/game.h +++ b/src/game.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "system_manager.h" | 5 | #include "system_manager.h" |
6 | #include "world.h" | 6 | #include "world.h" |
7 | #include "renderer/renderer.h" | 7 | #include "renderer/renderer.h" |
8 | #include "prototype_manager.h" | ||
8 | 9 | ||
9 | class Game { | 10 | class Game { |
10 | public: | 11 | public: |
@@ -28,11 +29,16 @@ public: | |||
28 | return systemManager_; | 29 | return systemManager_; |
29 | } | 30 | } |
30 | 31 | ||
31 | inline const World& getWorld() | 32 | inline const World& getWorld() const |
32 | { | 33 | { |
33 | return world_; | 34 | return world_; |
34 | } | 35 | } |
35 | 36 | ||
37 | inline const PrototypeManager& getPrototypeManager() const | ||
38 | { | ||
39 | return prototypes_; | ||
40 | } | ||
41 | |||
36 | friend void key_callback( | 42 | friend void key_callback( |
37 | GLFWwindow* window, | 43 | GLFWwindow* window, |
38 | int key, | 44 | int key, |
@@ -46,6 +52,7 @@ private: | |||
46 | EntityManager entityManager_; | 52 | EntityManager entityManager_; |
47 | SystemManager systemManager_; | 53 | SystemManager systemManager_; |
48 | World world_; | 54 | World world_; |
55 | PrototypeManager prototypes_; | ||
49 | bool shouldQuit_ = false; | 56 | bool shouldQuit_ = false; |
50 | }; | 57 | }; |
51 | 58 | ||
diff --git a/src/map.h b/src/map.h index 6fe1e62..0e11b9d 100644 --- a/src/map.h +++ b/src/map.h | |||
@@ -4,7 +4,6 @@ | |||
4 | #include <vector> | 4 | #include <vector> |
5 | #include <string> | 5 | #include <string> |
6 | #include <list> | 6 | #include <list> |
7 | #include <stdexcept> | ||
8 | #include <map> | 7 | #include <map> |
9 | 8 | ||
10 | class Map { | 9 | class Map { |
@@ -44,6 +43,59 @@ public: | |||
44 | int mapId_; | 43 | int mapId_; |
45 | }; | 44 | }; |
46 | 45 | ||
46 | class Object { | ||
47 | public: | ||
48 | |||
49 | Object( | ||
50 | std::string type, | ||
51 | double x, | ||
52 | double y, | ||
53 | size_t index, | ||
54 | std::map<std::string, int> items) : | ||
55 | type_(std::move(type)), | ||
56 | x_(x), | ||
57 | y_(y), | ||
58 | index_(index), | ||
59 | items_(std::move(items)) | ||
60 | { | ||
61 | } | ||
62 | |||
63 | inline const std::string& getType() const | ||
64 | { | ||
65 | return type_; | ||
66 | } | ||
67 | |||
68 | inline double getX() const | ||
69 | { | ||
70 | return x_; | ||
71 | } | ||
72 | |||
73 | inline double getY() const | ||
74 | { | ||
75 | return y_; | ||
76 | } | ||
77 | |||
78 | inline size_t getIndex() const | ||
79 | { | ||
80 | return index_; | ||
81 | } | ||
82 | |||
83 | inline const std::map<std::string, int>& getItems() const | ||
84 | { | ||
85 | return items_; | ||
86 | } | ||
87 | |||
88 | private: | ||
89 | |||
90 | std::string type_; | ||
91 | double x_; | ||
92 | double y_; | ||
93 | size_t index_; | ||
94 | std::map<std::string, int> items_; | ||
95 | }; | ||
96 | |||
97 | using object_storage_type = std::list<Object>; | ||
98 | |||
47 | Map( | 99 | Map( |
48 | int id, | 100 | int id, |
49 | std::vector<int> tiles, | 101 | std::vector<int> tiles, |
@@ -51,14 +103,16 @@ public: | |||
51 | Adjacent leftAdjacent, | 103 | Adjacent leftAdjacent, |
52 | Adjacent rightAdjacent, | 104 | Adjacent rightAdjacent, |
53 | Adjacent upAdjacent, | 105 | Adjacent upAdjacent, |
54 | Adjacent downAdjacent) : | 106 | Adjacent downAdjacent, |
107 | object_storage_type objects) : | ||
55 | id_(id), | 108 | id_(id), |
56 | tiles_(std::move(tiles)), | 109 | tiles_(std::move(tiles)), |
57 | title_(std::move(title)), | 110 | title_(std::move(title)), |
58 | leftAdjacent_(std::move(leftAdjacent)), | 111 | leftAdjacent_(std::move(leftAdjacent)), |
59 | rightAdjacent_(std::move(rightAdjacent)), | 112 | rightAdjacent_(std::move(rightAdjacent)), |
60 | upAdjacent_(std::move(upAdjacent)), | 113 | upAdjacent_(std::move(upAdjacent)), |
61 | downAdjacent_(std::move(downAdjacent)) | 114 | downAdjacent_(std::move(downAdjacent)), |
115 | objects_(std::move(objects)) | ||
62 | { | 116 | { |
63 | } | 117 | } |
64 | 118 | ||
@@ -97,6 +151,11 @@ public: | |||
97 | return downAdjacent_; | 151 | return downAdjacent_; |
98 | } | 152 | } |
99 | 153 | ||
154 | inline const object_storage_type& getObjects() const | ||
155 | { | ||
156 | return objects_; | ||
157 | } | ||
158 | |||
100 | private: | 159 | private: |
101 | 160 | ||
102 | int id_; | 161 | int id_; |
@@ -106,6 +165,7 @@ private: | |||
106 | Adjacent rightAdjacent_; | 165 | Adjacent rightAdjacent_; |
107 | Adjacent upAdjacent_; | 166 | Adjacent upAdjacent_; |
108 | Adjacent downAdjacent_; | 167 | Adjacent downAdjacent_; |
168 | object_storage_type objects_; | ||
109 | }; | 169 | }; |
110 | 170 | ||
111 | #endif /* end of include guard: MAP_H_74055FC0 */ | 171 | #endif /* end of include guard: MAP_H_74055FC0 */ |
diff --git a/src/prototype.cpp b/src/prototype.cpp new file mode 100644 index 0000000..a4a0e80 --- /dev/null +++ b/src/prototype.cpp | |||
@@ -0,0 +1,55 @@ | |||
1 | #include "prototype.h" | ||
2 | #include "game.h" | ||
3 | #include "animation.h" | ||
4 | #include "components/animatable.h" | ||
5 | #include "components/transformable.h" | ||
6 | #include "components/ponderable.h" | ||
7 | #include "systems/pondering.h" | ||
8 | #include "systems/playing.h" | ||
9 | |||
10 | id_type Prototype::instantiate( | ||
11 | Game& game, | ||
12 | const Map::Object& object) const | ||
13 | { | ||
14 | id_type entity = game.getEntityManager().emplaceEntity(); | ||
15 | |||
16 | AnimationSet entityGraphics(spritePath_.c_str(), w_, h_, 1); | ||
17 | entityGraphics.emplaceAnimation("default", 0, 1, 1); | ||
18 | |||
19 | game.getEntityManager().emplaceComponent<AnimatableComponent>( | ||
20 | entity, | ||
21 | std::move(entityGraphics), | ||
22 | "default"); | ||
23 | |||
24 | game.getEntityManager().emplaceComponent<TransformableComponent>( | ||
25 | entity, | ||
26 | object.getX(), | ||
27 | object.getY(), | ||
28 | w_, | ||
29 | h_); | ||
30 | |||
31 | game.getSystemManager().getSystem<PonderingSystem>().initializeBody( | ||
32 | entity, | ||
33 | PonderableComponent::BodyType::vacuumed, | ||
34 | PonderableComponent::ColliderType::event); | ||
35 | |||
36 | auto& ponderable = game.getEntityManager(). | ||
37 | getComponent<PonderableComponent>(entity); | ||
38 | |||
39 | switch (action_) | ||
40 | { | ||
41 | case Action::save: | ||
42 | { | ||
43 | ponderable.setEventCallback(PonderableComponent::ColliderType::player, | ||
44 | [] (Game& game) { | ||
45 | auto& playing = game.getSystemManager().getSystem<PlayingSystem>(); | ||
46 | |||
47 | playing.save(); | ||
48 | }); | ||
49 | |||
50 | break; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | return entity; | ||
55 | } | ||
diff --git a/src/prototype.h b/src/prototype.h new file mode 100644 index 0000000..03df00f --- /dev/null +++ b/src/prototype.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef PROTOTYPE_H_BB208E0F | ||
2 | #define PROTOTYPE_H_BB208E0F | ||
3 | |||
4 | #include <string> | ||
5 | #include <map> | ||
6 | #include "map.h" | ||
7 | #include "entity_manager.h" | ||
8 | |||
9 | class Game; | ||
10 | |||
11 | class Prototype { | ||
12 | public: | ||
13 | |||
14 | using id_type = EntityManager::id_type; | ||
15 | |||
16 | enum class Action { | ||
17 | none, | ||
18 | save | ||
19 | }; | ||
20 | |||
21 | Prototype( | ||
22 | int w, | ||
23 | int h, | ||
24 | std::string spritePath, | ||
25 | Action action) : | ||
26 | w_(w), | ||
27 | h_(h), | ||
28 | spritePath_(std::move(spritePath)), | ||
29 | action_(action) | ||
30 | { | ||
31 | } | ||
32 | |||
33 | id_type instantiate( | ||
34 | Game& game, | ||
35 | const Map::Object& object) const; | ||
36 | |||
37 | private: | ||
38 | |||
39 | int w_; | ||
40 | int h_; | ||
41 | std::string spritePath_; | ||
42 | Action action_; | ||
43 | }; | ||
44 | |||
45 | #endif /* end of include guard: PROTOTYPE_H_BB208E0F */ | ||
diff --git a/src/prototype_manager.cpp b/src/prototype_manager.cpp new file mode 100644 index 0000000..250aa59 --- /dev/null +++ b/src/prototype_manager.cpp | |||
@@ -0,0 +1,71 @@ | |||
1 | #include "prototype_manager.h" | ||
2 | #include <utility> | ||
3 | #include <stdexcept> | ||
4 | #include "xml.h" | ||
5 | |||
6 | PrototypeManager::PrototypeManager(std::string path) | ||
7 | { | ||
8 | xmlDocPtr doc = xmlParseFile(path.c_str()); | ||
9 | if (doc == nullptr) | ||
10 | { | ||
11 | throw std::invalid_argument("Cannot find prototypes file"); | ||
12 | } | ||
13 | |||
14 | xmlNodePtr top = xmlDocGetRootElement(doc); | ||
15 | if (top == nullptr) | ||
16 | { | ||
17 | throw std::invalid_argument("Error parsing prototypes file"); | ||
18 | } | ||
19 | |||
20 | if (xmlStrcmp(top->name, reinterpret_cast<const xmlChar*>("entities"))) | ||
21 | { | ||
22 | throw std::invalid_argument("Error parsing prototypes file"); | ||
23 | } | ||
24 | |||
25 | xmlChar* key = nullptr; | ||
26 | |||
27 | for (xmlNodePtr node = top->xmlChildrenNode; | ||
28 | node != nullptr; | ||
29 | node = node->next) | ||
30 | { | ||
31 | if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("entity"))) | ||
32 | { | ||
33 | key = getProp(node, "id"); | ||
34 | std::string prototypeName(reinterpret_cast<char*>(key)); | ||
35 | xmlFree(key); | ||
36 | |||
37 | key = getProp(node, "sprite"); | ||
38 | std::string spritePath(reinterpret_cast<char*>(key)); | ||
39 | xmlFree(key); | ||
40 | |||
41 | key = getProp(node, "width"); | ||
42 | int width = atoi(reinterpret_cast<char*>(key)); | ||
43 | xmlFree(key); | ||
44 | |||
45 | key = getProp(node, "height"); | ||
46 | int height = atoi(reinterpret_cast<char*>(key)); | ||
47 | xmlFree(key); | ||
48 | |||
49 | key = getProp(node, "action"); | ||
50 | std::string actionStr(reinterpret_cast<char*>(key)); | ||
51 | xmlFree(key); | ||
52 | |||
53 | Prototype::Action pAction = Prototype::Action::none; | ||
54 | if (actionStr == "save") | ||
55 | { | ||
56 | pAction = Prototype::Action::save; | ||
57 | } | ||
58 | |||
59 | prototypes_.emplace( | ||
60 | std::piecewise_construct, | ||
61 | std::tie(prototypeName), | ||
62 | std::tie( | ||
63 | width, | ||
64 | height, | ||
65 | spritePath, | ||
66 | pAction)); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | xmlFreeDoc(doc); | ||
71 | } | ||
diff --git a/src/prototype_manager.h b/src/prototype_manager.h new file mode 100644 index 0000000..3fadd23 --- /dev/null +++ b/src/prototype_manager.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef PROTOTYPE_MANAGER_H_83CECCA6 | ||
2 | #define PROTOTYPE_MANAGER_H_83CECCA6 | ||
3 | |||
4 | #include <string> | ||
5 | #include <map> | ||
6 | #include "prototype.h" | ||
7 | |||
8 | class PrototypeManager { | ||
9 | public: | ||
10 | |||
11 | PrototypeManager(std::string path); | ||
12 | |||
13 | inline const Prototype& getPrototype(std::string name) const | ||
14 | { | ||
15 | return prototypes_.at(name); | ||
16 | } | ||
17 | |||
18 | private: | ||
19 | |||
20 | std::map<std::string, Prototype> prototypes_; | ||
21 | }; | ||
22 | |||
23 | #endif /* end of include guard: PROTOTYPE_MANAGER_H_83CECCA6 */ | ||
diff --git a/src/systems/mapping.cpp b/src/systems/mapping.cpp index a3a17ec..c7c2f9d 100644 --- a/src/systems/mapping.cpp +++ b/src/systems/mapping.cpp | |||
@@ -195,4 +195,18 @@ void MappingSystem::loadMap(size_t mapId) | |||
195 | MappableComponent::Boundary::Type::danger); | 195 | MappableComponent::Boundary::Type::danger); |
196 | } | 196 | } |
197 | } | 197 | } |
198 | |||
199 | for (const Map::Object& object : map.getObjects()) | ||
200 | { | ||
201 | const Prototype& prototype = game_.getPrototypeManager(). | ||
202 | getPrototype(object.getType()); | ||
203 | |||
204 | id_type emplacedObject = prototype.instantiate( | ||
205 | game_, | ||
206 | object.getX(), | ||
207 | object.getY(), | ||
208 | object.getItems()); | ||
209 | |||
210 | mappable.getInstances()[object.getIndex()] = emplacedObject; | ||
211 | } | ||
198 | } | 212 | } |
diff --git a/src/systems/playing.cpp b/src/systems/playing.cpp index 40d9706..5077f8a 100644 --- a/src/systems/playing.cpp +++ b/src/systems/playing.cpp | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "components/playable.h" | 5 | #include "components/playable.h" |
6 | #include "components/controllable.h" | 6 | #include "components/controllable.h" |
7 | #include "components/orientable.h" | 7 | #include "components/orientable.h" |
8 | #include "components/mappable.h" | ||
8 | #include "systems/mapping.h" | 9 | #include "systems/mapping.h" |
9 | #include "systems/pondering.h" | 10 | #include "systems/pondering.h" |
10 | #include "systems/orienting.h" | 11 | #include "systems/orienting.h" |
@@ -84,7 +85,8 @@ void PlayingSystem::initPlayer() | |||
84 | 85 | ||
85 | game_.getSystemManager().getSystem<PonderingSystem>().initializeBody( | 86 | game_.getSystemManager().getSystem<PonderingSystem>().initializeBody( |
86 | player, | 87 | player, |
87 | PonderableComponent::Type::freefalling); | 88 | PonderableComponent::BodyType::freefalling, |
89 | PonderableComponent::ColliderType::player); | ||
88 | 90 | ||
89 | game_.getEntityManager().emplaceComponent<ControllableComponent>(player); | 91 | game_.getEntityManager().emplaceComponent<ControllableComponent>(player); |
90 | game_.getEntityManager().emplaceComponent<OrientableComponent>(player); | 92 | game_.getEntityManager().emplaceComponent<OrientableComponent>(player); |
@@ -173,3 +175,32 @@ void PlayingSystem::die() | |||
173 | }); | 175 | }); |
174 | } | 176 | } |
175 | } | 177 | } |
178 | |||
179 | void PlayingSystem::save() | ||
180 | { | ||
181 | playSound("res/Pickup_Coin23.wav", 0.25); | ||
182 | |||
183 | auto players = game_.getEntityManager().getEntitiesWithComponents< | ||
184 | TransformableComponent, | ||
185 | PlayableComponent>(); | ||
186 | |||
187 | auto maps = game_.getEntityManager().getEntitiesWithComponents< | ||
188 | MappableComponent>(); | ||
189 | |||
190 | auto& mappable = game_.getEntityManager(). | ||
191 | getComponent<MappableComponent>(*maps.begin()); | ||
192 | |||
193 | for (id_type player : players) | ||
194 | { | ||
195 | auto& transformable = game_.getEntityManager(). | ||
196 | getComponent<TransformableComponent>(player); | ||
197 | |||
198 | auto& playable = game_.getEntityManager(). | ||
199 | getComponent<PlayableComponent>(player); | ||
200 | |||
201 | playable.checkpointMapId = mappable.getMapId(); | ||
202 | playable.checkpointX = transformable.getX(); | ||
203 | playable.checkpointY = transformable.getY(); | ||
204 | playable.checkpointObjectActivated = false; | ||
205 | } | ||
206 | } | ||
diff --git a/src/systems/playing.h b/src/systems/playing.h index ff16808..d7f5072 100644 --- a/src/systems/playing.h +++ b/src/systems/playing.h | |||
@@ -23,6 +23,8 @@ public: | |||
23 | 23 | ||
24 | void die(); | 24 | void die(); |
25 | 25 | ||
26 | void save(); | ||
27 | |||
26 | }; | 28 | }; |
27 | 29 | ||
28 | #endif /* end of include guard: PLAYING_H_70A54F7D */ | 30 | #endif /* end of include guard: PLAYING_H_70A54F7D */ |
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index 02d5cfc..9115988 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp | |||
@@ -39,7 +39,7 @@ void PonderingSystem::tick(double dt) | |||
39 | ponderable.setVelocityY( | 39 | ponderable.setVelocityY( |
40 | ponderable.getVelocityY() + ponderable.getAccelY() * dt); | 40 | ponderable.getVelocityY() + ponderable.getAccelY() * dt); |
41 | 41 | ||
42 | if ((ponderable.getType() == PonderableComponent::Type::freefalling) | 42 | if ((ponderable.getBodyType() == PonderableComponent::BodyType::freefalling) |
43 | && (ponderable.getVelocityY() > TERMINAL_VELOCITY)) | 43 | && (ponderable.getVelocityY() > TERMINAL_VELOCITY)) |
44 | { | 44 | { |
45 | ponderable.setVelocityY(TERMINAL_VELOCITY); | 45 | ponderable.setVelocityY(TERMINAL_VELOCITY); |
@@ -58,7 +58,7 @@ void PonderingSystem::tick(double dt) | |||
58 | 58 | ||
59 | std::priority_queue<Collision> collisions; | 59 | std::priority_queue<Collision> collisions; |
60 | 60 | ||
61 | // Find collisions | 61 | // Find map collisions |
62 | for (id_type mapEntity : maps) | 62 | for (id_type mapEntity : maps) |
63 | { | 63 | { |
64 | auto& mappable = game_.getEntityManager(). | 64 | auto& mappable = game_.getEntityManager(). |
@@ -366,6 +366,51 @@ void PonderingSystem::tick(double dt) | |||
366 | } | 366 | } |
367 | } | 367 | } |
368 | 368 | ||
369 | // Find body collisions | ||
370 | for (id_type body : entities) | ||
371 | { | ||
372 | // Can't collide with self | ||
373 | if (body == entity) | ||
374 | { | ||
375 | continue; | ||
376 | } | ||
377 | |||
378 | // Make sure the body is collidable | ||
379 | auto& colliderPonderable = | ||
380 | game_.getEntityManager().getComponent<PonderableComponent>(body); | ||
381 | |||
382 | if (!colliderPonderable.isCollidable()) | ||
383 | { | ||
384 | continue; | ||
385 | } | ||
386 | |||
387 | // Test if the body was already colliding | ||
388 | auto& colliderTransformable = | ||
389 | game_.getEntityManager().getComponent<TransformableComponent>(body); | ||
390 | |||
391 | if ((oldRight > colliderTransformable.getX()) | ||
392 | && (oldX < colliderTransformable.getX() + colliderTransformable.getW()) | ||
393 | && (oldBottom > colliderTransformable.getY()) | ||
394 | && (oldY < colliderTransformable.getY() + colliderTransformable.getH())) | ||
395 | { | ||
396 | continue; | ||
397 | } | ||
398 | |||
399 | // Test if there is a new collision | ||
400 | if (!((newX + transformable.getW() > colliderTransformable.getX()) | ||
401 | && (newX < colliderTransformable.getX() + colliderTransformable.getW()) | ||
402 | && (newY + transformable.getH() > colliderTransformable.getY()) | ||
403 | && (newY < | ||
404 | colliderTransformable.getY() + colliderTransformable.getH()))) | ||
405 | { | ||
406 | continue; | ||
407 | } | ||
408 | |||
409 | // Process the collision | ||
410 | processBodyCollision(entity, body); | ||
411 | processBodyCollision(body, entity); | ||
412 | } | ||
413 | |||
369 | // Move | 414 | // Move |
370 | transformable.setX(newX); | 415 | transformable.setX(newX); |
371 | transformable.setY(newY); | 416 | transformable.setY(newY); |
@@ -399,13 +444,46 @@ void PonderingSystem::tick(double dt) | |||
399 | 444 | ||
400 | void PonderingSystem::initializeBody( | 445 | void PonderingSystem::initializeBody( |
401 | id_type entity, | 446 | id_type entity, |
402 | PonderableComponent::Type type) | 447 | PonderableComponent::BodyType bodyType, |
448 | PonderableComponent::ColliderType colliderType) | ||
403 | { | 449 | { |
404 | auto& ponderable = game_.getEntityManager(). | 450 | auto& ponderable = game_.getEntityManager(). |
405 | emplaceComponent<PonderableComponent>(entity, type); | 451 | emplaceComponent<PonderableComponent>(entity, bodyType, colliderType); |
406 | 452 | ||
407 | if (type == PonderableComponent::Type::freefalling) | 453 | if (bodyType == PonderableComponent::BodyType::freefalling) |
408 | { | 454 | { |
409 | ponderable.setAccelY(NORMAL_GRAVITY); | 455 | ponderable.setAccelY(NORMAL_GRAVITY); |
410 | } | 456 | } |
411 | } | 457 | } |
458 | |||
459 | void PonderingSystem::processBodyCollision(id_type body, id_type collider) | ||
460 | { | ||
461 | auto& bodyPonderable = game_.getEntityManager(). | ||
462 | getComponent<PonderableComponent>(body); | ||
463 | |||
464 | auto& colliderPonderable = game_.getEntityManager(). | ||
465 | getComponent<PonderableComponent>(collider); | ||
466 | |||
467 | switch (colliderPonderable.getColliderType()) | ||
468 | { | ||
469 | case PonderableComponent::ColliderType::event: | ||
470 | { | ||
471 | auto& callback = colliderPonderable. | ||
472 | getEventCallback(bodyPonderable.getColliderType()); | ||
473 | |||
474 | if (callback) | ||
475 | { | ||
476 | callback(game_); | ||
477 | } | ||
478 | |||
479 | break; | ||
480 | } | ||
481 | |||
482 | default: | ||
483 | { | ||
484 | // Do nothing. | ||
485 | |||
486 | break; | ||
487 | } | ||
488 | } | ||
489 | } | ||
diff --git a/src/systems/pondering.h b/src/systems/pondering.h index d70525b..7e342df 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h | |||
@@ -14,7 +14,14 @@ public: | |||
14 | 14 | ||
15 | void tick(double dt); | 15 | void tick(double dt); |
16 | 16 | ||
17 | void initializeBody(id_type entity, PonderableComponent::Type type); | 17 | void initializeBody( |
18 | id_type entity, | ||
19 | PonderableComponent::BodyType bodyType, | ||
20 | PonderableComponent::ColliderType colliderType); | ||
21 | |||
22 | private: | ||
23 | |||
24 | void processBodyCollision(id_type body, id_type collider); | ||
18 | 25 | ||
19 | }; | 26 | }; |
20 | 27 | ||
diff --git a/src/world.cpp b/src/world.cpp index 3b6bd41..d239067 100644 --- a/src/world.cpp +++ b/src/world.cpp | |||
@@ -1,19 +1,8 @@ | |||
1 | #include "world.h" | 1 | #include "world.h" |
2 | #include <libxml/parser.h> | ||
3 | #include <stdexcept> | 2 | #include <stdexcept> |
4 | #include <cstring> | 3 | #include <cstring> |
5 | #include "consts.h" | 4 | #include "consts.h" |
6 | 5 | #include "xml.h" | |
7 | inline xmlChar* getProp(xmlNodePtr node, const char* attr) | ||
8 | { | ||
9 | xmlChar* key = xmlGetProp(node, reinterpret_cast<const xmlChar*>(attr)); | ||
10 | if (key == nullptr) | ||
11 | { | ||
12 | throw std::invalid_argument("Error parsing world file"); | ||
13 | } | ||
14 | |||
15 | return key; | ||
16 | } | ||
17 | 6 | ||
18 | World::World(std::string filename) | 7 | World::World(std::string filename) |
19 | { | 8 | { |
@@ -67,6 +56,7 @@ World::World(std::string filename) | |||
67 | Map::Adjacent rightAdj; | 56 | Map::Adjacent rightAdj; |
68 | Map::Adjacent upAdj; | 57 | Map::Adjacent upAdj; |
69 | Map::Adjacent downAdj; | 58 | Map::Adjacent downAdj; |
59 | std::list<Map::Object> objects; | ||
70 | 60 | ||
71 | for (xmlNodePtr mapNode = node->xmlChildrenNode; | 61 | for (xmlNodePtr mapNode = node->xmlChildrenNode; |
72 | mapNode != nullptr; | 62 | mapNode != nullptr; |
@@ -77,6 +67,10 @@ World::World(std::string filename) | |||
77 | reinterpret_cast<const xmlChar*>("environment"))) | 67 | reinterpret_cast<const xmlChar*>("environment"))) |
78 | { | 68 | { |
79 | key = xmlNodeGetContent(mapNode); | 69 | key = xmlNodeGetContent(mapNode); |
70 | if (key == nullptr) | ||
71 | { | ||
72 | throw std::invalid_argument("Error parsing XML file"); | ||
73 | } | ||
80 | 74 | ||
81 | mapTiles.clear(); | 75 | mapTiles.clear(); |
82 | mapTiles.push_back(atoi(strtok(reinterpret_cast<char*>(key), ",\n"))); | 76 | mapTiles.push_back(atoi(strtok(reinterpret_cast<char*>(key), ",\n"))); |
@@ -88,6 +82,52 @@ World::World(std::string filename) | |||
88 | xmlFree(key); | 82 | xmlFree(key); |
89 | } else if (!xmlStrcmp( | 83 | } else if (!xmlStrcmp( |
90 | mapNode->name, | 84 | mapNode->name, |
85 | reinterpret_cast<const xmlChar*>("entity"))) | ||
86 | { | ||
87 | key = getProp(mapNode, "type"); | ||
88 | std::string entType(reinterpret_cast<char*>(key)); | ||
89 | xmlFree(key); | ||
90 | |||
91 | key = getProp(mapNode, "x"); | ||
92 | int entX = atoi(reinterpret_cast<char*>(key)); | ||
93 | xmlFree(key); | ||
94 | |||
95 | key = getProp(mapNode, "y"); | ||
96 | int entY = atoi(reinterpret_cast<char*>(key)); | ||
97 | xmlFree(key); | ||
98 | |||
99 | key = getProp(mapNode, "index"); | ||
100 | int entIndex = atoi(reinterpret_cast<char*>(key)); | ||
101 | xmlFree(key); | ||
102 | |||
103 | std::map<std::string, int> items; | ||
104 | |||
105 | for (xmlNodePtr entityNode = mapNode->xmlChildrenNode; | ||
106 | entityNode != nullptr; | ||
107 | entityNode = entityNode->next) | ||
108 | { | ||
109 | key = getProp(entityNode, "id"); | ||
110 | std::string itemId(reinterpret_cast<char*>(key)); | ||
111 | xmlFree(key); | ||
112 | |||
113 | key = xmlNodeGetContent(entityNode); | ||
114 | if (key == nullptr) | ||
115 | { | ||
116 | throw std::invalid_argument("Error parsing XML file"); | ||
117 | } | ||
118 | |||
119 | items[itemId] = atoi(reinterpret_cast<char*>(key)); | ||
120 | xmlFree(key); | ||
121 | } | ||
122 | |||
123 | objects.emplace_back( | ||
124 | std::move(entType), | ||
125 | entX, | ||
126 | entY, | ||
127 | entIndex, | ||
128 | std::move(items)); | ||
129 | } else if (!xmlStrcmp( | ||
130 | mapNode->name, | ||
91 | reinterpret_cast<const xmlChar*>("adjacent"))) | 131 | reinterpret_cast<const xmlChar*>("adjacent"))) |
92 | { | 132 | { |
93 | key = getProp(mapNode, "type"); | 133 | key = getProp(mapNode, "type"); |
@@ -147,7 +187,8 @@ World::World(std::string filename) | |||
147 | leftAdj, | 187 | leftAdj, |
148 | rightAdj, | 188 | rightAdj, |
149 | upAdj, | 189 | upAdj, |
150 | downAdj)); | 190 | downAdj, |
191 | std::move(objects))); | ||
151 | } | 192 | } |
152 | } | 193 | } |
153 | 194 | ||
diff --git a/src/xml.cpp b/src/xml.cpp new file mode 100644 index 0000000..f6f60ea --- /dev/null +++ b/src/xml.cpp | |||
@@ -0,0 +1,13 @@ | |||
1 | #include "xml.h" | ||
2 | #include <stdexcept> | ||
3 | |||
4 | xmlChar* getProp(xmlNodePtr node, const char* attr) | ||
5 | { | ||
6 | xmlChar* key = xmlGetProp(node, reinterpret_cast<const xmlChar*>(attr)); | ||
7 | if (key == nullptr) | ||
8 | { | ||
9 | throw std::invalid_argument("Error parsing XML file"); | ||
10 | } | ||
11 | |||
12 | return key; | ||
13 | } | ||
diff --git a/src/xml.h b/src/xml.h new file mode 100644 index 0000000..8ecf639 --- /dev/null +++ b/src/xml.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef XML_H_E5E95685 | ||
2 | #define XML_H_E5E95685 | ||
3 | |||
4 | #include <libxml/parser.h> | ||
5 | |||
6 | xmlChar* getProp(xmlNodePtr node, const char* attr); | ||
7 | |||
8 | #endif /* end of include guard: XML_H_E5E95685 */ | ||