diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-04-28 09:22:44 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-04-28 09:22:44 -0400 |
commit | 8016a7146fec3f6f43ca05723441750e5aae3d4d (patch) | |
tree | 0d527c1af80cf9ac34a027f9ee6f1acbb95db9f4 /src | |
parent | f782b81ba10c9b7a1e221b16de0aaa7b6c521729 (diff) | |
download | therapy-8016a7146fec3f6f43ca05723441750e5aae3d4d.tar.gz therapy-8016a7146fec3f6f43ca05723441750e5aae3d4d.tar.bz2 therapy-8016a7146fec3f6f43ca05723441750e5aae3d4d.zip |
Restructured the way the world is loaded
The World class was removed and replaced by the RealizingSystem and RealizableComponent. The realizable entity is intended to be a singleton and to represent the world. The Map class was also removed and integrated into the MappableComponent. These changes are to facilitate implementation of map objects without needing special intermediary objects (including the Map class). Now, map entities are created as soon as the world is created, and map object entities will be as well. They will simply be deactivated while the map is not active. Multiple players are now slightly better supported, which will be important in the future. This will likely become inefficient as the world becomes bigger, and some sort of sector-loading process will have to be designed. This also reduces the usefulness of EntityManager's entity-searching capabilities (which are not the most efficiently implemented currently anyway), and will likely in the future require some added functionality to better search subsets of entities. A lot of the components were also rewritten to use bare member variables instead of accessor methods, as they never had special functionality and just took up space. These components were also documented.
Diffstat (limited to 'src')
-rw-r--r-- | src/components/animatable.h | 146 | ||||
-rw-r--r-- | src/components/mappable.h | 208 | ||||
-rw-r--r-- | src/components/playable.h | 28 | ||||
-rw-r--r-- | src/components/ponderable.h | 151 | ||||
-rw-r--r-- | src/components/realizable.h | 67 | ||||
-rw-r--r-- | src/components/transformable.h | 79 | ||||
-rw-r--r-- | src/game.cpp | 6 | ||||
-rw-r--r-- | src/game.h | 7 | ||||
-rw-r--r-- | src/map.h | 111 | ||||
-rw-r--r-- | src/systems/animating.cpp | 93 | ||||
-rw-r--r-- | src/systems/animating.h | 2 | ||||
-rw-r--r-- | src/systems/mapping.cpp | 127 | ||||
-rw-r--r-- | src/systems/mapping.h | 2 | ||||
-rw-r--r-- | src/systems/orienting.cpp | 22 | ||||
-rw-r--r-- | src/systems/playing.cpp | 220 | ||||
-rw-r--r-- | src/systems/playing.h | 9 | ||||
-rw-r--r-- | src/systems/pondering.cpp | 354 | ||||
-rw-r--r-- | src/systems/pondering.h | 2 | ||||
-rw-r--r-- | src/systems/realizing.cpp | 321 | ||||
-rw-r--r-- | src/systems/realizing.h | 43 | ||||
-rw-r--r-- | src/world.cpp | 155 | ||||
-rw-r--r-- | src/world.h | 41 |
22 files changed, 1154 insertions, 1040 deletions
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 @@ | |||
8 | class AnimatableComponent : public Component { | 8 | class AnimatableComponent : public Component { |
9 | public: | 9 | public: |
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 | |
84 | private: | 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 | ||
10 | class MappableComponent : public Component { | 13 | class MappableComponent : public Component { |
11 | public: | 14 | public: |
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 | ||
128 | private: | 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 | ||
7 | class PlayableComponent : public Component { | 7 | class PlayableComponent : public Component { |
8 | public: | 8 | public: |
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 @@ | |||
6 | class PonderableComponent : public Component { | 6 | class PonderableComponent : public Component { |
7 | public: | 7 | public: |
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 | |||
93 | private: | ||
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 | |||
9 | class RealizableComponent : public Component { | ||
10 | public: | ||
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 @@ | |||
6 | class TransformableComponent : public Component { | 6 | class TransformableComponent : public Component { |
7 | public: | 7 | public: |
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 | |||
61 | private: | ||
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 | ||
31 | Game::Game() : world_("res/maps.xml") | 32 | Game::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 | ||
9 | class Game { | 8 | class 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 | |||
10 | class Map { | ||
11 | public: | ||
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 | |||
100 | private: | ||
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 | ||
83 | void 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 | |||
77 | void AnimatingSystem::startAnimation(id_type entity, std::string animation) | 96 | void 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 | ||
19 | void MappingSystem::render(Texture& texture) | 21 | void 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 | ||
83 | void MappingSystem::loadMap(size_t mapId) | 84 | void 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 | ||
16 | void 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 | |||
63 | void PlayingSystem::initPlayer() | 19 | void 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 | ||
100 | void PlayingSystem::changeMap( | 70 | void 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 | ||
122 | void PlayingSystem::die() | 117 | void 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 | ||
7 | class PlayingSystem : public System { | 6 | class PlayingSystem : public System { |
8 | public: | 7 | public: |
@@ -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 | ||
13 | void PonderingSystem::tick(double dt) | 16 | void 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 | |||
443 | void 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 | |||
17 | inline 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. | ||
30 | EntityManager::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 | |||
181 | EntityManager::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 | |||
198 | void 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 | |||
285 | void 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 | |||
304 | void 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 | |||
6 | class RealizingSystem : public System { | ||
7 | public: | ||
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 | |||
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 | |||
18 | World::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 | |||
8 | class World { | ||
9 | public: | ||
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 | |||
33 | private: | ||
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 */ | ||