summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/components/animatable.h146
-rw-r--r--src/components/mappable.h208
-rw-r--r--src/components/playable.h28
-rw-r--r--src/components/ponderable.h151
-rw-r--r--src/components/realizable.h67
-rw-r--r--src/components/transformable.h79
-rw-r--r--src/game.cpp6
-rw-r--r--src/game.h7
-rw-r--r--src/map.h111
-rw-r--r--src/systems/animating.cpp93
-rw-r--r--src/systems/animating.h2
-rw-r--r--src/systems/mapping.cpp127
-rw-r--r--src/systems/mapping.h2
-rw-r--r--src/systems/orienting.cpp22
-rw-r--r--src/systems/playing.cpp220
-rw-r--r--src/systems/playing.h9
-rw-r--r--src/systems/pondering.cpp354
-rw-r--r--src/systems/pondering.h2
-rw-r--r--src/systems/realizing.cpp321
-rw-r--r--src/systems/realizing.h43
-rw-r--r--src/world.cpp155
-rw-r--r--src/world.h41
23 files changed, 1155 insertions, 1041 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 34246ad..81365c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -53,7 +53,6 @@ add_executable(Aromatherapy
53 src/entity_manager.cpp 53 src/entity_manager.cpp
54 src/game.cpp 54 src/game.cpp
55 src/animation.cpp 55 src/animation.cpp
56 src/world.cpp
57 src/util.cpp 56 src/util.cpp
58 src/collision.cpp 57 src/collision.cpp
59 src/renderer/renderer.cpp 58 src/renderer/renderer.cpp
@@ -67,6 +66,7 @@ add_executable(Aromatherapy
67 src/systems/orienting.cpp 66 src/systems/orienting.cpp
68 src/systems/playing.cpp 67 src/systems/playing.cpp
69 src/systems/scheduling.cpp 68 src/systems/scheduling.cpp
69 src/systems/realizing.cpp
70) 70)
71 71
72set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 11) 72set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 11)
diff --git a/src/components/animatable.h b/src/components/animatable.h index ec72be0..1a678ba 100644 --- a/src/components/animatable.h +++ b/src/components/animatable.h
@@ -8,88 +8,86 @@
8class AnimatableComponent : public Component { 8class AnimatableComponent : public Component {
9public: 9public:
10 10
11 /**
12 * Constructor for initializing the animation set, because it is not default
13 * constructible.
14 */
11 AnimatableComponent( 15 AnimatableComponent(
12 AnimationSet animationSet, 16 AnimationSet animationSet) :
13 std::string animation) : 17 animationSet(std::move(animationSet))
14 animationSet_(std::move(animationSet)),
15 animation_(std::move(animation))
16 { 18 {
17 } 19 }
18 20
19 inline size_t getFrame() const 21 /**
20 { 22 * The animation set that this entity will use -- an object describing the
21 return frame_; 23 * different animations that can be used to render the entity.
22 } 24 *
23 25 * @managed_by RealizingSystem
24 inline void setFrame(size_t v) 26 */
25 { 27 AnimationSet animationSet;
26 frame_ = v; 28
27 } 29 /**
28 30 * The name of the currently active animation.
29 inline size_t getCountdown() const 31 *
30 { 32 * @managed_by AnimatingSystem
31 return countdown_; 33 */
32 } 34 std::string animation;
33 35
34 inline void setCountdown(size_t v) 36 /**
35 { 37 * For prototypes, the name of the original animation.
36 countdown_ = v; 38 *
37 } 39 * @managed_by RealizingSystem
38 40 */
39 inline const AnimationSet& getAnimationSet() const 41 std::string origAnimation;
40 { 42
41 return animationSet_; 43 /**
42 } 44 * Helper method for accessing the currently active animation.
43 45 */
44 inline const Animation& getAnimation() const 46 inline const Animation& getAnimation() const
45 { 47 {
46 return animationSet_.getAnimation(animation_); 48 return animationSet.getAnimation(animation);
47 } 49 }
48 50
49 inline void setAnimation(std::string animation) 51 /**
50 { 52 * The frame of animation that is currently being rendered.
51 animation_ = std::move(animation); 53 *
52 } 54 * @managed_by AnimatingSystem
53 55 */
54 inline bool isFlickering() const 56 size_t frame = 0;
55 { 57
56 return flickering_; 58 /**
57 } 59 * The amount of time (in game frames) before the animation is advanced.
58 60 *
59 inline void setFlickering(bool v) 61 * @managed_by AnimatingSystem
60 { 62 */
61 flickering_ = v; 63 size_t countdown = 0;
62 } 64
63 65 /**
64 inline size_t getFlickerTimer() const 66 * This option allows to give the sprite a "flickering" effect (as in, it is
65 { 67 * not rendered in some frames).
66 return flickerTimer_; 68 */
67 } 69 bool flickering = false;
68 70
69 inline void setFlickerTimer(size_t v) 71 /**
70 { 72 * Used for the flickering effect.
71 flickerTimer_ = v; 73 *
72 } 74 * @managed_by AnimatingSystem
73 75 */
74 inline bool isFrozen() const 76 size_t flickerTimer = 0;
75 { 77
76 return frozen_; 78 /**
77 } 79 * If enabled, this will prevent the sprite's animation from progressing (but
78 80 * will not affect things such as placement on screen and flickering).
79 inline void setFrozen(bool v) 81 */
80 { 82 bool frozen = false;
81 frozen_ = v; 83
82 } 84 /**
83 85 * If this flag is disabled, the entity will be ignored by the animating
84private: 86 * system.
85 87 *
86 AnimationSet animationSet_; 88 * @managed_by RealizingSystem
87 std::string animation_; 89 */
88 size_t frame_ = 0; 90 bool active = false;
89 size_t countdown_ = 0;
90 bool flickering_ = false;
91 size_t flickerTimer_ = 0;
92 bool frozen_ = false;
93}; 91};
94 92
95#endif /* end of include guard: SPRITE_RENDERABLE_H_D3AACBBF */ 93#endif /* end of include guard: SPRITE_RENDERABLE_H_D3AACBBF */
diff --git a/src/components/mappable.h b/src/components/mappable.h index 633cdf4..6f3d38e 100644 --- a/src/components/mappable.h +++ b/src/components/mappable.h
@@ -2,14 +2,47 @@
2#define MAPPABLE_H_0B0316FB 2#define MAPPABLE_H_0B0316FB
3 3
4#include <map> 4#include <map>
5#include <string>
6#include <vector>
7#include <list>
5#include "component.h" 8#include "component.h"
6#include "renderer/texture.h" 9#include "renderer/texture.h"
7#include "collision.h" 10#include "collision.h"
8#include "map.h" 11#include "entity_manager.h"
9 12
10class MappableComponent : public Component { 13class MappableComponent : public Component {
11public: 14public:
12 15
16 using id_type = EntityManager::id_type;
17
18 /**
19 * Helper type that stores information about map adjacency.
20 */
21 class Adjacent {
22 public:
23
24 enum class Type {
25 wall,
26 wrap,
27 warp,
28 reverse
29 };
30
31 Adjacent(
32 Type type = Type::wall,
33 size_t mapId = 0) :
34 type(type),
35 mapId(mapId)
36 {
37 }
38
39 Type type;
40 size_t mapId;
41 };
42
43 /**
44 * Helper type that stores information about collision boundaries.
45 */
13 class Boundary { 46 class Boundary {
14 public: 47 public:
15 48
@@ -20,121 +53,100 @@ public:
20 double lower, 53 double lower,
21 double upper, 54 double upper,
22 Type type) : 55 Type type) :
23 axis_(axis), 56 axis(axis),
24 lower_(lower), 57 lower(lower),
25 upper_(upper), 58 upper(upper),
26 type_(type) 59 type(type)
27 {
28 }
29
30 inline double getAxis() const
31 {
32 return axis_;
33 }
34
35 inline double getLower() const
36 {
37 return lower_;
38 }
39
40 inline double getUpper() const
41 {
42 return upper_;
43 }
44
45 inline Type getType() const
46 { 60 {
47 return type_;
48 } 61 }
49 62
50 private: 63 double axis;
51 64 double lower;
52 double axis_; 65 double upper;
53 double lower_; 66 Type type;
54 double upper_;
55 Type type_;
56 }; 67 };
57 68
58 MappableComponent( 69 /**
59 Texture tileset, 70 * Helper types for efficient storage and lookup of collision boundaries.
60 Texture font) : 71 */
61 tileset_(std::move(tileset)),
62 font_(std::move(font))
63 {
64 }
65
66 using asc_boundaries_type = 72 using asc_boundaries_type =
67 std::multimap< 73 std::multimap<
68 double, 74 double,
69 Boundary, 75 const Boundary,
70 std::less<double>>; 76 std::less<double>>;
71 77
72 using desc_boundaries_type = 78 using desc_boundaries_type =
73 std::multimap< 79 std::multimap<
74 double, 80 double,
75 Boundary, 81 const Boundary,
76 std::greater<double>>; 82 std::greater<double>>;
77 83
78 inline size_t getMapId() const 84 /**
79 { 85 * Constructor for initializing the tileset and font attributes, as they are
80 return mapId_; 86 * not default constructible.
81 } 87 */
82 88 MappableComponent(
83 inline void setMapId(size_t v) 89 Texture tileset,
84 { 90 Texture font) :
85 mapId_ = v; 91 tileset(std::move(tileset)),
86 } 92 font(std::move(font))
87
88 inline desc_boundaries_type& getLeftBoundaries()
89 {
90 return leftBoundaries_;
91 }
92
93 inline asc_boundaries_type& getRightBoundaries()
94 {
95 return rightBoundaries_;
96 }
97
98 inline desc_boundaries_type& getUpBoundaries()
99 {
100 return upBoundaries_;
101 }
102
103 inline asc_boundaries_type& getDownBoundaries()
104 {
105 return downBoundaries_;
106 }
107
108 inline const Texture& getTileset() const
109 {
110 return tileset_;
111 }
112
113 inline void setTileset(Texture v)
114 {
115 tileset_ = std::move(v);
116 }
117
118 inline const Texture& getFont() const
119 {
120 return font_;
121 }
122
123 inline void setFont(Texture v)
124 { 93 {
125 font_ = std::move(v);
126 } 94 }
127 95
128private: 96 /**
129 97 * The ID of the map in the world definition that this entity represents.
130 size_t mapId_ = -1; 98 *
131 99 * @managed_by RealizingSystem
132 desc_boundaries_type leftBoundaries_; 100 */
133 asc_boundaries_type rightBoundaries_; 101 size_t mapId;
134 desc_boundaries_type upBoundaries_; 102
135 asc_boundaries_type downBoundaries_; 103 /**
136 Texture tileset_; 104 * The title of the map, which is displayed at the bottom of the screen.
137 Texture font_; 105 */
106 std::string title;
107
108 /**
109 * The map data.
110 *
111 * @managed_by RealizingSystem
112 */
113 std::vector<int> tiles;
114
115 /**
116 * These objects describe the behavior of the four edges of the map.
117 *
118 * @managed_by RealizingSystem
119 */
120 Adjacent leftAdjacent;
121 Adjacent rightAdjacent;
122 Adjacent upAdjacent;
123 Adjacent downAdjacent;
124
125 /**
126 * Collision boundaries, for detecting when a ponderable entity is colliding
127 * with the environment.
128 *
129 * @managed_by MappingSystem
130 */
131 desc_boundaries_type leftBoundaries;
132 asc_boundaries_type rightBoundaries;
133 desc_boundaries_type upBoundaries;
134 asc_boundaries_type downBoundaries;
135
136 /**
137 * The list of entities representing the objects owned by the map.
138 *
139 * @managed_by RealizingSystem
140 */
141 std::list<id_type> objects;
142
143 /**
144 * The tilesets for the map and the map name.
145 *
146 * TODO: These probably do not belong here.
147 */
148 Texture tileset;
149 Texture font;
138}; 150};
139 151
140#endif /* end of include guard: MAPPABLE_H_0B0316FB */ 152#endif /* end of include guard: MAPPABLE_H_0B0316FB */
diff --git a/src/components/playable.h b/src/components/playable.h index 86a7ee7..94d4326 100644 --- a/src/components/playable.h +++ b/src/components/playable.h
@@ -2,22 +2,30 @@
2#define PLAYABLE_H_DDC566C3 2#define PLAYABLE_H_DDC566C3
3 3
4#include "component.h" 4#include "component.h"
5#include <functional> 5#include "entity_manager.h"
6 6
7class PlayableComponent : public Component { 7class PlayableComponent : public Component {
8public: 8public:
9 9
10 using MapChangeCallback = std::function<void()>; 10 using id_type = EntityManager::id_type;
11 11
12 bool changingMap = false; 12 /**
13 int newMapId = -1; 13 * The entity ID of the map that the player is on.
14 double newMapX = 0; 14 *
15 double newMapY = 0; 15 * @managed_by PlayingSystem
16 MapChangeCallback newMapCallback; 16 */
17 id_type mapId;
17 18
18 int checkpointMapId = -1; 19 /**
19 double checkpointX = 0; 20 * The map ID and coordinates of the location that the player will spawn after
20 double checkpointY = 0; 21 * dying. Note that the map ID here is a world description map ID, not an
22 * entity ID.
23 *
24 * @managed_by PlayingSystem
25 */
26 size_t checkpointMapId;
27 double checkpointX;
28 double checkpointY;
21 29
22}; 30};
23 31
diff --git a/src/components/ponderable.h b/src/components/ponderable.h index 78af25f..fd7e775 100644 --- a/src/components/ponderable.h +++ b/src/components/ponderable.h
@@ -6,100 +6,73 @@
6class PonderableComponent : public Component { 6class PonderableComponent : public Component {
7public: 7public:
8 8
9 /**
10 * List of different types of physical bodies.
11 *
12 * vacuumed - Default.
13 * freefalling - The body will be treated as if there were a downward force
14 * of gravity being exerted onto it. The body will also exhibit
15 * terminal velocity (that is, its downward velocity will be
16 * capped at a constant value).
17 */
9 enum class Type { 18 enum class Type {
10 vacuumed, 19 vacuumed,
11 freefalling 20 freefalling
12 }; 21 };
13 22
14 PonderableComponent(Type type) : type_(type) 23 /**
15 { 24 * Constructor for initializing the body type, which is a constant.
16 } 25 */
17 26 PonderableComponent(Type type) : type(type)
18 inline Type getType() const 27 {
19 { 28 }
20 return type_; 29
21 } 30 /**
22 31 * The velocity of the body.
23 inline double getVelocityX() const 32 */
24 { 33 double velX = 0.0;
25 return velX_; 34 double velY = 0.0;
26 } 35
27 36 /**
28 inline void setVelocityX(double v) 37 * The acceleration of the body.
29 { 38 */
30 velX_ = v; 39 double accelX = 0.0;
31 } 40 double accelY = 0.0;
32 41
33 inline double getVelocityY() const 42 /**
34 { 43 * The type of physical body that the entity is meant to assume. The body will
35 return velY_; 44 * be acted upon differently based on this. See the enumeration above for more
36 } 45 * details.
37 46 *
38 inline void setVelocityY(double v) 47 * @managed_by PonderingSystem
39 { 48 */
40 velY_ = v; 49 const Type type;
41 } 50
42 51 /**
43 inline double getAccelX() const 52 * Whether or not a freefalling body is in contact with the ground.
44 { 53 *
45 return accelX_; 54 * @managed_by PonderingSystem
46 } 55 */
47 56 bool grounded = false;
48 inline void setAccelX(double v) 57
49 { 58 /**
50 accelX_ = v; 59 * If enabled, this will prevent the body from moving.
51 } 60 */
52 61 bool frozen = false;
53 inline double getAccelY() const 62
54 { 63 /**
55 return accelY_; 64 * If disabled, collision detection for this body will not be performed and
56 } 65 * other bodies will ignore it.
57 66 */
58 inline void setAccelY(double v) 67 bool collidable = true;
59 { 68
60 accelY_ = v; 69 /**
61 } 70 * If this flag is disabled, the entity will be ignored by the pondering
62 71 * system.
63 inline bool isGrounded() const 72 *
64 { 73 * @managed_by RealizingSystem
65 return grounded_; 74 */
66 } 75 bool active = false;
67
68 inline void setGrounded(bool v)
69 {
70 grounded_ = v;
71 }
72
73 inline bool isFrozen() const
74 {
75 return frozen_;
76 }
77
78 inline void setFrozen(bool v)
79 {
80 frozen_ = v;
81 }
82
83 inline bool isCollidable() const
84 {
85 return collidable_;
86 }
87
88 inline void setCollidable(bool v)
89 {
90 collidable_ = v;
91 }
92
93private:
94
95 double velX_ = 0.0;
96 double velY_ = 0.0;
97 double accelX_ = 0.0;
98 double accelY_ = 0.0;
99 Type type_ = Type::vacuumed;
100 bool grounded_ = false;
101 bool frozen_ = false;
102 bool collidable_ = true;
103}; 76};
104 77
105#endif /* end of include guard: TANGIBLE_H_746DB3EE */ 78#endif /* end of include guard: TANGIBLE_H_746DB3EE */
diff --git a/src/components/realizable.h b/src/components/realizable.h new file mode 100644 index 0000000..f6a7eb4 --- /dev/null +++ b/src/components/realizable.h
@@ -0,0 +1,67 @@
1#ifndef REALIZABLE_H_36D8D71E
2#define REALIZABLE_H_36D8D71E
3
4#include "component.h"
5#include <set>
6#include <map>
7#include "entity_manager.h"
8
9class RealizableComponent : public Component {
10public:
11
12 using id_type = EntityManager::id_type;
13
14 /**
15 * Path to the XML file containing the world definition.
16 *
17 * @managed_by RealizingSystem
18 */
19 std::string worldFile;
20
21 /**
22 * Starting map and player location for a new game.
23 *
24 * @managed_by RealizingSystem
25 */
26 int startingMapId;
27 int startingX;
28 int startingY;
29
30 /**
31 * The set of map entities loaded by this entity. It is only intended for
32 * there to be one realizable entity, so this should contain all loaded maps.
33 * The realizable entity has ownership of the loaded maps.
34 *
35 * @managed_by RealizingSystem
36 */
37 std::set<id_type> maps;
38
39 /**
40 * A lookup table that translates a map ID to the entity representing that
41 * loaded map.
42 *
43 * @managed_by RealizingSystem
44 */
45 std::map<size_t, id_type> entityByMapId;
46
47 /**
48 * The entity ID of the currently active map.
49 *
50 * @managed_by RealizingSystem
51 */
52 id_type activeMap;
53
54 /**
55 * Whether or not a map has been activated yet.
56 *
57 * @managed_by RealizingSystem
58 */
59 bool hasActiveMap = false;
60
61 /**
62 * The entity ID of the currently active player.
63 */
64 id_type activePlayer;
65};
66
67#endif /* end of include guard: REALIZABLE_H_36D8D71E */
diff --git a/src/components/transformable.h b/src/components/transformable.h index 6ed2637..3296e49 100644 --- a/src/components/transformable.h +++ b/src/components/transformable.h
@@ -6,64 +6,27 @@
6class TransformableComponent : public Component { 6class TransformableComponent : public Component {
7public: 7public:
8 8
9 TransformableComponent( 9 /**
10 double x, 10 * The coordinates of the entity.
11 double y, 11 */
12 int w, 12 double x;
13 int h) : 13 double y;
14 x_(x), 14
15 y_(y), 15 /**
16 w_(w), 16 * The size of the entity.
17 h_(h) 17 */
18 { 18 int w;
19 } 19 int h;
20 20
21 inline double getX() const 21 /**
22 { 22 * For prototypes, the original coordinates and size of the entity.
23 return x_; 23 *
24 } 24 * @managed_by RealizingSystem
25 25 */
26 inline void setX(double v) 26 double origX;
27 { 27 double origY;
28 x_ = v; 28 int origW;
29 } 29 int origH;
30
31 inline double getY() const
32 {
33 return y_;
34 }
35
36 inline void setY(double v)
37 {
38 y_ = v;
39 }
40
41 inline int getW() const
42 {
43 return w_;
44 }
45
46 inline void setW(int v)
47 {
48 w_ = v;
49 }
50
51 inline int getH() const
52 {
53 return h_;
54 }
55
56 inline void setH(int v)
57 {
58 h_ = v;
59 }
60
61private:
62
63 double x_;
64 double y_;
65 int w_;
66 int h_;
67}; 30};
68 31
69#endif /* end of include guard: LOCATABLE_H_39E526CA */ 32#endif /* end of include guard: LOCATABLE_H_39E526CA */
diff --git a/src/game.cpp b/src/game.cpp index 3da23a3..b7dd200 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -11,6 +11,7 @@
11#include "systems/orienting.h" 11#include "systems/orienting.h"
12#include "systems/playing.h" 12#include "systems/playing.h"
13#include "systems/scheduling.h" 13#include "systems/scheduling.h"
14#include "systems/realizing.h"
14#include "animation.h" 15#include "animation.h"
15#include "consts.h" 16#include "consts.h"
16 17
@@ -28,8 +29,9 @@ void key_callback(GLFWwindow* window, int key, int, int action, int)
28 game.systemManager_.input(key, action); 29 game.systemManager_.input(key, action);
29} 30}
30 31
31Game::Game() : world_("res/maps.xml") 32Game::Game()
32{ 33{
34 systemManager_.emplaceSystem<RealizingSystem>(*this);
33 systemManager_.emplaceSystem<PlayingSystem>(*this); 35 systemManager_.emplaceSystem<PlayingSystem>(*this);
34 systemManager_.emplaceSystem<SchedulingSystem>(*this); 36 systemManager_.emplaceSystem<SchedulingSystem>(*this);
35 systemManager_.emplaceSystem<ControllingSystem>(*this); 37 systemManager_.emplaceSystem<ControllingSystem>(*this);
@@ -38,8 +40,8 @@ Game::Game() : world_("res/maps.xml")
38 systemManager_.emplaceSystem<MappingSystem>(*this); 40 systemManager_.emplaceSystem<MappingSystem>(*this);
39 systemManager_.emplaceSystem<AnimatingSystem>(*this); 41 systemManager_.emplaceSystem<AnimatingSystem>(*this);
40 42
43 systemManager_.getSystem<RealizingSystem>().initSingleton("res/maps.xml");
41 systemManager_.getSystem<PlayingSystem>().initPlayer(); 44 systemManager_.getSystem<PlayingSystem>().initPlayer();
42 systemManager_.getSystem<MappingSystem>().loadMap(world_.getStartingMapId());
43 45
44 glfwSwapInterval(1); 46 glfwSwapInterval(1);
45 glfwSetWindowUserPointer(renderer_.getWindow().getHandle(), this); 47 glfwSetWindowUserPointer(renderer_.getWindow().getHandle(), this);
diff --git a/src/game.h b/src/game.h index 43e08da..92a67d9 100644 --- a/src/game.h +++ b/src/game.h
@@ -3,7 +3,6 @@
3 3
4#include "entity_manager.h" 4#include "entity_manager.h"
5#include "system_manager.h" 5#include "system_manager.h"
6#include "world.h"
7#include "renderer/renderer.h" 6#include "renderer/renderer.h"
8 7
9class Game { 8class Game {
@@ -28,11 +27,6 @@ public:
28 return systemManager_; 27 return systemManager_;
29 } 28 }
30 29
31 inline const World& getWorld()
32 {
33 return world_;
34 }
35
36 friend void key_callback( 30 friend void key_callback(
37 GLFWwindow* window, 31 GLFWwindow* window,
38 int key, 32 int key,
@@ -45,7 +39,6 @@ private:
45 Renderer renderer_; 39 Renderer renderer_;
46 EntityManager entityManager_; 40 EntityManager entityManager_;
47 SystemManager systemManager_; 41 SystemManager systemManager_;
48 World world_;
49 bool shouldQuit_ = false; 42 bool shouldQuit_ = false;
50}; 43};
51 44
diff --git a/src/map.h b/src/map.h deleted file mode 100644 index 6fe1e62..0000000 --- a/src/map.h +++ /dev/null
@@ -1,111 +0,0 @@
1#ifndef MAP_H_74055FC0
2#define MAP_H_74055FC0
3
4#include <vector>
5#include <string>
6#include <list>
7#include <stdexcept>
8#include <map>
9
10class Map {
11public:
12
13 class Adjacent {
14 public:
15
16 enum class Type {
17 wall,
18 wrap,
19 warp,
20 reverse
21 };
22
23 Adjacent(
24 Type type = Type::wall,
25 int mapId = -1) :
26 type_(type),
27 mapId_(mapId)
28 {
29 }
30
31 inline Type getType() const
32 {
33 return type_;
34 }
35
36 inline int getMapId() const
37 {
38 return mapId_;
39 }
40
41 private:
42
43 Type type_;
44 int mapId_;
45 };
46
47 Map(
48 int id,
49 std::vector<int> tiles,
50 std::string title,
51 Adjacent leftAdjacent,
52 Adjacent rightAdjacent,
53 Adjacent upAdjacent,
54 Adjacent downAdjacent) :
55 id_(id),
56 tiles_(std::move(tiles)),
57 title_(std::move(title)),
58 leftAdjacent_(std::move(leftAdjacent)),
59 rightAdjacent_(std::move(rightAdjacent)),
60 upAdjacent_(std::move(upAdjacent)),
61 downAdjacent_(std::move(downAdjacent))
62 {
63 }
64
65 inline size_t getId() const
66 {
67 return id_;
68 }
69
70 inline const std::vector<int>& getTiles() const
71 {
72 return tiles_;
73 }
74
75 inline const std::string& getTitle() const
76 {
77 return title_;
78 }
79
80 inline const Adjacent& getLeftAdjacent() const
81 {
82 return leftAdjacent_;
83 }
84
85 inline const Adjacent& getRightAdjacent() const
86 {
87 return rightAdjacent_;
88 }
89
90 inline const Adjacent& getUpAdjacent() const
91 {
92 return upAdjacent_;
93 }
94
95 inline const Adjacent& getDownAdjacent() const
96 {
97 return downAdjacent_;
98 }
99
100private:
101
102 int id_;
103 std::vector<int> tiles_;
104 std::string title_;
105 Adjacent leftAdjacent_;
106 Adjacent rightAdjacent_;
107 Adjacent upAdjacent_;
108 Adjacent downAdjacent_;
109};
110
111#endif /* end of include guard: MAP_H_74055FC0 */
diff --git a/src/systems/animating.cpp b/src/systems/animating.cpp index 634af67..8543ba2 100644 --- a/src/systems/animating.cpp +++ b/src/systems/animating.cpp
@@ -13,26 +13,29 @@ void AnimatingSystem::tick(double)
13 auto& sprite = game_.getEntityManager(). 13 auto& sprite = game_.getEntityManager().
14 getComponent<AnimatableComponent>(entity); 14 getComponent<AnimatableComponent>(entity);
15 15
16 if (!sprite.isFrozen()) 16 if (sprite.active)
17 { 17 {
18 sprite.setCountdown(sprite.getCountdown() + 1); 18 if (!sprite.frozen)
19 } 19 {
20 20 sprite.countdown++;
21 const Animation& anim = sprite.getAnimation(); 21 }
22 if (sprite.getCountdown() >= anim.getDelay())
23 {
24 sprite.setFrame(sprite.getFrame() + 1);
25 sprite.setCountdown(0);
26 22
27 if (sprite.getFrame() >= anim.getFirstFrame() + anim.getNumFrames()) 23 const Animation& anim = sprite.getAnimation();
24 if (sprite.countdown >= anim.getDelay())
28 { 25 {
29 sprite.setFrame(anim.getFirstFrame()); 26 sprite.frame++;
27 sprite.countdown = 0;
28
29 if (sprite.frame >= anim.getFirstFrame() + anim.getNumFrames())
30 {
31 sprite.frame = anim.getFirstFrame();
32 }
30 } 33 }
31 }
32 34
33 if (sprite.isFlickering()) 35 if (sprite.flickering)
34 { 36 {
35 sprite.setFlickerTimer((sprite.getFlickerTimer() + 1) % 6); 37 sprite.flickerTimer = (sprite.flickerTimer + 1) % 6;
38 }
36 } 39 }
37 } 40 }
38} 41}
@@ -49,36 +52,52 @@ void AnimatingSystem::render(Texture& texture)
49 auto& sprite = game_.getEntityManager(). 52 auto& sprite = game_.getEntityManager().
50 getComponent<AnimatableComponent>(entity); 53 getComponent<AnimatableComponent>(entity);
51 54
52 auto& transform = game_.getEntityManager(). 55 if (sprite.active)
53 getComponent<TransformableComponent>(entity);
54
55 double alpha = 1.0;
56 if (sprite.isFlickering() && (sprite.getFlickerTimer() < 3))
57 { 56 {
58 alpha = 0.0; 57 auto& transform = game_.getEntityManager().
59 } 58 getComponent<TransformableComponent>(entity);
60 59
61 Rectangle dstrect { 60 double alpha = 1.0;
62 static_cast<int>(transform.getX()), 61 if (sprite.flickering && (sprite.flickerTimer < 3))
63 static_cast<int>(transform.getY()), 62 {
64 transform.getW(), 63 alpha = 0.0;
65 transform.getH()}; 64 }
66 65
67 const AnimationSet& aset = sprite.getAnimationSet(); 66 Rectangle dstrect {
68 game_.getRenderer().blit( 67 static_cast<int>(transform.x),
69 aset.getTexture(), 68 static_cast<int>(transform.y),
70 texture, 69 transform.w,
71 aset.getFrameRect(sprite.getFrame()), 70 transform.h};
72 dstrect, 71
73 alpha); 72 const AnimationSet& aset = sprite.animationSet;
73 game_.getRenderer().blit(
74 aset.getTexture(),
75 texture,
76 aset.getFrameRect(sprite.frame),
77 dstrect,
78 alpha);
79 }
74 } 80 }
75} 81}
76 82
83void AnimatingSystem::initPrototype(id_type entity)
84{
85 auto& sprite = game_.getEntityManager().
86 getComponent<AnimatableComponent>(entity);
87
88 startAnimation(entity, sprite.origAnimation);
89
90 sprite.countdown = 0;
91 sprite.flickering = false;
92 sprite.flickerTimer = 0;
93 sprite.frozen = false;
94}
95
77void AnimatingSystem::startAnimation(id_type entity, std::string animation) 96void AnimatingSystem::startAnimation(id_type entity, std::string animation)
78{ 97{
79 auto& sprite = game_.getEntityManager(). 98 auto& sprite = game_.getEntityManager().
80 getComponent<AnimatableComponent>(entity); 99 getComponent<AnimatableComponent>(entity);
81 100
82 sprite.setAnimation(animation); 101 sprite.animation = std::move(animation);
83 sprite.setFrame(sprite.getAnimation().getFirstFrame()); 102 sprite.frame = sprite.getAnimation().getFirstFrame();
84} 103}
diff --git a/src/systems/animating.h b/src/systems/animating.h index 548bff1..acc6191 100644 --- a/src/systems/animating.h +++ b/src/systems/animating.h
@@ -16,6 +16,8 @@ public:
16 16
17 void render(Texture& texture); 17 void render(Texture& texture);
18 18
19 void initPrototype(id_type entity);
20
19 void startAnimation(id_type entity, std::string animation); 21 void startAnimation(id_type entity, std::string animation);
20 22
21}; 23};
diff --git a/src/systems/mapping.cpp b/src/systems/mapping.cpp index a3a17ec..af67aed 100644 --- a/src/systems/mapping.cpp +++ b/src/systems/mapping.cpp
@@ -1,5 +1,7 @@
1#include "mapping.h" 1#include "mapping.h"
2#include "components/mappable.h" 2#include "components/mappable.h"
3#include "components/realizable.h"
4#include "systems/realizing.h"
3#include "game.h" 5#include "game.h"
4#include "consts.h" 6#include "consts.h"
5 7
@@ -18,104 +20,95 @@ inline void addBoundary(
18 20
19void MappingSystem::render(Texture& texture) 21void MappingSystem::render(Texture& texture)
20{ 22{
21 auto entities = game_.getEntityManager().getEntitiesWithComponents< 23 auto& realizable = game_.getEntityManager().
22 MappableComponent>(); 24 getComponent<RealizableComponent>(
25 game_.getSystemManager().getSystem<RealizingSystem>().getSingleton());
23 26
24 for (id_type entity : entities) 27 id_type map = realizable.activeMap;
25 {
26 auto& mappable = game_.getEntityManager().
27 getComponent<MappableComponent>(entity);
28 28
29 const Map& map = game_.getWorld().getMap(mappable.getMapId()); 29 auto& mappable = game_.getEntityManager().
30 getComponent<MappableComponent>(map);
30 31
31 for (int i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++) 32 for (int i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++)
32 { 33 {
33 int x = i % MAP_WIDTH; 34 int x = i % MAP_WIDTH;
34 int y = i / MAP_WIDTH; 35 int y = i / MAP_WIDTH;
35 int tile = map.getTiles()[i]; 36 int tile = mappable.tiles[i];
36
37 if (tile > 0)
38 {
39 Rectangle dst {
40 x * TILE_WIDTH,
41 y * TILE_HEIGHT,
42 TILE_WIDTH,
43 TILE_HEIGHT};
44
45 Rectangle src {
46 (tile % TILESET_COLS) * TILE_WIDTH,
47 (tile / TILESET_COLS) * TILE_HEIGHT,
48 TILE_WIDTH,
49 TILE_HEIGHT};
50
51 game_.getRenderer().blit(
52 mappable.getTileset(),
53 texture,
54 std::move(src),
55 std::move(dst));
56 }
57 }
58 37
59 int startX = ((GAME_WIDTH / TILE_WIDTH) / 2) - (map.getTitle().size() / 2); 38 if (tile > 0)
60 for (size_t i = 0; i < map.getTitle().size(); i++)
61 { 39 {
62 Rectangle src { 40 Rectangle dst {
63 (map.getTitle()[i] % FONT_COLS) * TILE_WIDTH, 41 x * TILE_WIDTH,
64 (map.getTitle()[i] / FONT_COLS) * TILE_HEIGHT, 42 y * TILE_HEIGHT,
65 TILE_WIDTH, 43 TILE_WIDTH,
66 TILE_HEIGHT}; 44 TILE_HEIGHT};
67 45
68 Rectangle dst { 46 Rectangle src {
69 (startX + static_cast<int>(i)) * TILE_WIDTH, 47 (tile % TILESET_COLS) * TILE_WIDTH,
70 24 * TILE_HEIGHT, 48 (tile / TILESET_COLS) * TILE_HEIGHT,
71 TILE_WIDTH, 49 TILE_WIDTH,
72 TILE_HEIGHT}; 50 TILE_HEIGHT};
73 51
74 game_.getRenderer().blit( 52 game_.getRenderer().blit(
75 mappable.getFont(), 53 mappable.tileset,
76 texture, 54 texture,
77 std::move(src), 55 std::move(src),
78 std::move(dst)); 56 std::move(dst));
79 } 57 }
80 } 58 }
59
60 int startX = ((GAME_WIDTH / TILE_WIDTH) / 2) - (mappable.title.size() / 2);
61
62 for (size_t i = 0; i < mappable.title.size(); i++)
63 {
64 Rectangle src {
65 (mappable.title[i] % FONT_COLS) * TILE_WIDTH,
66 (mappable.title[i] / FONT_COLS) * TILE_HEIGHT,
67 TILE_WIDTH,
68 TILE_HEIGHT};
69
70 Rectangle dst {
71 (startX + static_cast<int>(i)) * TILE_WIDTH,
72 24 * TILE_HEIGHT,
73 TILE_WIDTH,
74 TILE_HEIGHT};
75
76 game_.getRenderer().blit(
77 mappable.font,
78 texture,
79 std::move(src),
80 std::move(dst));
81 }
81} 82}
82 83
83void MappingSystem::loadMap(size_t mapId) 84void MappingSystem::generateBoundaries(id_type mapEntity)
84{ 85{
85 id_type mapEntity = game_.getEntityManager().emplaceEntity();
86
87 auto& mappable = game_.getEntityManager(). 86 auto& mappable = game_.getEntityManager().
88 emplaceComponent<MappableComponent>(mapEntity, 87 getComponent<MappableComponent>(mapEntity);
89 Texture("res/tiles.png"),
90 Texture("res/font.bmp"));
91
92 mappable.setMapId(mapId);
93
94 const Map& map = game_.getWorld().getMap(mappable.getMapId());
95 88
96 addBoundary( 89 addBoundary(
97 mappable.getLeftBoundaries(), 90 mappable.leftBoundaries,
98 -WALL_GAP, 91 -WALL_GAP,
99 0, 92 0,
100 MAP_HEIGHT * TILE_HEIGHT, 93 MAP_HEIGHT * TILE_HEIGHT,
101 MappableComponent::Boundary::Type::adjacency); 94 MappableComponent::Boundary::Type::adjacency);
102 95
103 addBoundary( 96 addBoundary(
104 mappable.getRightBoundaries(), 97 mappable.rightBoundaries,
105 GAME_WIDTH + WALL_GAP, 98 GAME_WIDTH + WALL_GAP,
106 0, 99 0,
107 MAP_HEIGHT * TILE_HEIGHT, 100 MAP_HEIGHT * TILE_HEIGHT,
108 MappableComponent::Boundary::Type::adjacency); 101 MappableComponent::Boundary::Type::adjacency);
109 102
110 addBoundary( 103 addBoundary(
111 mappable.getUpBoundaries(), 104 mappable.upBoundaries,
112 -WALL_GAP, 105 -WALL_GAP,
113 0, 106 0,
114 GAME_WIDTH, 107 GAME_WIDTH,
115 MappableComponent::Boundary::Type::adjacency); 108 MappableComponent::Boundary::Type::adjacency);
116 109
117 addBoundary( 110 addBoundary(
118 mappable.getDownBoundaries(), 111 mappable.downBoundaries,
119 MAP_HEIGHT * TILE_HEIGHT + WALL_GAP, 112 MAP_HEIGHT * TILE_HEIGHT + WALL_GAP,
120 0, 113 0,
121 GAME_WIDTH, 114 GAME_WIDTH,
@@ -125,12 +118,12 @@ void MappingSystem::loadMap(size_t mapId)
125 { 118 {
126 size_t x = i % MAP_WIDTH; 119 size_t x = i % MAP_WIDTH;
127 size_t y = i / MAP_WIDTH; 120 size_t y = i / MAP_WIDTH;
128 int tile = map.getTiles()[i]; 121 int tile = mappable.tiles[i];
129 122
130 if ((tile >= 5) && (tile <= 7)) 123 if ((tile >= 5) && (tile <= 7))
131 { 124 {
132 addBoundary( 125 addBoundary(
133 mappable.getDownBoundaries(), 126 mappable.downBoundaries,
134 y * TILE_HEIGHT, 127 y * TILE_HEIGHT,
135 x * TILE_WIDTH, 128 x * TILE_WIDTH,
136 (x + 1) * TILE_WIDTH, 129 (x + 1) * TILE_WIDTH,
@@ -138,28 +131,28 @@ void MappingSystem::loadMap(size_t mapId)
138 } else if ((tile > 0) && (tile < 28)) 131 } else if ((tile > 0) && (tile < 28))
139 { 132 {
140 addBoundary( 133 addBoundary(
141 mappable.getRightBoundaries(), 134 mappable.rightBoundaries,
142 x * TILE_WIDTH, 135 x * TILE_WIDTH,
143 y * TILE_HEIGHT, 136 y * TILE_HEIGHT,
144 (y+1) * TILE_HEIGHT, 137 (y+1) * TILE_HEIGHT,
145 MappableComponent::Boundary::Type::wall); 138 MappableComponent::Boundary::Type::wall);
146 139
147 addBoundary( 140 addBoundary(
148 mappable.getLeftBoundaries(), 141 mappable.leftBoundaries,
149 (x+1) * TILE_WIDTH, 142 (x+1) * TILE_WIDTH,
150 y * TILE_HEIGHT, 143 y * TILE_HEIGHT,
151 (y+1) * TILE_HEIGHT, 144 (y+1) * TILE_HEIGHT,
152 MappableComponent::Boundary::Type::wall); 145 MappableComponent::Boundary::Type::wall);
153 146
154 addBoundary( 147 addBoundary(
155 mappable.getDownBoundaries(), 148 mappable.downBoundaries,
156 y * TILE_HEIGHT, 149 y * TILE_HEIGHT,
157 x * TILE_WIDTH, 150 x * TILE_WIDTH,
158 (x+1) * TILE_WIDTH, 151 (x+1) * TILE_WIDTH,
159 MappableComponent::Boundary::Type::wall); 152 MappableComponent::Boundary::Type::wall);
160 153
161 addBoundary( 154 addBoundary(
162 mappable.getUpBoundaries(), 155 mappable.upBoundaries,
163 (y+1) * TILE_HEIGHT, 156 (y+1) * TILE_HEIGHT,
164 x * TILE_WIDTH, 157 x * TILE_WIDTH,
165 (x+1) * TILE_WIDTH, 158 (x+1) * TILE_WIDTH,
@@ -167,28 +160,28 @@ void MappingSystem::loadMap(size_t mapId)
167 } else if (tile == 42) 160 } else if (tile == 42)
168 { 161 {
169 addBoundary( 162 addBoundary(
170 mappable.getRightBoundaries(), 163 mappable.rightBoundaries,
171 x * TILE_WIDTH, 164 x * TILE_WIDTH,
172 y * TILE_HEIGHT, 165 y * TILE_HEIGHT,
173 (y+1) * TILE_HEIGHT, 166 (y+1) * TILE_HEIGHT,
174 MappableComponent::Boundary::Type::danger); 167 MappableComponent::Boundary::Type::danger);
175 168
176 addBoundary( 169 addBoundary(
177 mappable.getLeftBoundaries(), 170 mappable.leftBoundaries,
178 (x+1) * TILE_WIDTH, 171 (x+1) * TILE_WIDTH,
179 y * TILE_HEIGHT, 172 y * TILE_HEIGHT,
180 (y+1) * TILE_HEIGHT, 173 (y+1) * TILE_HEIGHT,
181 MappableComponent::Boundary::Type::danger); 174 MappableComponent::Boundary::Type::danger);
182 175
183 addBoundary( 176 addBoundary(
184 mappable.getDownBoundaries(), 177 mappable.downBoundaries,
185 y * TILE_HEIGHT, 178 y * TILE_HEIGHT,
186 x * TILE_WIDTH, 179 x * TILE_WIDTH,
187 (x+1) * TILE_WIDTH, 180 (x+1) * TILE_WIDTH,
188 MappableComponent::Boundary::Type::danger); 181 MappableComponent::Boundary::Type::danger);
189 182
190 addBoundary( 183 addBoundary(
191 mappable.getUpBoundaries(), 184 mappable.upBoundaries,
192 (y+1) * TILE_HEIGHT, 185 (y+1) * TILE_HEIGHT,
193 x * TILE_WIDTH, 186 x * TILE_WIDTH,
194 (x+1) * TILE_WIDTH, 187 (x+1) * TILE_WIDTH,
diff --git a/src/systems/mapping.h b/src/systems/mapping.h index 53d054b..3c47419 100644 --- a/src/systems/mapping.h +++ b/src/systems/mapping.h
@@ -12,7 +12,7 @@ public:
12 12
13 void render(Texture& texture); 13 void render(Texture& texture);
14 14
15 void loadMap(size_t mapId); 15 void generateBoundaries(id_type mapEntity);
16 16
17}; 17};
18 18
diff --git a/src/systems/orienting.cpp b/src/systems/orienting.cpp index 2df8f87..206ebf6 100644 --- a/src/systems/orienting.cpp +++ b/src/systems/orienting.cpp
@@ -24,27 +24,27 @@ void OrientingSystem::tick(double)
24 { 24 {
25 case OrientableComponent::WalkState::still: 25 case OrientableComponent::WalkState::still:
26 { 26 {
27 ponderable.setVelocityX(0); 27 ponderable.velX = 0.0;
28 28
29 break; 29 break;
30 } 30 }
31 31
32 case OrientableComponent::WalkState::left: 32 case OrientableComponent::WalkState::left:
33 { 33 {
34 ponderable.setVelocityX(-WALK_SPEED); 34 ponderable.velX = -WALK_SPEED;
35 35
36 break; 36 break;
37 } 37 }
38 38
39 case OrientableComponent::WalkState::right: 39 case OrientableComponent::WalkState::right:
40 { 40 {
41 ponderable.setVelocityX(WALK_SPEED); 41 ponderable.velX = WALK_SPEED;
42 42
43 break; 43 break;
44 } 44 }
45 } 45 }
46 46
47 if (orientable.isJumping() && (ponderable.getVelocityY() > 0)) 47 if (orientable.isJumping() && (ponderable.velY > 0))
48 { 48 {
49 orientable.setJumping(false); 49 orientable.setJumping(false);
50 } 50 }
@@ -63,7 +63,7 @@ void OrientingSystem::moveLeft(id_type entity)
63 orientable.setWalkState(OrientableComponent::WalkState::left); 63 orientable.setWalkState(OrientableComponent::WalkState::left);
64 64
65 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 65 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
66 if (ponderable.isGrounded()) 66 if (ponderable.grounded)
67 { 67 {
68 animating.startAnimation(entity, "walkingLeft"); 68 animating.startAnimation(entity, "walkingLeft");
69 } else { 69 } else {
@@ -83,7 +83,7 @@ void OrientingSystem::moveRight(id_type entity)
83 orientable.setWalkState(OrientableComponent::WalkState::right); 83 orientable.setWalkState(OrientableComponent::WalkState::right);
84 84
85 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 85 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
86 if (ponderable.isGrounded()) 86 if (ponderable.grounded)
87 { 87 {
88 animating.startAnimation(entity, "walkingRight"); 88 animating.startAnimation(entity, "walkingRight");
89 } else { 89 } else {
@@ -113,7 +113,7 @@ void OrientingSystem::jump(id_type entity)
113 auto& ponderable = game_.getEntityManager(). 113 auto& ponderable = game_.getEntityManager().
114 getComponent<PonderableComponent>(entity); 114 getComponent<PonderableComponent>(entity);
115 115
116 if (ponderable.isGrounded()) 116 if (ponderable.grounded)
117 { 117 {
118 auto& orientable = game_.getEntityManager(). 118 auto& orientable = game_.getEntityManager().
119 getComponent<OrientableComponent>(entity); 119 getComponent<OrientableComponent>(entity);
@@ -122,8 +122,8 @@ void OrientingSystem::jump(id_type entity)
122 122
123 playSound("res/Randomize87.wav", 0.25); 123 playSound("res/Randomize87.wav", 0.25);
124 124
125 ponderable.setVelocityY(JUMP_VELOCITY); 125 ponderable.velY = JUMP_VELOCITY;
126 ponderable.setAccelY(JUMP_GRAVITY); 126 ponderable.accelY = JUMP_GRAVITY;
127 127
128 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 128 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
129 if (orientable.isFacingRight()) 129 if (orientable.isFacingRight())
@@ -147,7 +147,7 @@ void OrientingSystem::stopJumping(id_type entity)
147 auto& ponderable = game_.getEntityManager(). 147 auto& ponderable = game_.getEntityManager().
148 getComponent<PonderableComponent>(entity); 148 getComponent<PonderableComponent>(entity);
149 149
150 ponderable.setAccelY(NORMAL_GRAVITY); 150 ponderable.accelY = NORMAL_GRAVITY;
151 } 151 }
152} 152}
153 153
@@ -211,7 +211,7 @@ void OrientingSystem::drop(id_type entity)
211 auto& ponderable = game_.getEntityManager(). 211 auto& ponderable = game_.getEntityManager().
212 getComponent<PonderableComponent>(entity); 212 getComponent<PonderableComponent>(entity);
213 213
214 if (ponderable.isGrounded() 214 if (ponderable.grounded
215 && (orientable.getDropState() == OrientableComponent::DropState::none)) 215 && (orientable.getDropState() == OrientableComponent::DropState::none))
216 { 216 {
217 orientable.setDropState(OrientableComponent::DropState::ready); 217 orientable.setDropState(OrientableComponent::DropState::ready);
diff --git a/src/systems/playing.cpp b/src/systems/playing.cpp index 40d9706..b04f0cb 100644 --- a/src/systems/playing.cpp +++ b/src/systems/playing.cpp
@@ -5,61 +5,17 @@
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/realizable.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"
11#include "systems/scheduling.h" 12#include "systems/scheduling.h"
12#include "systems/controlling.h" 13#include "systems/controlling.h"
14#include "systems/animating.h"
15#include "systems/realizing.h"
13#include "animation.h" 16#include "animation.h"
14#include "muxer.h" 17#include "muxer.h"
15 18
16void PlayingSystem::tick(double)
17{
18 // Check if we need to change the map
19 auto players = game_.getEntityManager().getEntitiesWithComponents<
20 PlayableComponent,
21 TransformableComponent>();
22
23 for (id_type player : players)
24 {
25 auto& playable = game_.getEntityManager().
26 getComponent<PlayableComponent>(player);
27
28 if (playable.changingMap)
29 {
30 // Change the map!
31 auto entities = game_.getEntityManager().getEntities();
32
33 for (id_type entity : entities)
34 {
35 if (entity != player)
36 {
37 game_.getEntityManager().deleteEntity(entity);
38 }
39 }
40
41 game_.getSystemManager().getSystem<MappingSystem>().
42 loadMap(playable.newMapId);
43
44 auto& transformable = game_.getEntityManager().
45 getComponent<TransformableComponent>(player);
46
47 transformable.setX(playable.newMapX);
48 transformable.setY(playable.newMapY);
49
50 playable.changingMap = false;
51
52 if (playable.newMapCallback)
53 {
54 playable.newMapCallback();
55 playable.newMapCallback = nullptr;
56 }
57
58 break;
59 }
60 }
61}
62
63void PlayingSystem::initPlayer() 19void PlayingSystem::initPlayer()
64{ 20{
65 id_type player = game_.getEntityManager().emplaceEntity(); 21 id_type player = game_.getEntityManager().emplaceEntity();
@@ -72,15 +28,24 @@ void PlayingSystem::initPlayer()
72 28
73 game_.getEntityManager().emplaceComponent<AnimatableComponent>( 29 game_.getEntityManager().emplaceComponent<AnimatableComponent>(
74 player, 30 player,
75 std::move(playerGraphics), 31 std::move(playerGraphics));
76 "stillLeft");
77 32
78 game_.getEntityManager().emplaceComponent<TransformableComponent>( 33 game_.getSystemManager().getSystem<AnimatingSystem>().startAnimation(
79 player, 34 player,
80 game_.getWorld().getStartingX(), 35 "stillLeft");
81 game_.getWorld().getStartingY(), 36
82 10, 37 auto& realizing = game_.getSystemManager().getSystem<RealizingSystem>();
83 12); 38
39 auto& realizable = game_.getEntityManager().
40 getComponent<RealizableComponent>(realizing.getSingleton());
41
42 auto& transformable = game_.getEntityManager().
43 emplaceComponent<TransformableComponent>(player);
44
45 transformable.x = realizable.startingX;
46 transformable.y = realizable.startingY;
47 transformable.w = 10;
48 transformable.h = 12;
84 49
85 game_.getSystemManager().getSystem<PonderingSystem>().initializeBody( 50 game_.getSystemManager().getSystem<PonderingSystem>().initializeBody(
86 player, 51 player,
@@ -92,84 +57,103 @@ void PlayingSystem::initPlayer()
92 auto& playable = game_.getEntityManager(). 57 auto& playable = game_.getEntityManager().
93 emplaceComponent<PlayableComponent>(player); 58 emplaceComponent<PlayableComponent>(player);
94 59
95 playable.checkpointMapId = game_.getWorld().getStartingMapId(); 60 playable.mapId = realizable.activeMap;
96 playable.checkpointX = game_.getWorld().getStartingX(); 61 playable.checkpointMapId = realizable.startingMapId;
97 playable.checkpointY = game_.getWorld().getStartingY(); 62 playable.checkpointX = realizable.startingX;
63 playable.checkpointY = realizable.startingY;
64
65 realizing.enterActiveMap(player);
66
67 realizable.activePlayer = player;
98} 68}
99 69
100void PlayingSystem::changeMap( 70void PlayingSystem::changeMap(
71 id_type player,
101 size_t mapId, 72 size_t mapId,
102 double x, 73 double x,
103 double y, 74 double y)
104 PlayableComponent::MapChangeCallback callback)
105{ 75{
106 auto players = game_.getEntityManager().getEntitiesWithComponents< 76 auto& playable = game_.getEntityManager().
107 PlayableComponent>(); 77 getComponent<PlayableComponent>(player);
108 78
109 for (id_type player : players) 79 auto& transformable = game_.getEntityManager().
80 getComponent<TransformableComponent>(player);
81
82 auto& animatable = game_.getEntityManager().
83 getComponent<AnimatableComponent>(player);
84
85 auto& ponderable = game_.getEntityManager().
86 getComponent<PonderableComponent>(player);
87
88 auto& realizing = game_.getSystemManager().getSystem<RealizingSystem>();
89
90 auto& realizable = game_.getEntityManager().
91 getComponent<RealizableComponent>(realizing.getSingleton());
92
93 id_type newMapEntity = realizable.entityByMapId[mapId];
94
95 if (playable.mapId != newMapEntity)
110 { 96 {
111 auto& playable = game_.getEntityManager(). 97 if (playable.mapId == realizable.activeMap)
112 getComponent<PlayableComponent>(player); 98 {
99 realizing.leaveActiveMap(player);
100 } else if (newMapEntity == realizable.activeMap)
101 {
102 realizing.enterActiveMap(player);
103 }
113 104
114 playable.changingMap = true; 105 playable.mapId = newMapEntity;
115 playable.newMapId = mapId; 106 }
116 playable.newMapX = x; 107
117 playable.newMapY = y; 108 transformable.x = x;
118 playable.newMapCallback = std::move(callback); 109 transformable.y = y;
110
111 if (realizable.activePlayer == player)
112 {
113 realizing.loadMap(newMapEntity);
119 } 114 }
120} 115}
121 116
122void PlayingSystem::die() 117void PlayingSystem::die(id_type player)
123{ 118{
124 playSound("res/Hit_Hurt5.wav", 0.25); 119 playSound("res/Hit_Hurt5.wav", 0.25);
125 120
126 auto players = game_.getEntityManager().getEntitiesWithComponents< 121 auto& animatable = game_.getEntityManager().
127 OrientableComponent, 122 getComponent<AnimatableComponent>(player);
128 ControllableComponent,
129 AnimatableComponent,
130 PonderableComponent,
131 PlayableComponent>();
132 123
133 for (id_type player : players) 124 auto& ponderable = game_.getEntityManager().
134 { 125 getComponent<PonderableComponent>(player);
135 auto& animatable = game_.getEntityManager(). 126
136 getComponent<AnimatableComponent>(player); 127 auto& controlling = game_.getSystemManager().getSystem<ControllingSystem>();
137 128 controlling.freeze(player);
138 auto& ponderable = game_.getEntityManager(). 129
139 getComponent<PonderableComponent>(player); 130 animatable.frozen = true;
140 131 animatable.flickering = true;
141 auto& controlling = game_.getSystemManager().getSystem<ControllingSystem>(); 132 ponderable.frozen = true;
142 controlling.freeze(player); 133 ponderable.collidable = false;
143 134
144 animatable.setFrozen(true); 135 auto& scheduling = game_.getSystemManager().getSystem<SchedulingSystem>();
145 animatable.setFlickering(true); 136
146 ponderable.setFrozen(true); 137 scheduling.schedule(player, 0.75, [&] (id_type player) {
147 ponderable.setCollidable(false); 138 auto& playable = game_.getEntityManager().
148 139 getComponent<PlayableComponent>(player);
149 auto& scheduling = game_.getSystemManager().getSystem<SchedulingSystem>(); 140
150 141 changeMap(
151 scheduling.schedule(player, 0.75, [&] (id_type player) { 142 player,
152 auto& playable = game_.getEntityManager(). 143 playable.checkpointMapId,
153 getComponent<PlayableComponent>(player); 144 playable.checkpointX,
154 145 playable.checkpointY);
155 changeMap( 146
156 playable.checkpointMapId, 147 animatable.frozen = false;
157 playable.checkpointX, 148 animatable.flickering = false;
158 playable.checkpointY, 149 ponderable.frozen = false;
159 [&, player] () { 150 ponderable.collidable = true;
160 animatable.setFrozen(false); 151
161 animatable.setFlickering(false); 152 // Reset the walk state, and then potentially let the
162 ponderable.setFrozen(false); 153 // ControllingSystem set it again.
163 ponderable.setCollidable(true); 154 auto& orienting = game_.getSystemManager().getSystem<OrientingSystem>();
164 155 orienting.stopWalking(player);
165 // Reset the walk state, and then potentially let the 156
166 // ControllingSystem set it again. 157 controlling.unfreeze(player);
167 auto& orienting = game_.getSystemManager(). 158 });
168 getSystem<OrientingSystem>();
169 orienting.stopWalking(player);
170
171 controlling.unfreeze(player);
172 });
173 });
174 }
175} 159}
diff --git a/src/systems/playing.h b/src/systems/playing.h index ff16808..9ba403b 100644 --- a/src/systems/playing.h +++ b/src/systems/playing.h
@@ -2,7 +2,6 @@
2#define PLAYING_H_70A54F7D 2#define PLAYING_H_70A54F7D
3 3
4#include "system.h" 4#include "system.h"
5#include "components/playable.h"
6 5
7class PlayingSystem : public System { 6class PlayingSystem : public System {
8public: 7public:
@@ -11,17 +10,15 @@ public:
11 { 10 {
12 } 11 }
13 12
14 void tick(double dt);
15
16 void initPlayer(); 13 void initPlayer();
17 14
18 void changeMap( 15 void changeMap(
16 id_type player,
19 size_t mapId, 17 size_t mapId,
20 double x, 18 double x,
21 double y, 19 double y);
22 PlayableComponent::MapChangeCallback callback = nullptr);
23 20
24 void die(); 21 void die(id_type player);
25 22
26}; 23};
27 24
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index 02d5cfc..4ae6176 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp
@@ -5,149 +5,153 @@
5#include "components/transformable.h" 5#include "components/transformable.h"
6#include "components/orientable.h" 6#include "components/orientable.h"
7#include "components/mappable.h" 7#include "components/mappable.h"
8#include "components/realizable.h"
9#include "components/playable.h"
8#include "systems/orienting.h" 10#include "systems/orienting.h"
9#include "systems/playing.h" 11#include "systems/playing.h"
12#include "systems/realizing.h"
10#include "consts.h" 13#include "consts.h"
11#include "collision.h" 14#include "collision.h"
12 15
13void PonderingSystem::tick(double dt) 16void PonderingSystem::tick(double dt)
14{ 17{
18 auto& realizable = game_.getEntityManager().
19 getComponent<RealizableComponent>(
20 game_.getSystemManager().getSystem<RealizingSystem>().getSingleton());
21
22 id_type mapEntity = realizable.activeMap;
23
24 auto& mappable = game_.getEntityManager().
25 getComponent<MappableComponent>(mapEntity);
26
15 auto entities = game_.getEntityManager().getEntitiesWithComponents< 27 auto entities = game_.getEntityManager().getEntitiesWithComponents<
16 PonderableComponent, 28 PonderableComponent,
17 TransformableComponent>(); 29 TransformableComponent>();
18 30
19 auto maps = game_.getEntityManager().getEntitiesWithComponents<
20 MappableComponent>();
21
22 for (id_type entity : entities) 31 for (id_type entity : entities)
23 { 32 {
24 auto& transformable = game_.getEntityManager().
25 getComponent<TransformableComponent>(entity);
26
27 auto& ponderable = game_.getEntityManager(). 33 auto& ponderable = game_.getEntityManager().
28 getComponent<PonderableComponent>(entity); 34 getComponent<PonderableComponent>(entity);
29 35
30 if (ponderable.isFrozen()) 36 if (!ponderable.active || ponderable.frozen)
31 { 37 {
32 continue; 38 continue;
33 } 39 }
34 40
35 // Accelerate 41 auto& transformable = game_.getEntityManager().
36 ponderable.setVelocityX( 42 getComponent<TransformableComponent>(entity);
37 ponderable.getVelocityX() + ponderable.getAccelX() * dt);
38 43
39 ponderable.setVelocityY( 44 // Accelerate
40 ponderable.getVelocityY() + ponderable.getAccelY() * dt); 45 ponderable.velX += ponderable.accelX * dt;
46 ponderable.velY += ponderable.accelY * dt;
41 47
42 if ((ponderable.getType() == PonderableComponent::Type::freefalling) 48 if ((ponderable.type == PonderableComponent::Type::freefalling)
43 && (ponderable.getVelocityY() > TERMINAL_VELOCITY)) 49 && (ponderable.velY > TERMINAL_VELOCITY))
44 { 50 {
45 ponderable.setVelocityY(TERMINAL_VELOCITY); 51 ponderable.velY = TERMINAL_VELOCITY;
46 } 52 }
47 53
48 const double oldX = transformable.getX(); 54 const double oldX = transformable.x;
49 const double oldY = transformable.getY(); 55 const double oldY = transformable.y;
50 const double oldRight = oldX + transformable.getW(); 56 const double oldRight = oldX + transformable.w;
51 const double oldBottom = oldY + transformable.getH(); 57 const double oldBottom = oldY + transformable.h;
52 58
53 double newX = oldX + ponderable.getVelocityX() * dt; 59 double newX = oldX + ponderable.velX * dt;
54 double newY = oldY + ponderable.getVelocityY() * dt; 60 double newY = oldY + ponderable.velY * dt;
55 61
56 bool oldGrounded = ponderable.isGrounded(); 62 bool oldGrounded = ponderable.grounded;
57 ponderable.setGrounded(false); 63 ponderable.grounded = false;
58 64
59 std::priority_queue<Collision> collisions; 65 std::priority_queue<Collision> collisions;
60 66
61 // Find collisions 67 // Find collisions
62 for (id_type mapEntity : maps) 68 if (newX < oldX)
63 { 69 {
64 auto& mappable = game_.getEntityManager(). 70 for (auto it = mappable.leftBoundaries.lower_bound(oldX);
65 getComponent<MappableComponent>(mapEntity); 71 (it != std::end(mappable.leftBoundaries)) && (it->first >= newX);
66 72 it++)
67 if (newX < oldX)
68 { 73 {
69 for (auto it = mappable.getLeftBoundaries().lower_bound(oldX); 74 if ((oldBottom > it->second.lower)
70 (it != std::end(mappable.getLeftBoundaries())) && (it->first >= newX); 75 && (oldY < it->second.upper))
71 it++)
72 { 76 {
73 if ((oldBottom > it->second.getLower()) 77 // We have a collision!
74 && (oldY < it->second.getUpper())) 78 collisions.emplace(
75 { 79 mapEntity,
76 // We have a collision! 80 Direction::left,
77 collisions.emplace( 81 it->second.type,
78 mapEntity, 82 it->first,
79 Direction::left, 83 it->second.lower,
80 it->second.getType(), 84 it->second.upper);
81 it->first,
82 it->second.getLower(),
83 it->second.getUpper());
84 }
85 } 85 }
86 } else if (newX > oldX) 86 }
87 } else if (newX > oldX)
88 {
89 for (auto it = mappable.rightBoundaries.lower_bound(oldRight);
90 (it != std::end(mappable.rightBoundaries))
91 && (it->first <= (newX + transformable.w));
92 it++)
87 { 93 {
88 for (auto it = mappable.getRightBoundaries().lower_bound(oldRight); 94 if ((oldBottom > it->second.lower)
89 (it != std::end(mappable.getRightBoundaries())) 95 && (oldY < it->second.upper))
90 && (it->first <= (newX + transformable.getW()));
91 it++)
92 { 96 {
93 if ((oldBottom > it->second.getLower()) 97 // We have a collision!
94 && (oldY < it->second.getUpper())) 98 collisions.emplace(
95 { 99 mapEntity,
96 // We have a collision! 100 Direction::right,
97 collisions.emplace( 101 it->second.type,
98 mapEntity, 102 it->first,
99 Direction::right, 103 it->second.lower,
100 it->second.getType(), 104 it->second.upper);
101 it->first,
102 it->second.getLower(),
103 it->second.getUpper());
104 }
105 } 105 }
106 } 106 }
107 }
107 108
108 if (newY < oldY) 109 if (newY < oldY)
110 {
111 for (auto it = mappable.upBoundaries.lower_bound(oldY);
112 (it != std::end(mappable.upBoundaries)) && (it->first >= newY);
113 it++)
109 { 114 {
110 for (auto it = mappable.getUpBoundaries().lower_bound(oldY); 115 if ((oldRight > it->second.lower)
111 (it != std::end(mappable.getUpBoundaries())) && (it->first >= newY); 116 && (oldX < it->second.upper))
112 it++)
113 { 117 {
114 if ((oldRight > it->second.getLower()) 118 // We have a collision!
115 && (oldX < it->second.getUpper())) 119 collisions.emplace(
116 { 120 mapEntity,
117 // We have a collision! 121 Direction::up,
118 collisions.emplace( 122 it->second.type,
119 mapEntity, 123 it->first,
120 Direction::up, 124 it->second.lower,
121 it->second.getType(), 125 it->second.upper);
122 it->first,
123 it->second.getLower(),
124 it->second.getUpper());
125 }
126 } 126 }
127 } else if (newY > oldY) 127 }
128 } else if (newY > oldY)
129 {
130 for (auto it = mappable.downBoundaries.lower_bound(oldBottom);
131 (it != std::end(mappable.downBoundaries))
132 && (it->first <= (newY + transformable.h));
133 it++)
128 { 134 {
129 for (auto it = mappable.getDownBoundaries().lower_bound(oldBottom); 135 if ((oldRight > it->second.lower)
130 (it != std::end(mappable.getDownBoundaries())) 136 && (oldX < it->second.upper))
131 && (it->first <= (newY + transformable.getH()));
132 it++)
133 { 137 {
134 if ((oldRight > it->second.getLower()) 138 // We have a collision!
135 && (oldX < it->second.getUpper())) 139 collisions.emplace(
136 { 140 mapEntity,
137 // We have a collision! 141 Direction::down,
138 collisions.emplace( 142 it->second.type,
139 mapEntity, 143 it->first,
140 Direction::down, 144 it->second.lower,
141 it->second.getType(), 145 it->second.upper);
142 it->first,
143 it->second.getLower(),
144 it->second.getUpper());
145 }
146 } 146 }
147 } 147 }
148 } 148 }
149 149
150 // Process collisions in order of priority 150 // Process collisions in order of priority
151 bool adjacentlyWarping = false;
152 Direction adjWarpDir;
153 size_t adjWarpMapId;
154
151 while (!collisions.empty()) 155 while (!collisions.empty())
152 { 156 {
153 Collision collision = collisions.top(); 157 Collision collision = collisions.top();
@@ -157,8 +161,8 @@ void PonderingSystem::tick(double dt)
157 if (!collision.isColliding( 161 if (!collision.isColliding(
158 newX, 162 newX,
159 newY, 163 newY,
160 transformable.getW(), 164 transformable.w,
161 transformable.getH())) 165 transformable.h))
162 { 166 {
163 continue; 167 continue;
164 } 168 }
@@ -201,33 +205,33 @@ void PonderingSystem::tick(double dt)
201 { 205 {
202 auto& mappable = game_.getEntityManager(). 206 auto& mappable = game_.getEntityManager().
203 getComponent<MappableComponent>(collision.getCollider()); 207 getComponent<MappableComponent>(collision.getCollider());
204 const Map& map = game_.getWorld().getMap(mappable.getMapId()); 208
205 auto& adj = [&] () -> const Map::Adjacent& { 209 auto& adj = [&] () -> const MappableComponent::Adjacent& {
206 switch (collision.getDirection()) 210 switch (collision.getDirection())
207 { 211 {
208 case Direction::left: return map.getLeftAdjacent(); 212 case Direction::left: return mappable.leftAdjacent;
209 case Direction::right: return map.getRightAdjacent(); 213 case Direction::right: return mappable.rightAdjacent;
210 case Direction::up: return map.getUpAdjacent(); 214 case Direction::up: return mappable.upAdjacent;
211 case Direction::down: return map.getDownAdjacent(); 215 case Direction::down: return mappable.downAdjacent;
212 } 216 }
213 }(); 217 }();
214 218
215 switch (adj.getType()) 219 switch (adj.type)
216 { 220 {
217 case Map::Adjacent::Type::wall: 221 case MappableComponent::Adjacent::Type::wall:
218 { 222 {
219 touchedWall = true; 223 touchedWall = true;
220 224
221 break; 225 break;
222 } 226 }
223 227
224 case Map::Adjacent::Type::wrap: 228 case MappableComponent::Adjacent::Type::wrap:
225 { 229 {
226 switch (collision.getDirection()) 230 switch (collision.getDirection())
227 { 231 {
228 case Direction::left: 232 case Direction::left:
229 { 233 {
230 newX = GAME_WIDTH + WALL_GAP - transformable.getW(); 234 newX = GAME_WIDTH + WALL_GAP - transformable.w;
231 235
232 break; 236 break;
233 } 237 }
@@ -241,8 +245,7 @@ void PonderingSystem::tick(double dt)
241 245
242 case Direction::up: 246 case Direction::up:
243 { 247 {
244 newY = MAP_HEIGHT * TILE_HEIGHT + WALL_GAP - 248 newY = MAP_HEIGHT * TILE_HEIGHT + WALL_GAP - transformable.h;
245 transformable.getH();
246 249
247 break; 250 break;
248 } 251 }
@@ -256,46 +259,22 @@ void PonderingSystem::tick(double dt)
256 } 259 }
257 } 260 }
258 261
259 case Map::Adjacent::Type::warp: 262 case MappableComponent::Adjacent::Type::warp:
260 { 263 {
261 double warpX = newX; 264 if (game_.getEntityManager().
262 double warpY = newY; 265 hasComponent<PlayableComponent>(entity))
263
264 switch (collision.getDirection())
265 { 266 {
266 case Direction::left: 267 adjacentlyWarping = true;
267 { 268 adjWarpDir = collision.getDirection();
268 warpX = GAME_WIDTH + WALL_GAP - transformable.getW(); 269 adjWarpMapId = adj.mapId;
269
270 break;
271 }
272
273 case Direction::right:
274 {
275 warpX = -WALL_GAP;
276
277 break;
278 }
279
280 case Direction::up:
281 {
282 warpY = MAP_HEIGHT * TILE_HEIGHT - transformable.getH();
283
284 break;
285 }
286
287 case Direction::down:
288 {
289 warpY = -WALL_GAP;
290
291 break;
292 }
293 } 270 }
294 271
295 game_.getSystemManager().getSystem<PlayingSystem>(). 272 break;
296 changeMap(adj.getMapId(), warpX, warpY); 273 }
297 274
298 stopProcessing = true; 275 case MappableComponent::Adjacent::Type::reverse:
276 {
277 // TODO: not yet implemented.
299 278
300 break; 279 break;
301 } 280 }
@@ -306,7 +285,13 @@ void PonderingSystem::tick(double dt)
306 285
307 case Collision::Type::danger: 286 case Collision::Type::danger:
308 { 287 {
309 game_.getSystemManager().getSystem<PlayingSystem>().die(); 288 if (game_.getEntityManager().
289 hasComponent<PlayableComponent>(entity))
290 {
291 game_.getSystemManager().getSystem<PlayingSystem>().die(entity);
292
293 adjacentlyWarping = false;
294 }
310 295
311 stopProcessing = true; 296 stopProcessing = true;
312 297
@@ -333,15 +318,15 @@ void PonderingSystem::tick(double dt)
333 case Direction::left: 318 case Direction::left:
334 { 319 {
335 newX = collision.getAxis(); 320 newX = collision.getAxis();
336 ponderable.setVelocityX(0.0); 321 ponderable.velX = 0.0;
337 322
338 break; 323 break;
339 } 324 }
340 325
341 case Direction::right: 326 case Direction::right:
342 { 327 {
343 newX = collision.getAxis() - transformable.getW(); 328 newX = collision.getAxis() - transformable.w;
344 ponderable.setVelocityX(0.0); 329 ponderable.velX = 0.0;
345 330
346 break; 331 break;
347 } 332 }
@@ -349,16 +334,16 @@ void PonderingSystem::tick(double dt)
349 case Direction::up: 334 case Direction::up:
350 { 335 {
351 newY = collision.getAxis(); 336 newY = collision.getAxis();
352 ponderable.setVelocityY(0.0); 337 ponderable.velY = 0.0;
353 338
354 break; 339 break;
355 } 340 }
356 341
357 case Direction::down: 342 case Direction::down:
358 { 343 {
359 newY = collision.getAxis() - transformable.getH(); 344 newY = collision.getAxis() - transformable.h;
360 ponderable.setVelocityY(0.0); 345 ponderable.velY = 0.0;
361 ponderable.setGrounded(true); 346 ponderable.grounded = true;
362 347
363 break; 348 break;
364 } 349 }
@@ -367,8 +352,8 @@ void PonderingSystem::tick(double dt)
367 } 352 }
368 353
369 // Move 354 // Move
370 transformable.setX(newX); 355 transformable.x = newX;
371 transformable.setY(newY); 356 transformable.y = newY;
372 357
373 // Perform cleanup for orientable entites 358 // Perform cleanup for orientable entites
374 if (game_.getEntityManager().hasComponent<OrientableComponent>(entity)) 359 if (game_.getEntityManager().hasComponent<OrientableComponent>(entity))
@@ -377,9 +362,9 @@ void PonderingSystem::tick(double dt)
377 getComponent<OrientableComponent>(entity); 362 getComponent<OrientableComponent>(entity);
378 363
379 // Handle changes in groundedness 364 // Handle changes in groundedness
380 if (ponderable.isGrounded() != oldGrounded) 365 if (ponderable.grounded != oldGrounded)
381 { 366 {
382 if (ponderable.isGrounded()) 367 if (ponderable.grounded)
383 { 368 {
384 game_.getSystemManager().getSystem<OrientingSystem>().land(entity); 369 game_.getSystemManager().getSystem<OrientingSystem>().land(entity);
385 } else { 370 } else {
@@ -394,6 +379,51 @@ void PonderingSystem::tick(double dt)
394 orientable.setDropState(OrientableComponent::DropState::none); 379 orientable.setDropState(OrientableComponent::DropState::none);
395 } 380 }
396 } 381 }
382
383 // Move to an adjacent map, if necessary
384 if (adjacentlyWarping)
385 {
386 double warpX = newX;
387 double warpY = newY;
388
389 switch (adjWarpDir)
390 {
391 case Direction::left:
392 {
393 warpX = GAME_WIDTH + WALL_GAP - transformable.w;
394
395 break;
396 }
397
398 case Direction::right:
399 {
400 warpX = -WALL_GAP;
401
402 break;
403 }
404
405 case Direction::up:
406 {
407 warpY = MAP_HEIGHT * TILE_HEIGHT - transformable.h;
408
409 break;
410 }
411
412 case Direction::down:
413 {
414 warpY = -WALL_GAP;
415
416 break;
417 }
418 }
419
420 game_.getSystemManager().getSystem<PlayingSystem>().
421 changeMap(
422 entity,
423 adjWarpMapId,
424 warpX,
425 warpY);
426 }
397 } 427 }
398} 428}
399 429
@@ -406,6 +436,20 @@ void PonderingSystem::initializeBody(
406 436
407 if (type == PonderableComponent::Type::freefalling) 437 if (type == PonderableComponent::Type::freefalling)
408 { 438 {
409 ponderable.setAccelY(NORMAL_GRAVITY); 439 ponderable.accelY = NORMAL_GRAVITY;
410 } 440 }
411} 441}
442
443void PonderingSystem::initPrototype(id_type prototype)
444{
445 auto& ponderable = game_.getEntityManager().
446 getComponent<PonderableComponent>(prototype);
447
448 ponderable.velX = 0.0;
449 ponderable.velY = 0.0;
450 ponderable.accelX = 0.0;
451 ponderable.accelY = 0.0;
452 ponderable.grounded = false;
453 ponderable.frozen = false;
454 ponderable.collidable = true;
455}
diff --git a/src/systems/pondering.h b/src/systems/pondering.h index d70525b..58e6496 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h
@@ -16,6 +16,8 @@ public:
16 16
17 void initializeBody(id_type entity, PonderableComponent::Type type); 17 void initializeBody(id_type entity, PonderableComponent::Type type);
18 18
19 void initPrototype(id_type prototype);
20
19}; 21};
20 22
21#endif /* end of include guard: PONDERING_H_F2530E0E */ 23#endif /* end of include guard: PONDERING_H_F2530E0E */
diff --git a/src/systems/realizing.cpp b/src/systems/realizing.cpp new file mode 100644 index 0000000..09c38f3 --- /dev/null +++ b/src/systems/realizing.cpp
@@ -0,0 +1,321 @@
1#include "realizing.h"
2#include <stdexcept>
3#include <libxml/parser.h>
4#include <cstring>
5#include "game.h"
6#include "consts.h"
7#include "components/realizable.h"
8#include "components/mappable.h"
9#include "components/animatable.h"
10#include "components/playable.h"
11#include "components/ponderable.h"
12#include "components/transformable.h"
13#include "systems/mapping.h"
14#include "systems/animating.h"
15#include "systems/pondering.h"
16
17inline xmlChar* getProp(xmlNodePtr node, const char* attr)
18{
19 xmlChar* key = xmlGetProp(node, reinterpret_cast<const xmlChar*>(attr));
20 if (key == nullptr)
21 {
22 throw std::invalid_argument("Error parsing world file");
23 }
24
25 return key;
26}
27
28// TODO: neither the XML doc nor any of the emplaced entities are properly
29// destroyed if this method throws an exception.
30EntityManager::id_type RealizingSystem::initSingleton(std::string filename)
31{
32 id_type world = game_.getEntityManager().emplaceEntity();
33
34 auto& realizable = game_.getEntityManager().
35 emplaceComponent<RealizableComponent>(world);
36
37 auto& mapping = game_.getSystemManager().getSystem<MappingSystem>();
38
39 xmlDocPtr doc = xmlParseFile(filename.c_str());
40 if (doc == nullptr)
41 {
42 throw std::invalid_argument("Cannot find world file");
43 }
44
45 xmlNodePtr top = xmlDocGetRootElement(doc);
46 if (top == nullptr)
47 {
48 throw std::invalid_argument("Error parsing world file");
49 }
50
51 if (xmlStrcmp(top->name, reinterpret_cast<const xmlChar*>("world")))
52 {
53 throw std::invalid_argument("Error parsing world file");
54 }
55
56 xmlChar* key = nullptr;
57
58 key = getProp(top, "startx");
59 realizable.startingX = atoi(reinterpret_cast<char*>(key));
60 xmlFree(key);
61
62 key = getProp(top, "starty");
63 realizable.startingY = atoi(reinterpret_cast<char*>(key));
64 xmlFree(key);
65
66 key = getProp(top, "startmap");
67 realizable.startingMapId = atoi(reinterpret_cast<char*>(key));
68 xmlFree(key);
69
70 for (xmlNodePtr node = top->xmlChildrenNode;
71 node != nullptr;
72 node = node->next)
73 {
74 if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("map")))
75 {
76 id_type map = game_.getEntityManager().emplaceEntity();
77
78 auto& mappable = game_.getEntityManager().
79 emplaceComponent<MappableComponent>(map,
80 Texture("res/tiles.png"),
81 Texture("res/font.bmp"));
82
83 key = getProp(node, "id");
84 mappable.mapId = atoi(reinterpret_cast<char*>(key));
85 xmlFree(key);
86
87 key = getProp(node, "title");
88 mappable.title = reinterpret_cast<char*>(key);
89 xmlFree(key);
90
91 for (xmlNodePtr mapNode = node->xmlChildrenNode;
92 mapNode != nullptr;
93 mapNode = mapNode->next)
94 {
95 if (!xmlStrcmp(
96 mapNode->name,
97 reinterpret_cast<const xmlChar*>("environment")))
98 {
99 key = xmlNodeGetContent(mapNode);
100 if (key == nullptr)
101 {
102 throw std::invalid_argument("Error parsing world file");
103 }
104
105 mappable.tiles.clear();
106 mappable.tiles.push_back(atoi(strtok(
107 reinterpret_cast<char*>(key),
108 ",\n")));
109
110 for (size_t i = 1; i < (MAP_WIDTH * MAP_HEIGHT); i++)
111 {
112 mappable.tiles.push_back(atoi(strtok(nullptr, ",\n")));
113 }
114
115 xmlFree(key);
116 } else if (!xmlStrcmp(
117 mapNode->name,
118 reinterpret_cast<const xmlChar*>("adjacent")))
119 {
120 key = getProp(mapNode, "type");
121 std::string adjTypeStr(reinterpret_cast<char*>(key));
122 xmlFree(key);
123
124 MappableComponent::Adjacent::Type adjType;
125 if (adjTypeStr == "wall")
126 {
127 adjType = MappableComponent::Adjacent::Type::wall;
128 } else if (adjTypeStr == "wrap")
129 {
130 adjType = MappableComponent::Adjacent::Type::wrap;
131 } else if (adjTypeStr == "warp")
132 {
133 adjType = MappableComponent::Adjacent::Type::warp;
134 } else if (adjTypeStr == "reverseWarp")
135 {
136 adjType = MappableComponent::Adjacent::Type::reverse;
137 } else {
138 throw std::logic_error("Invalid adjacency type");
139 }
140
141 key = getProp(mapNode, "map");
142 size_t adjMapId = atoi(reinterpret_cast<char*>(key));
143 xmlFree(key);
144
145 key = getProp(mapNode, "dir");
146 std::string adjDir(reinterpret_cast<char*>(key));
147 xmlFree(key);
148
149 if (adjDir == "left")
150 {
151 mappable.leftAdjacent = {adjType, adjMapId};
152 } else if (adjDir == "right")
153 {
154 mappable.rightAdjacent = {adjType, adjMapId};
155 } else if (adjDir == "up")
156 {
157 mappable.upAdjacent = {adjType, adjMapId};
158 } else if (adjDir == "down")
159 {
160 mappable.downAdjacent = {adjType, adjMapId};
161 } else {
162 throw std::logic_error("Invalid adjacency direction");
163 }
164 }
165 }
166
167 mapping.generateBoundaries(map);
168
169 realizable.maps.insert(map);
170 realizable.entityByMapId[mappable.mapId] = map;
171 }
172 }
173
174 xmlFreeDoc(doc);
175
176 loadMap(realizable.entityByMapId[realizable.startingMapId]);
177
178 return world;
179}
180
181EntityManager::id_type RealizingSystem::getSingleton() const
182{
183 std::set<id_type> result =
184 game_.getEntityManager().getEntitiesWithComponents<
185 RealizableComponent>();
186
187 if (result.empty())
188 {
189 throw std::logic_error("No realizable entity found");
190 } else if (result.size() > 1)
191 {
192 throw std::logic_error("Multiple realizable entities found");
193 }
194
195 return *std::begin(result);
196}
197
198void RealizingSystem::loadMap(id_type mapEntity)
199{
200 id_type world = getSingleton();
201
202 auto& realizable = game_.getEntityManager().
203 getComponent<RealizableComponent>(world);
204
205 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
206 auto& pondering = game_.getSystemManager().getSystem<PonderingSystem>();
207
208 std::set<id_type> players =
209 game_.getEntityManager().getEntitiesWithComponents<
210 PlayableComponent>();
211
212 if (realizable.hasActiveMap)
213 {
214 id_type oldMap = realizable.activeMap;
215
216 auto& oldMappable = game_.getEntityManager().
217 getComponent<MappableComponent>(oldMap);
218
219 // Deactivate any map objects from the old map.
220 for (id_type prototype : oldMappable.objects)
221 {
222 leaveActiveMap(prototype);
223 }
224
225 // Deactivate players that were on the old map.
226 for (id_type player : players)
227 {
228 auto& playable = game_.getEntityManager().
229 getComponent<PlayableComponent>(player);
230
231 if (playable.mapId == oldMap)
232 {
233 leaveActiveMap(player);
234 }
235 }
236 }
237
238 realizable.hasActiveMap = true;
239 realizable.activeMap = mapEntity;
240
241 auto& mappable = game_.getEntityManager().
242 getComponent<MappableComponent>(mapEntity);
243
244 // Initialize the new map's objects.
245 for (id_type prototype : mappable.objects)
246 {
247 if (game_.getEntityManager().
248 hasComponent<TransformableComponent>(prototype))
249 {
250 auto& transformable = game_.getEntityManager().
251 getComponent<TransformableComponent>(prototype);
252
253 transformable.x = transformable.origX;
254 transformable.y = transformable.origY;
255 transformable.w = transformable.origW;
256 transformable.h = transformable.origH;
257 }
258
259 if (game_.getEntityManager().hasComponent<AnimatableComponent>(prototype))
260 {
261 animating.initPrototype(prototype);
262 }
263
264 if (game_.getEntityManager().hasComponent<PonderableComponent>(prototype))
265 {
266 pondering.initPrototype(prototype);
267 }
268
269 enterActiveMap(prototype);
270 }
271
272 // Activate any players on the map.
273 for (id_type player : players)
274 {
275 auto& playable = game_.getEntityManager().
276 getComponent<PlayableComponent>(player);
277
278 if (playable.mapId == mapEntity)
279 {
280 enterActiveMap(player);
281 }
282 }
283}
284
285void RealizingSystem::enterActiveMap(id_type entity)
286{
287 if (game_.getEntityManager().hasComponent<AnimatableComponent>(entity))
288 {
289 auto& animatable = game_.getEntityManager().
290 getComponent<AnimatableComponent>(entity);
291
292 animatable.active = true;
293 }
294
295 if (game_.getEntityManager().hasComponent<PonderableComponent>(entity))
296 {
297 auto& ponderable = game_.getEntityManager().
298 getComponent<PonderableComponent>(entity);
299
300 ponderable.active = true;
301 }
302}
303
304void RealizingSystem::leaveActiveMap(id_type entity)
305{
306 if (game_.getEntityManager().hasComponent<AnimatableComponent>(entity))
307 {
308 auto& animatable = game_.getEntityManager().
309 getComponent<AnimatableComponent>(entity);
310
311 animatable.active = false;
312 }
313
314 if (game_.getEntityManager().hasComponent<PonderableComponent>(entity))
315 {
316 auto& ponderable = game_.getEntityManager().
317 getComponent<PonderableComponent>(entity);
318
319 ponderable.active = false;
320 }
321}
diff --git a/src/systems/realizing.h b/src/systems/realizing.h new file mode 100644 index 0000000..c681892 --- /dev/null +++ b/src/systems/realizing.h
@@ -0,0 +1,43 @@
1#ifndef REALIZING_H_6853748C
2#define REALIZING_H_6853748C
3
4#include "system.h"
5
6class RealizingSystem : public System {
7public:
8
9 RealizingSystem(Game& game) : System(game)
10 {
11 }
12
13 /**
14 * Creates the singleton realizable entity and initializes it with the
15 * provided world definition.
16 */
17 id_type initSingleton(std::string filename);
18
19 /**
20 * Helper method that returns the entity ID of the (assumed) singleton entity
21 * with a RealizableComponent. Throws an exception if the number of realizable
22 * entities is not exactly one.
23 */
24 id_type getSingleton() const;
25
26 /**
27 * Loads the given map.
28 */
29 void loadMap(id_type mapEntity);
30
31 /**
32 * Treats the given entity as part of the active map.
33 */
34 void enterActiveMap(id_type entity);
35
36 /**
37 * Stops treating the given entity as part of the active map.
38 */
39 void leaveActiveMap(id_type entity);
40
41};
42
43#endif /* end of include guard: REALIZING_H_6853748C */
diff --git a/src/world.cpp b/src/world.cpp deleted file mode 100644 index 3b6bd41..0000000 --- a/src/world.cpp +++ /dev/null
@@ -1,155 +0,0 @@
1#include "world.h"
2#include <libxml/parser.h>
3#include <stdexcept>
4#include <cstring>
5#include "consts.h"
6
7inline 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
18World::World(std::string filename)
19{
20 xmlDocPtr doc = xmlParseFile(filename.c_str());
21 if (doc == nullptr)
22 {
23 throw std::invalid_argument("Cannot find world file");
24 }
25
26 xmlNodePtr top = xmlDocGetRootElement(doc);
27 if (top == nullptr)
28 {
29 throw std::invalid_argument("Error parsing world file");
30 }
31
32 if (xmlStrcmp(top->name, reinterpret_cast<const xmlChar*>("world")))
33 {
34 throw std::invalid_argument("Error parsing world file");
35 }
36
37 xmlChar* key = nullptr;
38
39 key = getProp(top, "startx");
40 startX_ = atoi(reinterpret_cast<char*>(key));
41 xmlFree(key);
42
43 key = getProp(top, "starty");
44 startY_ = atoi(reinterpret_cast<char*>(key));
45 xmlFree(key);
46
47 key = getProp(top, "startmap");
48 startMap_ = atoi(reinterpret_cast<char*>(key));
49 xmlFree(key);
50
51 for (xmlNodePtr node = top->xmlChildrenNode;
52 node != nullptr;
53 node = node->next)
54 {
55 if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("map")))
56 {
57 key = getProp(node, "id");
58 size_t mapId = atoi(reinterpret_cast<char*>(key));
59 xmlFree(key);
60
61 key = getProp(node, "title");
62 std::string mapTitle(reinterpret_cast<char*>(key));
63 xmlFree(key);
64
65 std::vector<int> mapTiles;
66 Map::Adjacent leftAdj;
67 Map::Adjacent rightAdj;
68 Map::Adjacent upAdj;
69 Map::Adjacent downAdj;
70
71 for (xmlNodePtr mapNode = node->xmlChildrenNode;
72 mapNode != nullptr;
73 mapNode = mapNode->next)
74 {
75 if (!xmlStrcmp(
76 mapNode->name,
77 reinterpret_cast<const xmlChar*>("environment")))
78 {
79 key = xmlNodeGetContent(mapNode);
80
81 mapTiles.clear();
82 mapTiles.push_back(atoi(strtok(reinterpret_cast<char*>(key), ",\n")));
83 for (size_t i = 1; i < (MAP_WIDTH * MAP_HEIGHT); i++)
84 {
85 mapTiles.push_back(atoi(strtok(nullptr, ",\n")));
86 }
87
88 xmlFree(key);
89 } else if (!xmlStrcmp(
90 mapNode->name,
91 reinterpret_cast<const xmlChar*>("adjacent")))
92 {
93 key = getProp(mapNode, "type");
94 std::string adjTypeStr(reinterpret_cast<char*>(key));
95 xmlFree(key);
96
97 Map::Adjacent::Type adjType;
98 if (adjTypeStr == "wall")
99 {
100 adjType = Map::Adjacent::Type::wall;
101 } else if (adjTypeStr == "wrap")
102 {
103 adjType = Map::Adjacent::Type::wrap;
104 } else if (adjTypeStr == "warp")
105 {
106 adjType = Map::Adjacent::Type::warp;
107 } else if (adjTypeStr == "reverseWarp")
108 {
109 adjType = Map::Adjacent::Type::reverse;
110 } else {
111 throw std::logic_error("Invalid adjacency type");
112 }
113
114 key = getProp(mapNode, "map");
115 int adjMapId = atoi(reinterpret_cast<char*>(key));
116 xmlFree(key);
117
118 key = getProp(mapNode, "dir");
119 std::string adjDir(reinterpret_cast<char*>(key));
120 xmlFree(key);
121
122 if (adjDir == "left")
123 {
124 leftAdj = {adjType, adjMapId};
125 } else if (adjDir == "right")
126 {
127 rightAdj = {adjType, adjMapId};
128 } else if (adjDir == "up")
129 {
130 upAdj = {adjType, adjMapId};
131 } else if (adjDir == "down")
132 {
133 downAdj = {adjType, adjMapId};
134 } else {
135 throw std::logic_error("Invalid adjacency direction");
136 }
137 }
138 }
139
140 maps_.emplace(
141 std::piecewise_construct,
142 std::forward_as_tuple(mapId),
143 std::forward_as_tuple(
144 mapId,
145 std::move(mapTiles),
146 std::move(mapTitle),
147 leftAdj,
148 rightAdj,
149 upAdj,
150 downAdj));
151 }
152 }
153
154 xmlFreeDoc(doc);
155}
diff --git a/src/world.h b/src/world.h deleted file mode 100644 index b88adf4..0000000 --- a/src/world.h +++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef WORLD_H_153C698B
2#define WORLD_H_153C698B
3
4#include <map>
5#include <string>
6#include "map.h"
7
8class World {
9public:
10
11 explicit World(std::string filename);
12
13 inline const Map& getMap(size_t id) const
14 {
15 return maps_.at(id);
16 }
17
18 inline size_t getStartingMapId() const
19 {
20 return startMap_;
21 }
22
23 inline int getStartingX() const
24 {
25 return startX_;
26 }
27
28 inline int getStartingY() const
29 {
30 return startY_;
31 }
32
33private:
34
35 std::map<size_t, Map> maps_;
36 size_t startMap_;
37 int startX_;
38 int startY_;
39};
40
41#endif /* end of include guard: WORLD_H_153C698B */