summary refs log tree commit diff stats
path: root/src/systems
diff options
context:
space:
mode:
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 */