summary refs log tree commit diff stats
path: root/src/systems
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-04-28 09:22:44 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-04-28 09:22:44 -0400
commit8016a7146fec3f6f43ca05723441750e5aae3d4d (patch)
tree0d527c1af80cf9ac34a027f9ee6f1acbb95db9f4 /src/systems
parentf782b81ba10c9b7a1e221b16de0aaa7b6c521729 (diff)
downloadtherapy-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/systems')
-rw-r--r--src/systems/animating.cpp93
-rw-r--r--src/systems/animating.h2
-rw-r--r--src/systems/mapping.cpp127
-rw-r--r--src/systems/mapping.h2
-rw-r--r--src/systems/orienting.cpp22
-rw-r--r--src/systems/playing.cpp220
-rw-r--r--src/systems/playing.h9
-rw-r--r--src/systems/pondering.cpp354
-rw-r--r--src/systems/pondering.h2
-rw-r--r--src/systems/realizing.cpp321
-rw-r--r--src/systems/realizing.h43
11 files changed, 800 insertions, 395 deletions
diff --git a/src/systems/animating.cpp b/src/systems/animating.cpp index 634af67..8543ba2 100644 --- a/src/systems/animating.cpp +++ b/src/systems/animating.cpp
@@ -13,26 +13,29 @@ void AnimatingSystem::tick(double)
13 auto& sprite = game_.getEntityManager(). 13 auto& sprite = game_.getEntityManager().
14 getComponent<AnimatableComponent>(entity); 14 getComponent<AnimatableComponent>(entity);
15 15
16 if (!sprite.isFrozen()) 16 if (sprite.active)
17 { 17 {
18 sprite.setCountdown(sprite.getCountdown() + 1); 18 if (!sprite.frozen)
19 } 19 {
20 20 sprite.countdown++;
21 const Animation& anim = sprite.getAnimation(); 21 }
22 if (sprite.getCountdown() >= anim.getDelay())
23 {
24 sprite.setFrame(sprite.getFrame() + 1);
25 sprite.setCountdown(0);
26 22
27 if (sprite.getFrame() >= anim.getFirstFrame() + anim.getNumFrames()) 23 const Animation& anim = sprite.getAnimation();
24 if (sprite.countdown >= anim.getDelay())
28 { 25 {
29 sprite.setFrame(anim.getFirstFrame()); 26 sprite.frame++;
27 sprite.countdown = 0;
28
29 if (sprite.frame >= anim.getFirstFrame() + anim.getNumFrames())
30 {
31 sprite.frame = anim.getFirstFrame();
32 }
30 } 33 }
31 }
32 34
33 if (sprite.isFlickering()) 35 if (sprite.flickering)
34 { 36 {
35 sprite.setFlickerTimer((sprite.getFlickerTimer() + 1) % 6); 37 sprite.flickerTimer = (sprite.flickerTimer + 1) % 6;
38 }
36 } 39 }
37 } 40 }
38} 41}
@@ -49,36 +52,52 @@ void AnimatingSystem::render(Texture& texture)
49 auto& sprite = game_.getEntityManager(). 52 auto& sprite = game_.getEntityManager().
50 getComponent<AnimatableComponent>(entity); 53 getComponent<AnimatableComponent>(entity);
51 54
52 auto& transform = game_.getEntityManager(). 55 if (sprite.active)
53 getComponent<TransformableComponent>(entity);
54
55 double alpha = 1.0;
56 if (sprite.isFlickering() && (sprite.getFlickerTimer() < 3))
57 { 56 {
58 alpha = 0.0; 57 auto& transform = game_.getEntityManager().
59 } 58 getComponent<TransformableComponent>(entity);
60 59
61 Rectangle dstrect { 60 double alpha = 1.0;
62 static_cast<int>(transform.getX()), 61 if (sprite.flickering && (sprite.flickerTimer < 3))
63 static_cast<int>(transform.getY()), 62 {
64 transform.getW(), 63 alpha = 0.0;
65 transform.getH()}; 64 }
66 65
67 const AnimationSet& aset = sprite.getAnimationSet(); 66 Rectangle dstrect {
68 game_.getRenderer().blit( 67 static_cast<int>(transform.x),
69 aset.getTexture(), 68 static_cast<int>(transform.y),
70 texture, 69 transform.w,
71 aset.getFrameRect(sprite.getFrame()), 70 transform.h};
72 dstrect, 71
73 alpha); 72 const AnimationSet& aset = sprite.animationSet;
73 game_.getRenderer().blit(
74 aset.getTexture(),
75 texture,
76 aset.getFrameRect(sprite.frame),
77 dstrect,
78 alpha);
79 }
74 } 80 }
75} 81}
76 82
83void AnimatingSystem::initPrototype(id_type entity)
84{
85 auto& sprite = game_.getEntityManager().
86 getComponent<AnimatableComponent>(entity);
87
88 startAnimation(entity, sprite.origAnimation);
89
90 sprite.countdown = 0;
91 sprite.flickering = false;
92 sprite.flickerTimer = 0;
93 sprite.frozen = false;
94}
95
77void AnimatingSystem::startAnimation(id_type entity, std::string animation) 96void AnimatingSystem::startAnimation(id_type entity, std::string animation)
78{ 97{
79 auto& sprite = game_.getEntityManager(). 98 auto& sprite = game_.getEntityManager().
80 getComponent<AnimatableComponent>(entity); 99 getComponent<AnimatableComponent>(entity);
81 100
82 sprite.setAnimation(animation); 101 sprite.animation = std::move(animation);
83 sprite.setFrame(sprite.getAnimation().getFirstFrame()); 102 sprite.frame = sprite.getAnimation().getFirstFrame();
84} 103}
diff --git a/src/systems/animating.h b/src/systems/animating.h index 548bff1..acc6191 100644 --- a/src/systems/animating.h +++ b/src/systems/animating.h
@@ -16,6 +16,8 @@ public:
16 16
17 void render(Texture& texture); 17 void render(Texture& texture);
18 18
19 void initPrototype(id_type entity);
20
19 void startAnimation(id_type entity, std::string animation); 21 void startAnimation(id_type entity, std::string animation);
20 22
21}; 23};
diff --git a/src/systems/mapping.cpp b/src/systems/mapping.cpp index a3a17ec..af67aed 100644 --- a/src/systems/mapping.cpp +++ b/src/systems/mapping.cpp
@@ -1,5 +1,7 @@
1#include "mapping.h" 1#include "mapping.h"
2#include "components/mappable.h" 2#include "components/mappable.h"
3#include "components/realizable.h"
4#include "systems/realizing.h"
3#include "game.h" 5#include "game.h"
4#include "consts.h" 6#include "consts.h"
5 7
@@ -18,104 +20,95 @@ inline void addBoundary(
18 20
19void MappingSystem::render(Texture& texture) 21void MappingSystem::render(Texture& texture)
20{ 22{
21 auto entities = game_.getEntityManager().getEntitiesWithComponents< 23 auto& realizable = game_.getEntityManager().
22 MappableComponent>(); 24 getComponent<RealizableComponent>(
25 game_.getSystemManager().getSystem<RealizingSystem>().getSingleton());
23 26
24 for (id_type entity : entities) 27 id_type map = realizable.activeMap;
25 {
26 auto& mappable = game_.getEntityManager().
27 getComponent<MappableComponent>(entity);
28 28
29 const Map& map = game_.getWorld().getMap(mappable.getMapId()); 29 auto& mappable = game_.getEntityManager().
30 getComponent<MappableComponent>(map);
30 31
31 for (int i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++) 32 for (int i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++)
32 { 33 {
33 int x = i % MAP_WIDTH; 34 int x = i % MAP_WIDTH;
34 int y = i / MAP_WIDTH; 35 int y = i / MAP_WIDTH;
35 int tile = map.getTiles()[i]; 36 int tile = mappable.tiles[i];
36
37 if (tile > 0)
38 {
39 Rectangle dst {
40 x * TILE_WIDTH,
41 y * TILE_HEIGHT,
42 TILE_WIDTH,
43 TILE_HEIGHT};
44
45 Rectangle src {
46 (tile % TILESET_COLS) * TILE_WIDTH,
47 (tile / TILESET_COLS) * TILE_HEIGHT,
48 TILE_WIDTH,
49 TILE_HEIGHT};
50
51 game_.getRenderer().blit(
52 mappable.getTileset(),
53 texture,
54 std::move(src),
55 std::move(dst));
56 }
57 }
58 37
59 int startX = ((GAME_WIDTH / TILE_WIDTH) / 2) - (map.getTitle().size() / 2); 38 if (tile > 0)
60 for (size_t i = 0; i < map.getTitle().size(); i++)
61 { 39 {
62 Rectangle src { 40 Rectangle dst {
63 (map.getTitle()[i] % FONT_COLS) * TILE_WIDTH, 41 x * TILE_WIDTH,
64 (map.getTitle()[i] / FONT_COLS) * TILE_HEIGHT, 42 y * TILE_HEIGHT,
65 TILE_WIDTH, 43 TILE_WIDTH,
66 TILE_HEIGHT}; 44 TILE_HEIGHT};
67 45
68 Rectangle dst { 46 Rectangle src {
69 (startX + static_cast<int>(i)) * TILE_WIDTH, 47 (tile % TILESET_COLS) * TILE_WIDTH,
70 24 * TILE_HEIGHT, 48 (tile / TILESET_COLS) * TILE_HEIGHT,
71 TILE_WIDTH, 49 TILE_WIDTH,
72 TILE_HEIGHT}; 50 TILE_HEIGHT};
73 51
74 game_.getRenderer().blit( 52 game_.getRenderer().blit(
75 mappable.getFont(), 53 mappable.tileset,
76 texture, 54 texture,
77 std::move(src), 55 std::move(src),
78 std::move(dst)); 56 std::move(dst));
79 } 57 }
80 } 58 }
59
60 int startX = ((GAME_WIDTH / TILE_WIDTH) / 2) - (mappable.title.size() / 2);
61
62 for (size_t i = 0; i < mappable.title.size(); i++)
63 {
64 Rectangle src {
65 (mappable.title[i] % FONT_COLS) * TILE_WIDTH,
66 (mappable.title[i] / FONT_COLS) * TILE_HEIGHT,
67 TILE_WIDTH,
68 TILE_HEIGHT};
69
70 Rectangle dst {
71 (startX + static_cast<int>(i)) * TILE_WIDTH,
72 24 * TILE_HEIGHT,
73 TILE_WIDTH,
74 TILE_HEIGHT};
75
76 game_.getRenderer().blit(
77 mappable.font,
78 texture,
79 std::move(src),
80 std::move(dst));
81 }
81} 82}
82 83
83void MappingSystem::loadMap(size_t mapId) 84void MappingSystem::generateBoundaries(id_type mapEntity)
84{ 85{
85 id_type mapEntity = game_.getEntityManager().emplaceEntity();
86
87 auto& mappable = game_.getEntityManager(). 86 auto& mappable = game_.getEntityManager().
88 emplaceComponent<MappableComponent>(mapEntity, 87 getComponent<MappableComponent>(mapEntity);
89 Texture("res/tiles.png"),
90 Texture("res/font.bmp"));
91
92 mappable.setMapId(mapId);
93
94 const Map& map = game_.getWorld().getMap(mappable.getMapId());
95 88
96 addBoundary( 89 addBoundary(
97 mappable.getLeftBoundaries(), 90 mappable.leftBoundaries,
98 -WALL_GAP, 91 -WALL_GAP,
99 0, 92 0,
100 MAP_HEIGHT * TILE_HEIGHT, 93 MAP_HEIGHT * TILE_HEIGHT,
101 MappableComponent::Boundary::Type::adjacency); 94 MappableComponent::Boundary::Type::adjacency);
102 95
103 addBoundary( 96 addBoundary(
104 mappable.getRightBoundaries(), 97 mappable.rightBoundaries,
105 GAME_WIDTH + WALL_GAP, 98 GAME_WIDTH + WALL_GAP,
106 0, 99 0,
107 MAP_HEIGHT * TILE_HEIGHT, 100 MAP_HEIGHT * TILE_HEIGHT,
108 MappableComponent::Boundary::Type::adjacency); 101 MappableComponent::Boundary::Type::adjacency);
109 102
110 addBoundary( 103 addBoundary(
111 mappable.getUpBoundaries(), 104 mappable.upBoundaries,
112 -WALL_GAP, 105 -WALL_GAP,
113 0, 106 0,
114 GAME_WIDTH, 107 GAME_WIDTH,
115 MappableComponent::Boundary::Type::adjacency); 108 MappableComponent::Boundary::Type::adjacency);
116 109
117 addBoundary( 110 addBoundary(
118 mappable.getDownBoundaries(), 111 mappable.downBoundaries,
119 MAP_HEIGHT * TILE_HEIGHT + WALL_GAP, 112 MAP_HEIGHT * TILE_HEIGHT + WALL_GAP,
120 0, 113 0,
121 GAME_WIDTH, 114 GAME_WIDTH,
@@ -125,12 +118,12 @@ void MappingSystem::loadMap(size_t mapId)
125 { 118 {
126 size_t x = i % MAP_WIDTH; 119 size_t x = i % MAP_WIDTH;
127 size_t y = i / MAP_WIDTH; 120 size_t y = i / MAP_WIDTH;
128 int tile = map.getTiles()[i]; 121 int tile = mappable.tiles[i];
129 122
130 if ((tile >= 5) && (tile <= 7)) 123 if ((tile >= 5) && (tile <= 7))
131 { 124 {
132 addBoundary( 125 addBoundary(
133 mappable.getDownBoundaries(), 126 mappable.downBoundaries,
134 y * TILE_HEIGHT, 127 y * TILE_HEIGHT,
135 x * TILE_WIDTH, 128 x * TILE_WIDTH,
136 (x + 1) * TILE_WIDTH, 129 (x + 1) * TILE_WIDTH,
@@ -138,28 +131,28 @@ void MappingSystem::loadMap(size_t mapId)
138 } else if ((tile > 0) && (tile < 28)) 131 } else if ((tile > 0) && (tile < 28))
139 { 132 {
140 addBoundary( 133 addBoundary(
141 mappable.getRightBoundaries(), 134 mappable.rightBoundaries,
142 x * TILE_WIDTH, 135 x * TILE_WIDTH,
143 y * TILE_HEIGHT, 136 y * TILE_HEIGHT,
144 (y+1) * TILE_HEIGHT, 137 (y+1) * TILE_HEIGHT,
145 MappableComponent::Boundary::Type::wall); 138 MappableComponent::Boundary::Type::wall);
146 139
147 addBoundary( 140 addBoundary(
148 mappable.getLeftBoundaries(), 141 mappable.leftBoundaries,
149 (x+1) * TILE_WIDTH, 142 (x+1) * TILE_WIDTH,
150 y * TILE_HEIGHT, 143 y * TILE_HEIGHT,
151 (y+1) * TILE_HEIGHT, 144 (y+1) * TILE_HEIGHT,
152 MappableComponent::Boundary::Type::wall); 145 MappableComponent::Boundary::Type::wall);
153 146
154 addBoundary( 147 addBoundary(
155 mappable.getDownBoundaries(), 148 mappable.downBoundaries,
156 y * TILE_HEIGHT, 149 y * TILE_HEIGHT,
157 x * TILE_WIDTH, 150 x * TILE_WIDTH,
158 (x+1) * TILE_WIDTH, 151 (x+1) * TILE_WIDTH,
159 MappableComponent::Boundary::Type::wall); 152 MappableComponent::Boundary::Type::wall);
160 153
161 addBoundary( 154 addBoundary(
162 mappable.getUpBoundaries(), 155 mappable.upBoundaries,
163 (y+1) * TILE_HEIGHT, 156 (y+1) * TILE_HEIGHT,
164 x * TILE_WIDTH, 157 x * TILE_WIDTH,
165 (x+1) * TILE_WIDTH, 158 (x+1) * TILE_WIDTH,
@@ -167,28 +160,28 @@ void MappingSystem::loadMap(size_t mapId)
167 } else if (tile == 42) 160 } else if (tile == 42)
168 { 161 {
169 addBoundary( 162 addBoundary(
170 mappable.getRightBoundaries(), 163 mappable.rightBoundaries,
171 x * TILE_WIDTH, 164 x * TILE_WIDTH,
172 y * TILE_HEIGHT, 165 y * TILE_HEIGHT,
173 (y+1) * TILE_HEIGHT, 166 (y+1) * TILE_HEIGHT,
174 MappableComponent::Boundary::Type::danger); 167 MappableComponent::Boundary::Type::danger);
175 168
176 addBoundary( 169 addBoundary(
177 mappable.getLeftBoundaries(), 170 mappable.leftBoundaries,
178 (x+1) * TILE_WIDTH, 171 (x+1) * TILE_WIDTH,
179 y * TILE_HEIGHT, 172 y * TILE_HEIGHT,
180 (y+1) * TILE_HEIGHT, 173 (y+1) * TILE_HEIGHT,
181 MappableComponent::Boundary::Type::danger); 174 MappableComponent::Boundary::Type::danger);
182 175
183 addBoundary( 176 addBoundary(
184 mappable.getDownBoundaries(), 177 mappable.downBoundaries,
185 y * TILE_HEIGHT, 178 y * TILE_HEIGHT,
186 x * TILE_WIDTH, 179 x * TILE_WIDTH,
187 (x+1) * TILE_WIDTH, 180 (x+1) * TILE_WIDTH,
188 MappableComponent::Boundary::Type::danger); 181 MappableComponent::Boundary::Type::danger);
189 182
190 addBoundary( 183 addBoundary(
191 mappable.getUpBoundaries(), 184 mappable.upBoundaries,
192 (y+1) * TILE_HEIGHT, 185 (y+1) * TILE_HEIGHT,
193 x * TILE_WIDTH, 186 x * TILE_WIDTH,
194 (x+1) * TILE_WIDTH, 187 (x+1) * TILE_WIDTH,
diff --git a/src/systems/mapping.h b/src/systems/mapping.h index 53d054b..3c47419 100644 --- a/src/systems/mapping.h +++ b/src/systems/mapping.h
@@ -12,7 +12,7 @@ public:
12 12
13 void render(Texture& texture); 13 void render(Texture& texture);
14 14
15 void loadMap(size_t mapId); 15 void generateBoundaries(id_type mapEntity);
16 16
17}; 17};
18 18
diff --git a/src/systems/orienting.cpp b/src/systems/orienting.cpp index 2df8f87..206ebf6 100644 --- a/src/systems/orienting.cpp +++ b/src/systems/orienting.cpp
@@ -24,27 +24,27 @@ void OrientingSystem::tick(double)
24 { 24 {
25 case OrientableComponent::WalkState::still: 25 case OrientableComponent::WalkState::still:
26 { 26 {
27 ponderable.setVelocityX(0); 27 ponderable.velX = 0.0;
28 28
29 break; 29 break;
30 } 30 }
31 31
32 case OrientableComponent::WalkState::left: 32 case OrientableComponent::WalkState::left:
33 { 33 {
34 ponderable.setVelocityX(-WALK_SPEED); 34 ponderable.velX = -WALK_SPEED;
35 35
36 break; 36 break;
37 } 37 }
38 38
39 case OrientableComponent::WalkState::right: 39 case OrientableComponent::WalkState::right:
40 { 40 {
41 ponderable.setVelocityX(WALK_SPEED); 41 ponderable.velX = WALK_SPEED;
42 42
43 break; 43 break;
44 } 44 }
45 } 45 }
46 46
47 if (orientable.isJumping() && (ponderable.getVelocityY() > 0)) 47 if (orientable.isJumping() && (ponderable.velY > 0))
48 { 48 {
49 orientable.setJumping(false); 49 orientable.setJumping(false);
50 } 50 }
@@ -63,7 +63,7 @@ void OrientingSystem::moveLeft(id_type entity)
63 orientable.setWalkState(OrientableComponent::WalkState::left); 63 orientable.setWalkState(OrientableComponent::WalkState::left);
64 64
65 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 65 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
66 if (ponderable.isGrounded()) 66 if (ponderable.grounded)
67 { 67 {
68 animating.startAnimation(entity, "walkingLeft"); 68 animating.startAnimation(entity, "walkingLeft");
69 } else { 69 } else {
@@ -83,7 +83,7 @@ void OrientingSystem::moveRight(id_type entity)
83 orientable.setWalkState(OrientableComponent::WalkState::right); 83 orientable.setWalkState(OrientableComponent::WalkState::right);
84 84
85 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 85 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
86 if (ponderable.isGrounded()) 86 if (ponderable.grounded)
87 { 87 {
88 animating.startAnimation(entity, "walkingRight"); 88 animating.startAnimation(entity, "walkingRight");
89 } else { 89 } else {
@@ -113,7 +113,7 @@ void OrientingSystem::jump(id_type entity)
113 auto& ponderable = game_.getEntityManager(). 113 auto& ponderable = game_.getEntityManager().
114 getComponent<PonderableComponent>(entity); 114 getComponent<PonderableComponent>(entity);
115 115
116 if (ponderable.isGrounded()) 116 if (ponderable.grounded)
117 { 117 {
118 auto& orientable = game_.getEntityManager(). 118 auto& orientable = game_.getEntityManager().
119 getComponent<OrientableComponent>(entity); 119 getComponent<OrientableComponent>(entity);
@@ -122,8 +122,8 @@ void OrientingSystem::jump(id_type entity)
122 122
123 playSound("res/Randomize87.wav", 0.25); 123 playSound("res/Randomize87.wav", 0.25);
124 124
125 ponderable.setVelocityY(JUMP_VELOCITY); 125 ponderable.velY = JUMP_VELOCITY;
126 ponderable.setAccelY(JUMP_GRAVITY); 126 ponderable.accelY = JUMP_GRAVITY;
127 127
128 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 128 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
129 if (orientable.isFacingRight()) 129 if (orientable.isFacingRight())
@@ -147,7 +147,7 @@ void OrientingSystem::stopJumping(id_type entity)
147 auto& ponderable = game_.getEntityManager(). 147 auto& ponderable = game_.getEntityManager().
148 getComponent<PonderableComponent>(entity); 148 getComponent<PonderableComponent>(entity);
149 149
150 ponderable.setAccelY(NORMAL_GRAVITY); 150 ponderable.accelY = NORMAL_GRAVITY;
151 } 151 }
152} 152}
153 153
@@ -211,7 +211,7 @@ void OrientingSystem::drop(id_type entity)
211 auto& ponderable = game_.getEntityManager(). 211 auto& ponderable = game_.getEntityManager().
212 getComponent<PonderableComponent>(entity); 212 getComponent<PonderableComponent>(entity);
213 213
214 if (ponderable.isGrounded() 214 if (ponderable.grounded
215 && (orientable.getDropState() == OrientableComponent::DropState::none)) 215 && (orientable.getDropState() == OrientableComponent::DropState::none))
216 { 216 {
217 orientable.setDropState(OrientableComponent::DropState::ready); 217 orientable.setDropState(OrientableComponent::DropState::ready);
diff --git a/src/systems/playing.cpp b/src/systems/playing.cpp index 40d9706..b04f0cb 100644 --- a/src/systems/playing.cpp +++ b/src/systems/playing.cpp
@@ -5,61 +5,17 @@
5#include "components/playable.h" 5#include "components/playable.h"
6#include "components/controllable.h" 6#include "components/controllable.h"
7#include "components/orientable.h" 7#include "components/orientable.h"
8#include "components/realizable.h"
8#include "systems/mapping.h" 9#include "systems/mapping.h"
9#include "systems/pondering.h" 10#include "systems/pondering.h"
10#include "systems/orienting.h" 11#include "systems/orienting.h"
11#include "systems/scheduling.h" 12#include "systems/scheduling.h"
12#include "systems/controlling.h" 13#include "systems/controlling.h"
14#include "systems/animating.h"
15#include "systems/realizing.h"
13#include "animation.h" 16#include "animation.h"
14#include "muxer.h" 17#include "muxer.h"
15 18
16void PlayingSystem::tick(double)
17{
18 // Check if we need to change the map
19 auto players = game_.getEntityManager().getEntitiesWithComponents<
20 PlayableComponent,
21 TransformableComponent>();
22
23 for (id_type player : players)
24 {
25 auto& playable = game_.getEntityManager().
26 getComponent<PlayableComponent>(player);
27
28 if (playable.changingMap)
29 {
30 // Change the map!
31 auto entities = game_.getEntityManager().getEntities();
32
33 for (id_type entity : entities)
34 {
35 if (entity != player)
36 {
37 game_.getEntityManager().deleteEntity(entity);
38 }
39 }
40
41 game_.getSystemManager().getSystem<MappingSystem>().
42 loadMap(playable.newMapId);
43
44 auto& transformable = game_.getEntityManager().
45 getComponent<TransformableComponent>(player);
46
47 transformable.setX(playable.newMapX);
48 transformable.setY(playable.newMapY);
49
50 playable.changingMap = false;
51
52 if (playable.newMapCallback)
53 {
54 playable.newMapCallback();
55 playable.newMapCallback = nullptr;
56 }
57
58 break;
59 }
60 }
61}
62
63void PlayingSystem::initPlayer() 19void PlayingSystem::initPlayer()
64{ 20{
65 id_type player = game_.getEntityManager().emplaceEntity(); 21 id_type player = game_.getEntityManager().emplaceEntity();
@@ -72,15 +28,24 @@ void PlayingSystem::initPlayer()
72 28
73 game_.getEntityManager().emplaceComponent<AnimatableComponent>( 29 game_.getEntityManager().emplaceComponent<AnimatableComponent>(
74 player, 30 player,
75 std::move(playerGraphics), 31 std::move(playerGraphics));
76 "stillLeft");
77 32
78 game_.getEntityManager().emplaceComponent<TransformableComponent>( 33 game_.getSystemManager().getSystem<AnimatingSystem>().startAnimation(
79 player, 34 player,
80 game_.getWorld().getStartingX(), 35 "stillLeft");
81 game_.getWorld().getStartingY(), 36
82 10, 37 auto& realizing = game_.getSystemManager().getSystem<RealizingSystem>();
83 12); 38
39 auto& realizable = game_.getEntityManager().
40 getComponent<RealizableComponent>(realizing.getSingleton());
41
42 auto& transformable = game_.getEntityManager().
43 emplaceComponent<TransformableComponent>(player);
44
45 transformable.x = realizable.startingX;
46 transformable.y = realizable.startingY;
47 transformable.w = 10;
48 transformable.h = 12;
84 49
85 game_.getSystemManager().getSystem<PonderingSystem>().initializeBody( 50 game_.getSystemManager().getSystem<PonderingSystem>().initializeBody(
86 player, 51 player,
@@ -92,84 +57,103 @@ void PlayingSystem::initPlayer()
92 auto& playable = game_.getEntityManager(). 57 auto& playable = game_.getEntityManager().
93 emplaceComponent<PlayableComponent>(player); 58 emplaceComponent<PlayableComponent>(player);
94 59
95 playable.checkpointMapId = game_.getWorld().getStartingMapId(); 60 playable.mapId = realizable.activeMap;
96 playable.checkpointX = game_.getWorld().getStartingX(); 61 playable.checkpointMapId = realizable.startingMapId;
97 playable.checkpointY = game_.getWorld().getStartingY(); 62 playable.checkpointX = realizable.startingX;
63 playable.checkpointY = realizable.startingY;
64
65 realizing.enterActiveMap(player);
66
67 realizable.activePlayer = player;
98} 68}
99 69
100void PlayingSystem::changeMap( 70void PlayingSystem::changeMap(
71 id_type player,
101 size_t mapId, 72 size_t mapId,
102 double x, 73 double x,
103 double y, 74 double y)
104 PlayableComponent::MapChangeCallback callback)
105{ 75{
106 auto players = game_.getEntityManager().getEntitiesWithComponents< 76 auto& playable = game_.getEntityManager().
107 PlayableComponent>(); 77 getComponent<PlayableComponent>(player);
108 78
109 for (id_type player : players) 79 auto& transformable = game_.getEntityManager().
80 getComponent<TransformableComponent>(player);
81
82 auto& animatable = game_.getEntityManager().
83 getComponent<AnimatableComponent>(player);
84
85 auto& ponderable = game_.getEntityManager().
86 getComponent<PonderableComponent>(player);
87
88 auto& realizing = game_.getSystemManager().getSystem<RealizingSystem>();
89
90 auto& realizable = game_.getEntityManager().
91 getComponent<RealizableComponent>(realizing.getSingleton());
92
93 id_type newMapEntity = realizable.entityByMapId[mapId];
94
95 if (playable.mapId != newMapEntity)
110 { 96 {
111 auto& playable = game_.getEntityManager(). 97 if (playable.mapId == realizable.activeMap)
112 getComponent<PlayableComponent>(player); 98 {
99 realizing.leaveActiveMap(player);
100 } else if (newMapEntity == realizable.activeMap)
101 {
102 realizing.enterActiveMap(player);
103 }
113 104
114 playable.changingMap = true; 105 playable.mapId = newMapEntity;
115 playable.newMapId = mapId; 106 }
116 playable.newMapX = x; 107
117 playable.newMapY = y; 108 transformable.x = x;
118 playable.newMapCallback = std::move(callback); 109 transformable.y = y;
110
111 if (realizable.activePlayer == player)
112 {
113 realizing.loadMap(newMapEntity);
119 } 114 }
120} 115}
121 116
122void PlayingSystem::die() 117void PlayingSystem::die(id_type player)
123{ 118{
124 playSound("res/Hit_Hurt5.wav", 0.25); 119 playSound("res/Hit_Hurt5.wav", 0.25);
125 120
126 auto players = game_.getEntityManager().getEntitiesWithComponents< 121 auto& animatable = game_.getEntityManager().
127 OrientableComponent, 122 getComponent<AnimatableComponent>(player);
128 ControllableComponent,
129 AnimatableComponent,
130 PonderableComponent,
131 PlayableComponent>();
132 123
133 for (id_type player : players) 124 auto& ponderable = game_.getEntityManager().
134 { 125 getComponent<PonderableComponent>(player);
135 auto& animatable = game_.getEntityManager(). 126
136 getComponent<AnimatableComponent>(player); 127 auto& controlling = game_.getSystemManager().getSystem<ControllingSystem>();
137 128 controlling.freeze(player);
138 auto& ponderable = game_.getEntityManager(). 129
139 getComponent<PonderableComponent>(player); 130 animatable.frozen = true;
140 131 animatable.flickering = true;
141 auto& controlling = game_.getSystemManager().getSystem<ControllingSystem>(); 132 ponderable.frozen = true;
142 controlling.freeze(player); 133 ponderable.collidable = false;
143 134
144 animatable.setFrozen(true); 135 auto& scheduling = game_.getSystemManager().getSystem<SchedulingSystem>();
145 animatable.setFlickering(true); 136
146 ponderable.setFrozen(true); 137 scheduling.schedule(player, 0.75, [&] (id_type player) {
147 ponderable.setCollidable(false); 138 auto& playable = game_.getEntityManager().
148 139 getComponent<PlayableComponent>(player);
149 auto& scheduling = game_.getSystemManager().getSystem<SchedulingSystem>(); 140
150 141 changeMap(
151 scheduling.schedule(player, 0.75, [&] (id_type player) { 142 player,
152 auto& playable = game_.getEntityManager(). 143 playable.checkpointMapId,
153 getComponent<PlayableComponent>(player); 144 playable.checkpointX,
154 145 playable.checkpointY);
155 changeMap( 146
156 playable.checkpointMapId, 147 animatable.frozen = false;
157 playable.checkpointX, 148 animatable.flickering = false;
158 playable.checkpointY, 149 ponderable.frozen = false;
159 [&, player] () { 150 ponderable.collidable = true;
160 animatable.setFrozen(false); 151
161 animatable.setFlickering(false); 152 // Reset the walk state, and then potentially let the
162 ponderable.setFrozen(false); 153 // ControllingSystem set it again.
163 ponderable.setCollidable(true); 154 auto& orienting = game_.getSystemManager().getSystem<OrientingSystem>();
164 155 orienting.stopWalking(player);
165 // Reset the walk state, and then potentially let the 156
166 // ControllingSystem set it again. 157 controlling.unfreeze(player);
167 auto& orienting = game_.getSystemManager(). 158 });
168 getSystem<OrientingSystem>();
169 orienting.stopWalking(player);
170
171 controlling.unfreeze(player);
172 });
173 });
174 }
175} 159}
diff --git a/src/systems/playing.h b/src/systems/playing.h index ff16808..9ba403b 100644 --- a/src/systems/playing.h +++ b/src/systems/playing.h
@@ -2,7 +2,6 @@
2#define PLAYING_H_70A54F7D 2#define PLAYING_H_70A54F7D
3 3
4#include "system.h" 4#include "system.h"
5#include "components/playable.h"
6 5
7class PlayingSystem : public System { 6class PlayingSystem : public System {
8public: 7public:
@@ -11,17 +10,15 @@ public:
11 { 10 {
12 } 11 }
13 12
14 void tick(double dt);
15
16 void initPlayer(); 13 void initPlayer();
17 14
18 void changeMap( 15 void changeMap(
16 id_type player,
19 size_t mapId, 17 size_t mapId,
20 double x, 18 double x,
21 double y, 19 double y);
22 PlayableComponent::MapChangeCallback callback = nullptr);
23 20
24 void die(); 21 void die(id_type player);
25 22
26}; 23};
27 24
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index 02d5cfc..4ae6176 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp
@@ -5,149 +5,153 @@
5#include "components/transformable.h" 5#include "components/transformable.h"
6#include "components/orientable.h" 6#include "components/orientable.h"
7#include "components/mappable.h" 7#include "components/mappable.h"
8#include "components/realizable.h"
9#include "components/playable.h"
8#include "systems/orienting.h" 10#include "systems/orienting.h"
9#include "systems/playing.h" 11#include "systems/playing.h"
12#include "systems/realizing.h"
10#include "consts.h" 13#include "consts.h"
11#include "collision.h" 14#include "collision.h"
12 15
13void PonderingSystem::tick(double dt) 16void PonderingSystem::tick(double dt)
14{ 17{
18 auto& realizable = game_.getEntityManager().
19 getComponent<RealizableComponent>(
20 game_.getSystemManager().getSystem<RealizingSystem>().getSingleton());
21
22 id_type mapEntity = realizable.activeMap;
23
24 auto& mappable = game_.getEntityManager().
25 getComponent<MappableComponent>(mapEntity);
26
15 auto entities = game_.getEntityManager().getEntitiesWithComponents< 27 auto entities = game_.getEntityManager().getEntitiesWithComponents<
16 PonderableComponent, 28 PonderableComponent,
17 TransformableComponent>(); 29 TransformableComponent>();
18 30
19 auto maps = game_.getEntityManager().getEntitiesWithComponents<
20 MappableComponent>();
21
22 for (id_type entity : entities) 31 for (id_type entity : entities)
23 { 32 {
24 auto& transformable = game_.getEntityManager().
25 getComponent<TransformableComponent>(entity);
26
27 auto& ponderable = game_.getEntityManager(). 33 auto& ponderable = game_.getEntityManager().
28 getComponent<PonderableComponent>(entity); 34 getComponent<PonderableComponent>(entity);
29 35
30 if (ponderable.isFrozen()) 36 if (!ponderable.active || ponderable.frozen)
31 { 37 {
32 continue; 38 continue;
33 } 39 }
34 40
35 // Accelerate 41 auto& transformable = game_.getEntityManager().
36 ponderable.setVelocityX( 42 getComponent<TransformableComponent>(entity);
37 ponderable.getVelocityX() + ponderable.getAccelX() * dt);
38 43
39 ponderable.setVelocityY( 44 // Accelerate
40 ponderable.getVelocityY() + ponderable.getAccelY() * dt); 45 ponderable.velX += ponderable.accelX * dt;
46 ponderable.velY += ponderable.accelY * dt;
41 47
42 if ((ponderable.getType() == PonderableComponent::Type::freefalling) 48 if ((ponderable.type == PonderableComponent::Type::freefalling)
43 && (ponderable.getVelocityY() > TERMINAL_VELOCITY)) 49 && (ponderable.velY > TERMINAL_VELOCITY))
44 { 50 {
45 ponderable.setVelocityY(TERMINAL_VELOCITY); 51 ponderable.velY = TERMINAL_VELOCITY;
46 } 52 }
47 53
48 const double oldX = transformable.getX(); 54 const double oldX = transformable.x;
49 const double oldY = transformable.getY(); 55 const double oldY = transformable.y;
50 const double oldRight = oldX + transformable.getW(); 56 const double oldRight = oldX + transformable.w;
51 const double oldBottom = oldY + transformable.getH(); 57 const double oldBottom = oldY + transformable.h;
52 58
53 double newX = oldX + ponderable.getVelocityX() * dt; 59 double newX = oldX + ponderable.velX * dt;
54 double newY = oldY + ponderable.getVelocityY() * dt; 60 double newY = oldY + ponderable.velY * dt;
55 61
56 bool oldGrounded = ponderable.isGrounded(); 62 bool oldGrounded = ponderable.grounded;
57 ponderable.setGrounded(false); 63 ponderable.grounded = false;
58 64
59 std::priority_queue<Collision> collisions; 65 std::priority_queue<Collision> collisions;
60 66
61 // Find collisions 67 // Find collisions
62 for (id_type mapEntity : maps) 68 if (newX < oldX)
63 { 69 {
64 auto& mappable = game_.getEntityManager(). 70 for (auto it = mappable.leftBoundaries.lower_bound(oldX);
65 getComponent<MappableComponent>(mapEntity); 71 (it != std::end(mappable.leftBoundaries)) && (it->first >= newX);
66 72 it++)
67 if (newX < oldX)
68 { 73 {
69 for (auto it = mappable.getLeftBoundaries().lower_bound(oldX); 74 if ((oldBottom > it->second.lower)
70 (it != std::end(mappable.getLeftBoundaries())) && (it->first >= newX); 75 && (oldY < it->second.upper))
71 it++)
72 { 76 {
73 if ((oldBottom > it->second.getLower()) 77 // We have a collision!
74 && (oldY < it->second.getUpper())) 78 collisions.emplace(
75 { 79 mapEntity,
76 // We have a collision! 80 Direction::left,
77 collisions.emplace( 81 it->second.type,
78 mapEntity, 82 it->first,
79 Direction::left, 83 it->second.lower,
80 it->second.getType(), 84 it->second.upper);
81 it->first,
82 it->second.getLower(),
83 it->second.getUpper());
84 }
85 } 85 }
86 } else if (newX > oldX) 86 }
87 } else if (newX > oldX)
88 {
89 for (auto it = mappable.rightBoundaries.lower_bound(oldRight);
90 (it != std::end(mappable.rightBoundaries))
91 && (it->first <= (newX + transformable.w));
92 it++)
87 { 93 {
88 for (auto it = mappable.getRightBoundaries().lower_bound(oldRight); 94 if ((oldBottom > it->second.lower)
89 (it != std::end(mappable.getRightBoundaries())) 95 && (oldY < it->second.upper))
90 && (it->first <= (newX + transformable.getW()));
91 it++)
92 { 96 {
93 if ((oldBottom > it->second.getLower()) 97 // We have a collision!
94 && (oldY < it->second.getUpper())) 98 collisions.emplace(
95 { 99 mapEntity,
96 // We have a collision! 100 Direction::right,
97 collisions.emplace( 101 it->second.type,
98 mapEntity, 102 it->first,
99 Direction::right, 103 it->second.lower,
100 it->second.getType(), 104 it->second.upper);
101 it->first,
102 it->second.getLower(),
103 it->second.getUpper());
104 }
105 } 105 }
106 } 106 }
107 }
107 108
108 if (newY < oldY) 109 if (newY < oldY)
110 {
111 for (auto it = mappable.upBoundaries.lower_bound(oldY);
112 (it != std::end(mappable.upBoundaries)) && (it->first >= newY);
113 it++)
109 { 114 {
110 for (auto it = mappable.getUpBoundaries().lower_bound(oldY); 115 if ((oldRight > it->second.lower)
111 (it != std::end(mappable.getUpBoundaries())) && (it->first >= newY); 116 && (oldX < it->second.upper))
112 it++)
113 { 117 {
114 if ((oldRight > it->second.getLower()) 118 // We have a collision!
115 && (oldX < it->second.getUpper())) 119 collisions.emplace(
116 { 120 mapEntity,
117 // We have a collision! 121 Direction::up,
118 collisions.emplace( 122 it->second.type,
119 mapEntity, 123 it->first,
120 Direction::up, 124 it->second.lower,
121 it->second.getType(), 125 it->second.upper);
122 it->first,
123 it->second.getLower(),
124 it->second.getUpper());
125 }
126 } 126 }
127 } else if (newY > oldY) 127 }
128 } else if (newY > oldY)
129 {
130 for (auto it = mappable.downBoundaries.lower_bound(oldBottom);
131 (it != std::end(mappable.downBoundaries))
132 && (it->first <= (newY + transformable.h));
133 it++)
128 { 134 {
129 for (auto it = mappable.getDownBoundaries().lower_bound(oldBottom); 135 if ((oldRight > it->second.lower)
130 (it != std::end(mappable.getDownBoundaries())) 136 && (oldX < it->second.upper))
131 && (it->first <= (newY + transformable.getH()));
132 it++)
133 { 137 {
134 if ((oldRight > it->second.getLower()) 138 // We have a collision!
135 && (oldX < it->second.getUpper())) 139 collisions.emplace(
136 { 140 mapEntity,
137 // We have a collision! 141 Direction::down,
138 collisions.emplace( 142 it->second.type,
139 mapEntity, 143 it->first,
140 Direction::down, 144 it->second.lower,
141 it->second.getType(), 145 it->second.upper);
142 it->first,
143 it->second.getLower(),
144 it->second.getUpper());
145 }
146 } 146 }
147 } 147 }
148 } 148 }
149 149
150 // Process collisions in order of priority 150 // Process collisions in order of priority
151 bool adjacentlyWarping = false;
152 Direction adjWarpDir;
153 size_t adjWarpMapId;
154
151 while (!collisions.empty()) 155 while (!collisions.empty())
152 { 156 {
153 Collision collision = collisions.top(); 157 Collision collision = collisions.top();
@@ -157,8 +161,8 @@ void PonderingSystem::tick(double dt)
157 if (!collision.isColliding( 161 if (!collision.isColliding(
158 newX, 162 newX,
159 newY, 163 newY,
160 transformable.getW(), 164 transformable.w,
161 transformable.getH())) 165 transformable.h))
162 { 166 {
163 continue; 167 continue;
164 } 168 }
@@ -201,33 +205,33 @@ void PonderingSystem::tick(double dt)
201 { 205 {
202 auto& mappable = game_.getEntityManager(). 206 auto& mappable = game_.getEntityManager().
203 getComponent<MappableComponent>(collision.getCollider()); 207 getComponent<MappableComponent>(collision.getCollider());
204 const Map& map = game_.getWorld().getMap(mappable.getMapId()); 208
205 auto& adj = [&] () -> const Map::Adjacent& { 209 auto& adj = [&] () -> const MappableComponent::Adjacent& {
206 switch (collision.getDirection()) 210 switch (collision.getDirection())
207 { 211 {
208 case Direction::left: return map.getLeftAdjacent(); 212 case Direction::left: return mappable.leftAdjacent;
209 case Direction::right: return map.getRightAdjacent(); 213 case Direction::right: return mappable.rightAdjacent;
210 case Direction::up: return map.getUpAdjacent(); 214 case Direction::up: return mappable.upAdjacent;
211 case Direction::down: return map.getDownAdjacent(); 215 case Direction::down: return mappable.downAdjacent;
212 } 216 }
213 }(); 217 }();
214 218
215 switch (adj.getType()) 219 switch (adj.type)
216 { 220 {
217 case Map::Adjacent::Type::wall: 221 case MappableComponent::Adjacent::Type::wall:
218 { 222 {
219 touchedWall = true; 223 touchedWall = true;
220 224
221 break; 225 break;
222 } 226 }
223 227
224 case Map::Adjacent::Type::wrap: 228 case MappableComponent::Adjacent::Type::wrap:
225 { 229 {
226 switch (collision.getDirection()) 230 switch (collision.getDirection())
227 { 231 {
228 case Direction::left: 232 case Direction::left:
229 { 233 {
230 newX = GAME_WIDTH + WALL_GAP - transformable.getW(); 234 newX = GAME_WIDTH + WALL_GAP - transformable.w;
231 235
232 break; 236 break;
233 } 237 }
@@ -241,8 +245,7 @@ void PonderingSystem::tick(double dt)
241 245
242 case Direction::up: 246 case Direction::up:
243 { 247 {
244 newY = MAP_HEIGHT * TILE_HEIGHT + WALL_GAP - 248 newY = MAP_HEIGHT * TILE_HEIGHT + WALL_GAP - transformable.h;
245 transformable.getH();
246 249
247 break; 250 break;
248 } 251 }
@@ -256,46 +259,22 @@ void PonderingSystem::tick(double dt)
256 } 259 }
257 } 260 }
258 261
259 case Map::Adjacent::Type::warp: 262 case MappableComponent::Adjacent::Type::warp:
260 { 263 {
261 double warpX = newX; 264 if (game_.getEntityManager().
262 double warpY = newY; 265 hasComponent<PlayableComponent>(entity))
263
264 switch (collision.getDirection())
265 { 266 {
266 case Direction::left: 267 adjacentlyWarping = true;
267 { 268 adjWarpDir = collision.getDirection();
268 warpX = GAME_WIDTH + WALL_GAP - transformable.getW(); 269 adjWarpMapId = adj.mapId;
269
270 break;
271 }
272
273 case Direction::right:
274 {
275 warpX = -WALL_GAP;
276
277 break;
278 }
279
280 case Direction::up:
281 {
282 warpY = MAP_HEIGHT * TILE_HEIGHT - transformable.getH();
283
284 break;
285 }
286
287 case Direction::down:
288 {
289 warpY = -WALL_GAP;
290
291 break;
292 }
293 } 270 }
294 271
295 game_.getSystemManager().getSystem<PlayingSystem>(). 272 break;
296 changeMap(adj.getMapId(), warpX, warpY); 273 }
297 274
298 stopProcessing = true; 275 case MappableComponent::Adjacent::Type::reverse:
276 {
277 // TODO: not yet implemented.
299 278
300 break; 279 break;
301 } 280 }
@@ -306,7 +285,13 @@ void PonderingSystem::tick(double dt)
306 285
307 case Collision::Type::danger: 286 case Collision::Type::danger:
308 { 287 {
309 game_.getSystemManager().getSystem<PlayingSystem>().die(); 288 if (game_.getEntityManager().
289 hasComponent<PlayableComponent>(entity))
290 {
291 game_.getSystemManager().getSystem<PlayingSystem>().die(entity);
292
293 adjacentlyWarping = false;
294 }
310 295
311 stopProcessing = true; 296 stopProcessing = true;
312 297
@@ -333,15 +318,15 @@ void PonderingSystem::tick(double dt)
333 case Direction::left: 318 case Direction::left:
334 { 319 {
335 newX = collision.getAxis(); 320 newX = collision.getAxis();
336 ponderable.setVelocityX(0.0); 321 ponderable.velX = 0.0;
337 322
338 break; 323 break;
339 } 324 }
340 325
341 case Direction::right: 326 case Direction::right:
342 { 327 {
343 newX = collision.getAxis() - transformable.getW(); 328 newX = collision.getAxis() - transformable.w;
344 ponderable.setVelocityX(0.0); 329 ponderable.velX = 0.0;
345 330
346 break; 331 break;
347 } 332 }
@@ -349,16 +334,16 @@ void PonderingSystem::tick(double dt)
349 case Direction::up: 334 case Direction::up:
350 { 335 {
351 newY = collision.getAxis(); 336 newY = collision.getAxis();
352 ponderable.setVelocityY(0.0); 337 ponderable.velY = 0.0;
353 338
354 break; 339 break;
355 } 340 }
356 341
357 case Direction::down: 342 case Direction::down:
358 { 343 {
359 newY = collision.getAxis() - transformable.getH(); 344 newY = collision.getAxis() - transformable.h;
360 ponderable.setVelocityY(0.0); 345 ponderable.velY = 0.0;
361 ponderable.setGrounded(true); 346 ponderable.grounded = true;
362 347
363 break; 348 break;
364 } 349 }
@@ -367,8 +352,8 @@ void PonderingSystem::tick(double dt)
367 } 352 }
368 353
369 // Move 354 // Move
370 transformable.setX(newX); 355 transformable.x = newX;
371 transformable.setY(newY); 356 transformable.y = newY;
372 357
373 // Perform cleanup for orientable entites 358 // Perform cleanup for orientable entites
374 if (game_.getEntityManager().hasComponent<OrientableComponent>(entity)) 359 if (game_.getEntityManager().hasComponent<OrientableComponent>(entity))
@@ -377,9 +362,9 @@ void PonderingSystem::tick(double dt)
377 getComponent<OrientableComponent>(entity); 362 getComponent<OrientableComponent>(entity);
378 363
379 // Handle changes in groundedness 364 // Handle changes in groundedness
380 if (ponderable.isGrounded() != oldGrounded) 365 if (ponderable.grounded != oldGrounded)
381 { 366 {
382 if (ponderable.isGrounded()) 367 if (ponderable.grounded)
383 { 368 {
384 game_.getSystemManager().getSystem<OrientingSystem>().land(entity); 369 game_.getSystemManager().getSystem<OrientingSystem>().land(entity);
385 } else { 370 } else {
@@ -394,6 +379,51 @@ void PonderingSystem::tick(double dt)
394 orientable.setDropState(OrientableComponent::DropState::none); 379 orientable.setDropState(OrientableComponent::DropState::none);
395 } 380 }
396 } 381 }
382
383 // Move to an adjacent map, if necessary
384 if (adjacentlyWarping)
385 {
386 double warpX = newX;
387 double warpY = newY;
388
389 switch (adjWarpDir)
390 {
391 case Direction::left:
392 {
393 warpX = GAME_WIDTH + WALL_GAP - transformable.w;
394
395 break;
396 }
397
398 case Direction::right:
399 {
400 warpX = -WALL_GAP;
401
402 break;
403 }
404
405 case Direction::up:
406 {
407 warpY = MAP_HEIGHT * TILE_HEIGHT - transformable.h;
408
409 break;
410 }
411
412 case Direction::down:
413 {
414 warpY = -WALL_GAP;
415
416 break;
417 }
418 }
419
420 game_.getSystemManager().getSystem<PlayingSystem>().
421 changeMap(
422 entity,
423 adjWarpMapId,
424 warpX,
425 warpY);
426 }
397 } 427 }
398} 428}
399 429
@@ -406,6 +436,20 @@ void PonderingSystem::initializeBody(
406 436
407 if (type == PonderableComponent::Type::freefalling) 437 if (type == PonderableComponent::Type::freefalling)
408 { 438 {
409 ponderable.setAccelY(NORMAL_GRAVITY); 439 ponderable.accelY = NORMAL_GRAVITY;
410 } 440 }
411} 441}
442
443void PonderingSystem::initPrototype(id_type prototype)
444{
445 auto& ponderable = game_.getEntityManager().
446 getComponent<PonderableComponent>(prototype);
447
448 ponderable.velX = 0.0;
449 ponderable.velY = 0.0;
450 ponderable.accelX = 0.0;
451 ponderable.accelY = 0.0;
452 ponderable.grounded = false;
453 ponderable.frozen = false;
454 ponderable.collidable = true;
455}
diff --git a/src/systems/pondering.h b/src/systems/pondering.h index d70525b..58e6496 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h
@@ -16,6 +16,8 @@ public:
16 16
17 void initializeBody(id_type entity, PonderableComponent::Type type); 17 void initializeBody(id_type entity, PonderableComponent::Type type);
18 18
19 void initPrototype(id_type prototype);
20
19}; 21};
20 22
21#endif /* end of include guard: PONDERING_H_F2530E0E */ 23#endif /* end of include guard: PONDERING_H_F2530E0E */
diff --git a/src/systems/realizing.cpp b/src/systems/realizing.cpp new file mode 100644 index 0000000..09c38f3 --- /dev/null +++ b/src/systems/realizing.cpp
@@ -0,0 +1,321 @@
1#include "realizing.h"
2#include <stdexcept>
3#include <libxml/parser.h>
4#include <cstring>
5#include "game.h"
6#include "consts.h"
7#include "components/realizable.h"
8#include "components/mappable.h"
9#include "components/animatable.h"
10#include "components/playable.h"
11#include "components/ponderable.h"
12#include "components/transformable.h"
13#include "systems/mapping.h"
14#include "systems/animating.h"
15#include "systems/pondering.h"
16
17inline xmlChar* getProp(xmlNodePtr node, const char* attr)
18{
19 xmlChar* key = xmlGetProp(node, reinterpret_cast<const xmlChar*>(attr));
20 if (key == nullptr)
21 {
22 throw std::invalid_argument("Error parsing world file");
23 }
24
25 return key;
26}
27
28// TODO: neither the XML doc nor any of the emplaced entities are properly
29// destroyed if this method throws an exception.
30EntityManager::id_type RealizingSystem::initSingleton(std::string filename)
31{
32 id_type world = game_.getEntityManager().emplaceEntity();
33
34 auto& realizable = game_.getEntityManager().
35 emplaceComponent<RealizableComponent>(world);
36
37 auto& mapping = game_.getSystemManager().getSystem<MappingSystem>();
38
39 xmlDocPtr doc = xmlParseFile(filename.c_str());
40 if (doc == nullptr)
41 {
42 throw std::invalid_argument("Cannot find world file");
43 }
44
45 xmlNodePtr top = xmlDocGetRootElement(doc);
46 if (top == nullptr)
47 {
48 throw std::invalid_argument("Error parsing world file");
49 }
50
51 if (xmlStrcmp(top->name, reinterpret_cast<const xmlChar*>("world")))
52 {
53 throw std::invalid_argument("Error parsing world file");
54 }
55
56 xmlChar* key = nullptr;
57
58 key = getProp(top, "startx");
59 realizable.startingX = atoi(reinterpret_cast<char*>(key));
60 xmlFree(key);
61
62 key = getProp(top, "starty");
63 realizable.startingY = atoi(reinterpret_cast<char*>(key));
64 xmlFree(key);
65
66 key = getProp(top, "startmap");
67 realizable.startingMapId = atoi(reinterpret_cast<char*>(key));
68 xmlFree(key);
69
70 for (xmlNodePtr node = top->xmlChildrenNode;
71 node != nullptr;
72 node = node->next)
73 {
74 if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("map")))
75 {
76 id_type map = game_.getEntityManager().emplaceEntity();
77
78 auto& mappable = game_.getEntityManager().
79 emplaceComponent<MappableComponent>(map,
80 Texture("res/tiles.png"),
81 Texture("res/font.bmp"));
82
83 key = getProp(node, "id");
84 mappable.mapId = atoi(reinterpret_cast<char*>(key));
85 xmlFree(key);
86
87 key = getProp(node, "title");
88 mappable.title = reinterpret_cast<char*>(key);
89 xmlFree(key);
90
91 for (xmlNodePtr mapNode = node->xmlChildrenNode;
92 mapNode != nullptr;
93 mapNode = mapNode->next)
94 {
95 if (!xmlStrcmp(
96 mapNode->name,
97 reinterpret_cast<const xmlChar*>("environment")))
98 {
99 key = xmlNodeGetContent(mapNode);
100 if (key == nullptr)
101 {
102 throw std::invalid_argument("Error parsing world file");
103 }
104
105 mappable.tiles.clear();
106 mappable.tiles.push_back(atoi(strtok(
107 reinterpret_cast<char*>(key),
108 ",\n")));
109
110 for (size_t i = 1; i < (MAP_WIDTH * MAP_HEIGHT); i++)
111 {
112 mappable.tiles.push_back(atoi(strtok(nullptr, ",\n")));
113 }
114
115 xmlFree(key);
116 } else if (!xmlStrcmp(
117 mapNode->name,
118 reinterpret_cast<const xmlChar*>("adjacent")))
119 {
120 key = getProp(mapNode, "type");
121 std::string adjTypeStr(reinterpret_cast<char*>(key));
122 xmlFree(key);
123
124 MappableComponent::Adjacent::Type adjType;
125 if (adjTypeStr == "wall")
126 {
127 adjType = MappableComponent::Adjacent::Type::wall;
128 } else if (adjTypeStr == "wrap")
129 {
130 adjType = MappableComponent::Adjacent::Type::wrap;
131 } else if (adjTypeStr == "warp")
132 {
133 adjType = MappableComponent::Adjacent::Type::warp;
134 } else if (adjTypeStr == "reverseWarp")
135 {
136 adjType = MappableComponent::Adjacent::Type::reverse;
137 } else {
138 throw std::logic_error("Invalid adjacency type");
139 }
140
141 key = getProp(mapNode, "map");
142 size_t adjMapId = atoi(reinterpret_cast<char*>(key));
143 xmlFree(key);
144
145 key = getProp(mapNode, "dir");
146 std::string adjDir(reinterpret_cast<char*>(key));
147 xmlFree(key);
148
149 if (adjDir == "left")
150 {
151 mappable.leftAdjacent = {adjType, adjMapId};
152 } else if (adjDir == "right")
153 {
154 mappable.rightAdjacent = {adjType, adjMapId};
155 } else if (adjDir == "up")
156 {
157 mappable.upAdjacent = {adjType, adjMapId};
158 } else if (adjDir == "down")
159 {
160 mappable.downAdjacent = {adjType, adjMapId};
161 } else {
162 throw std::logic_error("Invalid adjacency direction");
163 }
164 }
165 }
166
167 mapping.generateBoundaries(map);
168
169 realizable.maps.insert(map);
170 realizable.entityByMapId[mappable.mapId] = map;
171 }
172 }
173
174 xmlFreeDoc(doc);
175
176 loadMap(realizable.entityByMapId[realizable.startingMapId]);
177
178 return world;
179}
180
181EntityManager::id_type RealizingSystem::getSingleton() const
182{
183 std::set<id_type> result =
184 game_.getEntityManager().getEntitiesWithComponents<
185 RealizableComponent>();
186
187 if (result.empty())
188 {
189 throw std::logic_error("No realizable entity found");
190 } else if (result.size() > 1)
191 {
192 throw std::logic_error("Multiple realizable entities found");
193 }
194
195 return *std::begin(result);
196}
197
198void RealizingSystem::loadMap(id_type mapEntity)
199{
200 id_type world = getSingleton();
201
202 auto& realizable = game_.getEntityManager().
203 getComponent<RealizableComponent>(world);
204
205 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
206 auto& pondering = game_.getSystemManager().getSystem<PonderingSystem>();
207
208 std::set<id_type> players =
209 game_.getEntityManager().getEntitiesWithComponents<
210 PlayableComponent>();
211
212 if (realizable.hasActiveMap)
213 {
214 id_type oldMap = realizable.activeMap;
215
216 auto& oldMappable = game_.getEntityManager().
217 getComponent<MappableComponent>(oldMap);
218
219 // Deactivate any map objects from the old map.
220 for (id_type prototype : oldMappable.objects)
221 {
222 leaveActiveMap(prototype);
223 }
224
225 // Deactivate players that were on the old map.
226 for (id_type player : players)
227 {
228 auto& playable = game_.getEntityManager().
229 getComponent<PlayableComponent>(player);
230
231 if (playable.mapId == oldMap)
232 {
233 leaveActiveMap(player);
234 }
235 }
236 }
237
238 realizable.hasActiveMap = true;
239 realizable.activeMap = mapEntity;
240
241 auto& mappable = game_.getEntityManager().
242 getComponent<MappableComponent>(mapEntity);
243
244 // Initialize the new map's objects.
245 for (id_type prototype : mappable.objects)
246 {
247 if (game_.getEntityManager().
248 hasComponent<TransformableComponent>(prototype))
249 {
250 auto& transformable = game_.getEntityManager().
251 getComponent<TransformableComponent>(prototype);
252
253 transformable.x = transformable.origX;
254 transformable.y = transformable.origY;
255 transformable.w = transformable.origW;
256 transformable.h = transformable.origH;
257 }
258
259 if (game_.getEntityManager().hasComponent<AnimatableComponent>(prototype))
260 {
261 animating.initPrototype(prototype);
262 }
263
264 if (game_.getEntityManager().hasComponent<PonderableComponent>(prototype))
265 {
266 pondering.initPrototype(prototype);
267 }
268
269 enterActiveMap(prototype);
270 }
271
272 // Activate any players on the map.
273 for (id_type player : players)
274 {
275 auto& playable = game_.getEntityManager().
276 getComponent<PlayableComponent>(player);
277
278 if (playable.mapId == mapEntity)
279 {
280 enterActiveMap(player);
281 }
282 }
283}
284
285void RealizingSystem::enterActiveMap(id_type entity)
286{
287 if (game_.getEntityManager().hasComponent<AnimatableComponent>(entity))
288 {
289 auto& animatable = game_.getEntityManager().
290 getComponent<AnimatableComponent>(entity);
291
292 animatable.active = true;
293 }
294
295 if (game_.getEntityManager().hasComponent<PonderableComponent>(entity))
296 {
297 auto& ponderable = game_.getEntityManager().
298 getComponent<PonderableComponent>(entity);
299
300 ponderable.active = true;
301 }
302}
303
304void RealizingSystem::leaveActiveMap(id_type entity)
305{
306 if (game_.getEntityManager().hasComponent<AnimatableComponent>(entity))
307 {
308 auto& animatable = game_.getEntityManager().
309 getComponent<AnimatableComponent>(entity);
310
311 animatable.active = false;
312 }
313
314 if (game_.getEntityManager().hasComponent<PonderableComponent>(entity))
315 {
316 auto& ponderable = game_.getEntityManager().
317 getComponent<PonderableComponent>(entity);
318
319 ponderable.active = false;
320 }
321}
diff --git a/src/systems/realizing.h b/src/systems/realizing.h new file mode 100644 index 0000000..c681892 --- /dev/null +++ b/src/systems/realizing.h
@@ -0,0 +1,43 @@
1#ifndef REALIZING_H_6853748C
2#define REALIZING_H_6853748C
3
4#include "system.h"
5
6class RealizingSystem : public System {
7public:
8
9 RealizingSystem(Game& game) : System(game)
10 {
11 }
12
13 /**
14 * Creates the singleton realizable entity and initializes it with the
15 * provided world definition.
16 */
17 id_type initSingleton(std::string filename);
18
19 /**
20 * Helper method that returns the entity ID of the (assumed) singleton entity
21 * with a RealizableComponent. Throws an exception if the number of realizable
22 * entities is not exactly one.
23 */
24 id_type getSingleton() const;
25
26 /**
27 * Loads the given map.
28 */
29 void loadMap(id_type mapEntity);
30
31 /**
32 * Treats the given entity as part of the active map.
33 */
34 void enterActiveMap(id_type entity);
35
36 /**
37 * Stops treating the given entity as part of the active map.
38 */
39 void leaveActiveMap(id_type entity);
40
41};
42
43#endif /* end of include guard: REALIZING_H_6853748C */