summary refs log tree commit diff stats
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/ai.cpp142
-rw-r--r--src/components/ai.h73
-rw-r--r--src/components/animatable.h62
-rw-r--r--src/components/controllable.h92
-rw-r--r--src/components/map_collision.cpp241
-rw-r--r--src/components/map_collision.h47
-rw-r--r--src/components/map_render.cpp40
-rw-r--r--src/components/map_render.h19
-rw-r--r--src/components/mappable.h146
-rw-r--r--src/components/orientable.h69
-rw-r--r--src/components/physics_body.cpp66
-rw-r--r--src/components/physics_body.h20
-rw-r--r--src/components/player_physics.cpp118
-rw-r--r--src/components/player_physics.h25
-rw-r--r--src/components/player_sprite.cpp60
-rw-r--r--src/components/player_sprite.h23
-rw-r--r--src/components/ponderable.h83
-rw-r--r--src/components/simple_collider.cpp14
-rw-r--r--src/components/simple_collider.h18
-rw-r--r--src/components/static_image.cpp11
-rw-r--r--src/components/static_image.h18
-rw-r--r--src/components/transformable.h69
-rw-r--r--src/components/user_movement.cpp100
-rw-r--r--src/components/user_movement.h19
24 files changed, 521 insertions, 1054 deletions
diff --git a/src/components/ai.cpp b/src/components/ai.cpp deleted file mode 100644 index 9f8c764..0000000 --- a/src/components/ai.cpp +++ /dev/null
@@ -1,142 +0,0 @@
1#include "ai.h"
2#include <cstdlib>
3#include "entity.h"
4
5void AIActionContainer::addAction(std::shared_ptr<AIAction> action)
6{
7 actions.push_back(action);
8}
9
10void AIActionContainer::start(Game& game, Entity& entity)
11{
12 currentAction = begin(actions);
13
14 if (currentAction != end(actions))
15 {
16 (*currentAction)->start(game, entity);
17 }
18}
19
20void AIActionContainer::perform(Game& game, Entity& entity, double dt)
21{
22 if (!isDone())
23 {
24 (*currentAction)->perform(game, entity, dt);
25
26 if ((*currentAction)->isDone())
27 {
28 currentAction++;
29
30 if (!isDone())
31 {
32 (*currentAction)->start(game, entity);
33 }
34 }
35 }
36}
37
38bool AIActionContainer::isDone() const
39{
40 return currentAction == end(actions);
41}
42
43AI::AI(int chance)
44{
45 this->chance = chance;
46}
47
48int AI::getChance() const
49{
50 return chance;
51}
52
53AI& AIComponent::emplaceAI(int chance)
54{
55 maxChance += chance;
56 ais.emplace_back(chance);
57
58 return ais.back();
59}
60
61void AIComponent::tick(Game& game, Entity& entity, double dt)
62{
63 if (currentAI == nullptr)
64 {
65 int toChoose = rand() % maxChance;
66 for (auto& ai : ais)
67 {
68 if (toChoose < ai.getChance())
69 {
70 currentAI = &ai;
71 break;
72 } else {
73 toChoose -= ai.getChance();
74 }
75 }
76
77 if (currentAI != nullptr)
78 {
79 currentAI->start(game, entity);
80 }
81 }
82
83 if (currentAI != nullptr)
84 {
85 currentAI->perform(game, entity, dt);
86
87 if (currentAI->isDone())
88 {
89 currentAI = nullptr;
90 }
91 }
92}
93
94MoveAIAction::MoveAIAction(Direction dir, int len, int speed)
95{
96 this->dir = dir;
97 this->len = len;
98 this->speed = speed;
99}
100
101void MoveAIAction::start(Game& game, Entity& entity)
102{
103 remaining = len;
104}
105
106void MoveAIAction::perform(Game&, Entity& entity, double dt)
107{
108 double dist = dt * speed;
109 remaining -= dist;
110
111 switch (dir)
112 {
113 case Direction::Left:
114 {
115 entity.position.first -= dist;
116 break;
117 }
118
119 case Direction::Right:
120 {
121 entity.position.first += dist;
122 break;
123 }
124
125 case Direction::Up:
126 {
127 entity.position.second -= dist;
128 break;
129 }
130
131 case Direction::Down:
132 {
133 entity.position.second += dist;
134 break;
135 }
136 }
137}
138
139bool MoveAIAction::isDone() const
140{
141 return remaining <= 0.0;
142}
diff --git a/src/components/ai.h b/src/components/ai.h deleted file mode 100644 index 840283b..0000000 --- a/src/components/ai.h +++ /dev/null
@@ -1,73 +0,0 @@
1#ifndef AI_H
2#define AI_H
3
4#include <list>
5#include <map>
6#include <string>
7#include <memory>
8
9#include "entity.h"
10
11class AIAction {
12 public:
13 virtual void start(Game& game, Entity& entity) = 0;
14 virtual void perform(Game& game, Entity& entity, double dt) = 0;
15 virtual bool isDone() const = 0;
16};
17
18class AIActionContainer {
19 public:
20 void addAction(std::shared_ptr<AIAction> action);
21 virtual void start(Game& game, Entity& entity);
22 virtual void perform(Game& game, Entity& entity, double dt);
23 virtual bool isDone() const;
24
25 private:
26 std::list<std::shared_ptr<AIAction>> actions;
27 std::list<std::shared_ptr<AIAction>>::iterator currentAction {end(actions)};
28};
29
30class AI : public AIActionContainer {
31 public:
32 AI(int chance);
33
34 int getChance() const;
35
36 private:
37 int chance;
38};
39
40class AIComponent : public Component {
41 public:
42 AI& emplaceAI(int chance);
43 void tick(Game& game, Entity& entity, double dt);
44
45 private:
46 int maxChance = 0;
47 std::list<AI> ais;
48 AI* currentAI = nullptr;
49};
50
51class MoveAIAction : public AIAction {
52 public:
53 enum class Direction {
54 Left,
55 Right,
56 Up,
57 Down
58 };
59
60 MoveAIAction(Direction dir, int len, int speed);
61
62 void start(Game& game, Entity& entity);
63 void perform(Game& game, Entity& entity, double dt);
64 bool isDone() const;
65
66 private:
67 Direction dir;
68 int len;
69 int speed;
70 double remaining;
71};
72
73#endif /* end of include guard: AI_H */
diff --git a/src/components/animatable.h b/src/components/animatable.h new file mode 100644 index 0000000..ed0133e --- /dev/null +++ b/src/components/animatable.h
@@ -0,0 +1,62 @@
1#ifndef SPRITE_RENDERABLE_H_D3AACBBF
2#define SPRITE_RENDERABLE_H_D3AACBBF
3
4#include "component.h"
5#include "animation.h"
6#include <string>
7
8class AnimatableComponent : public Component {
9public:
10
11 AnimatableComponent(
12 AnimationSet animationSet,
13 std::string animation) :
14 animationSet_(std::move(animationSet)),
15 animation_(std::move(animation))
16 {
17 }
18
19 inline size_t getFrame() const
20 {
21 return frame_;
22 }
23
24 inline void setFrame(size_t v)
25 {
26 frame_ = v;
27 }
28
29 inline size_t getCountdown() const
30 {
31 return countdown_;
32 }
33
34 inline void setCountdown(size_t v)
35 {
36 countdown_ = v;
37 }
38
39 inline const AnimationSet& getAnimationSet() const
40 {
41 return animationSet_;
42 }
43
44 inline const Animation& getAnimation() const
45 {
46 return animationSet_.getAnimation(animation_);
47 }
48
49 inline void setAnimation(std::string animation)
50 {
51 animation_ = std::move(animation);
52 }
53
54private:
55
56 AnimationSet animationSet_;
57 std::string animation_;
58 size_t frame_ = 0;
59 size_t countdown_ = 0;
60};
61
62#endif /* end of include guard: SPRITE_RENDERABLE_H_D3AACBBF */
diff --git a/src/components/controllable.h b/src/components/controllable.h new file mode 100644 index 0000000..fa78c8b --- /dev/null +++ b/src/components/controllable.h
@@ -0,0 +1,92 @@
1#ifndef CONTROLLABLE_H_4E0B85B4
2#define CONTROLLABLE_H_4E0B85B4
3
4#include "component.h"
5#include "renderer.h"
6
7class ControllableComponent : public Component {
8public:
9
10 inline int getLeftKey() const
11 {
12 return leftKey_;
13 }
14
15 inline void setLeftKey(int k)
16 {
17 leftKey_ = k;
18 }
19
20 inline int getRightKey() const
21 {
22 return rightKey_;
23 }
24
25 inline void setRightKey(int k)
26 {
27 rightKey_ = k;
28 }
29
30 inline int getJumpKey() const
31 {
32 return jumpKey_;
33 }
34
35 inline void setJumpKey(int k)
36 {
37 jumpKey_ = k;
38 }
39
40 inline int getDropKey() const
41 {
42 return dropKey_;
43 }
44
45 inline void setDropKey(int k)
46 {
47 dropKey_ = k;
48 }
49
50 inline bool isFrozen() const
51 {
52 return frozen_;
53 }
54
55 inline void setFrozen(bool f)
56 {
57 frozen_ = f;
58 }
59
60 inline bool isHoldingLeft() const
61 {
62 return holdingLeft_;
63 }
64
65 inline void setHoldingLeft(bool f)
66 {
67 holdingLeft_ = f;
68 }
69
70 inline bool isHoldingRight() const
71 {
72 return holdingRight_;
73 }
74
75 inline void setHoldingRight(bool f)
76 {
77 holdingRight_ = f;
78 }
79
80private:
81
82 int leftKey_ = GLFW_KEY_LEFT;
83 int rightKey_ = GLFW_KEY_RIGHT;
84 int jumpKey_ = GLFW_KEY_UP;
85 int dropKey_ = GLFW_KEY_DOWN;
86
87 bool frozen_ = false;
88 bool holdingLeft_ = false;
89 bool holdingRight_ = false;
90};
91
92#endif /* end of include guard: CONTROLLABLE_H_4E0B85B4 */
diff --git a/src/components/map_collision.cpp b/src/components/map_collision.cpp deleted file mode 100644 index 3ad574b..0000000 --- a/src/components/map_collision.cpp +++ /dev/null
@@ -1,241 +0,0 @@
1#include "map_collision.h"
2#include "map.h"
3#include "game.h"
4#include "consts.h"
5
6MapCollisionComponent::MapCollisionComponent(const Map& map) : map(map)
7{
8 addCollision(-6, 0, MAP_HEIGHT*TILE_HEIGHT, Direction::left, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Left).type));
9 addCollision(GAME_WIDTH+6, 0, MAP_HEIGHT*TILE_HEIGHT, Direction::right, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Right).type));
10 addCollision(-6, 0, GAME_WIDTH, Direction::up, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Up).type));
11 addCollision(MAP_HEIGHT*TILE_HEIGHT+6, 0, GAME_WIDTH, Direction::down, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Down).type));
12
13 for (int i=0; i<MAP_WIDTH*MAP_HEIGHT; i++)
14 {
15 int x = i % MAP_WIDTH;
16 int y = i / MAP_WIDTH;
17 int tile = map.getMapdata()[i];
18
19 if ((tile > 0) && (tile < 28) && (!((tile >= 5) && (tile <= 7))))
20 {
21 addCollision(x*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, Direction::right, Collision::Type::wall);
22 addCollision((x+1)*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, Direction::left, Collision::Type::wall);
23 addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::wall);
24 addCollision((y+1)*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::up, Collision::Type::wall);
25 } else if ((tile >= 5) && (tile <= 7))
26 {
27 addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::platform);
28 } else if (tile == 42)
29 {
30 addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::danger);
31 }
32 }
33}
34
35void MapCollisionComponent::addCollision(double axis, double lower, double
36 upper, Direction dir, Collision::Type type)
37{
38 std::list<Collision>::iterator it;
39
40 switch (dir)
41 {
42 case Direction::up:
43 it = up_collisions.begin();
44 for (; it!=up_collisions.end(); it++)
45 {
46 if (it->axis < axis) break;
47 }
48
49 up_collisions.insert(it, {axis, lower, upper, type});
50
51 break;
52 case Direction::down:
53 it = down_collisions.begin();
54 for (; it!=down_collisions.end(); it++)
55 {
56 if (it->axis > axis) break;
57 }
58
59 down_collisions.insert(it, {axis, lower, upper, type});
60
61 break;
62 case Direction::left:
63 it = left_collisions.begin();
64 for (; it!=left_collisions.end(); it++)
65 {
66 if (it->axis < axis) break;
67 }
68
69 left_collisions.insert(it, {axis, lower, upper, type});
70
71 break;
72 case Direction::right:
73 it = right_collisions.begin();
74 for (; it!=right_collisions.end(); it++)
75 {
76 if (it->axis > axis) break;
77 }
78
79 right_collisions.insert(it, {axis, lower, upper, type});
80
81 break;
82 }
83}
84
85void MapCollisionComponent::detectCollision(Game& game, Entity&, Entity& collider, std::pair<double, double> old_position)
86{
87 if (collider.position.first < old_position.first)
88 {
89 for (auto collision : left_collisions)
90 {
91 if (collision.axis > old_position.first) continue;
92 if (collision.axis < collider.position.first) break;
93
94 if ((old_position.second+collider.size.second > collision.lower) && (old_position.second < collision.upper))
95 {
96 // We have a collision!
97 processCollision(game, collider, collision, Direction::left, old_position);
98
99 break;
100 }
101 }
102 } else if (collider.position.first > old_position.first)
103 {
104 for (auto collision : right_collisions)
105 {
106 if (collision.axis < old_position.first+collider.size.first) continue;
107 if (collision.axis > collider.position.first+collider.size.first) break;
108
109 if ((old_position.second+collider.size.second > collision.lower) && (old_position.second < collision.upper))
110 {
111 // We have a collision!
112 processCollision(game, collider, collision, Direction::right, old_position);
113
114 break;
115 }
116 }
117 }
118
119 if (collider.position.second < old_position.second)
120 {
121 for (auto collision : up_collisions)
122 {
123 if (collision.axis > old_position.second) continue;
124 if (collision.axis < collider.position.second) break;
125
126 if ((collider.position.first+collider.size.first > collision.lower) && (collider.position.first < collision.upper))
127 {
128 // We have a collision!
129 processCollision(game, collider, collision, Direction::up, old_position);
130
131 break;
132 }
133 }
134 } else if (collider.position.second > old_position.second)
135 {
136 for (auto collision : down_collisions)
137 {
138 if (collision.axis < old_position.second+collider.size.second) continue;
139 if (collision.axis > collider.position.second+collider.size.second) break;
140
141 if ((collider.position.first+collider.size.first > collision.lower) && (collider.position.first < collision.upper))
142 {
143 // We have a collision!
144 processCollision(game, collider, collision, Direction::down, old_position);
145
146 break;
147 }
148 }
149 }
150}
151
152void MapCollisionComponent::processCollision(Game& game, Entity& collider, Collision collision, Direction dir, std::pair<double, double> old_position)
153{
154 if (collision.type == Collision::Type::wall)
155 {
156 if (dir == Direction::left)
157 {
158 collider.position.first = collision.axis;
159
160 Message msg(Message::Type::setHorizontalVelocity);
161 msg.velocity = 0.0;
162 collider.send(game, msg);
163 } else if (dir == Direction::right)
164 {
165 collider.position.first = collision.axis - collider.size.first;
166
167 Message msg(Message::Type::setHorizontalVelocity);
168 msg.velocity = 0.0;
169 collider.send(game, msg);
170 } else if (dir == Direction::up)
171 {
172 collider.position.second = collision.axis;
173
174 Message msg(Message::Type::setVerticalVelocity);
175 msg.velocity = 0.0;
176 collider.send(game, msg);
177 } else if (dir == Direction::down)
178 {
179 collider.position.second = collision.axis - collider.size.second;
180 collider.send(game, Message::Type::hitTheGround);
181 }
182 } else if (collision.type == Collision::Type::wrap)
183 {
184 if (dir == Direction::left)
185 {
186 collider.position.first = GAME_WIDTH-collider.size.first/2;
187 } else if (dir == Direction::right)
188 {
189 collider.position.first = -collider.size.first/2;
190 } else if (dir == Direction::up)
191 {
192 collider.position.second = GAME_HEIGHT-collider.size.second/2-1;
193 } else if (dir == Direction::down)
194 {
195 collider.position.second = -collider.size.second/2;
196 }
197 } else if (collision.type == Collision::Type::teleport)
198 {
199 if (dir == Direction::left)
200 {
201 game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Left).map), std::make_pair(GAME_WIDTH-collider.size.first/2, old_position.second));
202 } else if (dir == Direction::right)
203 {
204 game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Right).map), std::make_pair(-collider.size.first/2, old_position.second));
205 } else if (dir == Direction::up)
206 {
207 game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Up).map), std::make_pair(old_position.first, MAP_HEIGHT*TILE_HEIGHT-collider.size.second/2));
208 } else if (dir == Direction::down)
209 {
210 game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Down).map), std::make_pair(old_position.first, -collider.size.second/2));
211 }
212 } else if (collision.type == Collision::Type::reverse)
213 {
214 // TODO reverse
215 if (dir == Direction::right)
216 {
217 collider.position.first = collision.axis - collider.size.first;
218 collider.send(game, Message::Type::walkLeft);
219 }
220 } else if (collision.type == Collision::Type::platform)
221 {
222 Message msg(Message::Type::drop);
223 msg.dropAxis = collision.axis;
224
225 collider.send(game, msg);
226 } else if (collision.type == Collision::Type::danger)
227 {
228 game.playerDie();
229 }
230}
231
232MapCollisionComponent::Collision::Type MapCollisionComponent::collisionFromMoveType(Map::MoveType type)
233{
234 switch (type)
235 {
236 case Map::MoveType::Wall: return Collision::Type::wall;
237 case Map::MoveType::Wrap: return Collision::Type::wrap;
238 case Map::MoveType::Warp: return Collision::Type::teleport;
239 case Map::MoveType::ReverseWarp: return Collision::Type::reverse;
240 }
241}
diff --git a/src/components/map_collision.h b/src/components/map_collision.h deleted file mode 100644 index 18b9397..0000000 --- a/src/components/map_collision.h +++ /dev/null
@@ -1,47 +0,0 @@
1#ifndef MAP_COLLISION_H
2#define MAP_COLLISION_H
3
4#include "entity.h"
5#include "map.h"
6#include <list>
7
8class Game;
9
10class MapCollisionComponent : public Component {
11 public:
12 MapCollisionComponent(const Map& map);
13 void detectCollision(Game& game, Entity& entity, Entity& collider, std::pair<double, double> old_position);
14
15 private:
16 enum class Direction {
17 up, left, down, right
18 };
19
20 struct Collision {
21 enum class Type {
22 wall,
23 wrap,
24 teleport,
25 reverse,
26 platform,
27 danger
28 };
29
30 double axis;
31 double lower;
32 double upper;
33 Type type;
34 };
35
36 void addCollision(double axis, double lower, double upper, Direction dir, Collision::Type type);
37 void processCollision(Game& game, Entity& collider, Collision collision, Direction dir, std::pair<double, double> old_position);
38 Collision::Type collisionFromMoveType(Map::MoveType type);
39
40 std::list<Collision> left_collisions;
41 std::list<Collision> right_collisions;
42 std::list<Collision> up_collisions;
43 std::list<Collision> down_collisions;
44 const Map& map;
45};
46
47#endif
diff --git a/src/components/map_render.cpp b/src/components/map_render.cpp deleted file mode 100644 index 45766e1..0000000 --- a/src/components/map_render.cpp +++ /dev/null
@@ -1,40 +0,0 @@
1#include "map_render.h"
2#include "map.h"
3#include "game.h"
4#include "consts.h"
5
6MapRenderComponent::MapRenderComponent(const Map& map) : screen(GAME_WIDTH, GAME_HEIGHT)
7{
8 screen.fill(screen.entirety(), 0, 0, 0);
9
10 Texture tiles("res/tiles.png");
11
12 for (int i=0; i<MAP_WIDTH*MAP_HEIGHT; i++)
13 {
14 int tile = map.getMapdata()[i];
15 int x = i % MAP_WIDTH;
16 int y = i / MAP_WIDTH;
17 Rectangle dst {x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT};
18 Rectangle src {tile%8*TILE_WIDTH, tile/8*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT};
19
20 if (tile > 0)
21 {
22 screen.blit(tiles, src, dst);
23 }
24 }
25
26 Texture font("res/font.bmp");
27 std::string map_name = map.getTitle();
28 int start_x = (40/2) - (map_name.length()/2);
29 for (size_t i=0; i<map_name.length(); i++)
30 {
31 Rectangle srcRect {map_name[i] % 16 * 8, map_name[i] / 16 * 8, 8, 8};
32 Rectangle dstRect {(start_x + (int)i)*8, 24*8, 8, 8};
33 screen.blit(font, srcRect, dstRect);
34 }
35}
36
37void MapRenderComponent::render(Game&, Entity&, Texture& buffer)
38{
39 buffer.blit(screen, screen.entirety(), buffer.entirety());
40}
diff --git a/src/components/map_render.h b/src/components/map_render.h deleted file mode 100644 index a232aa6..0000000 --- a/src/components/map_render.h +++ /dev/null
@@ -1,19 +0,0 @@
1#ifndef MAP_RENDER_H
2#define MAP_RENDER_H
3
4#include "entity.h"
5#include "renderer.h"
6
7class Map;
8class Game;
9
10class MapRenderComponent : public Component {
11 public:
12 MapRenderComponent(const Map& map);
13 void render(Game& game, Entity& entity, Texture& buffer);
14
15 private:
16 Texture screen;
17};
18
19#endif
diff --git a/src/components/mappable.h b/src/components/mappable.h new file mode 100644 index 0000000..7530919 --- /dev/null +++ b/src/components/mappable.h
@@ -0,0 +1,146 @@
1#ifndef MAPPABLE_H_0B0316FB
2#define MAPPABLE_H_0B0316FB
3
4#include <map>
5#include "component.h"
6#include "renderer.h"
7#include "map.h"
8
9class MappableComponent : public Component {
10public:
11
12 class Boundary {
13 public:
14
15 enum class Type {
16 wall,
17 wrap,
18 teleport,
19 reverse,
20 platform,
21 danger
22 };
23
24 Boundary(
25 double axis,
26 double lower,
27 double upper,
28 Type type) :
29 axis_(axis),
30 lower_(lower),
31 upper_(upper),
32 type_(type)
33 {
34 }
35
36 inline double getAxis() const
37 {
38 return axis_;
39 }
40
41 inline double getLower() const
42 {
43 return lower_;
44 }
45
46 inline double getUpper() const
47 {
48 return upper_;
49 }
50
51 inline Type getType() const
52 {
53 return type_;
54 }
55
56 private:
57
58 double axis_;
59 double lower_;
60 double upper_;
61 Type type_;
62 };
63
64 MappableComponent(
65 Texture tileset,
66 Texture font) :
67 tileset_(std::move(tileset)),
68 font_(std::move(font))
69 {
70 }
71
72 using asc_boundaries_type =
73 std::multimap<
74 double,
75 Boundary,
76 std::less<double>>;
77
78 using desc_boundaries_type =
79 std::multimap<
80 double,
81 Boundary,
82 std::greater<double>>;
83
84 inline size_t getMapId() const
85 {
86 return mapId_;
87 }
88
89 inline void setMapId(size_t v)
90 {
91 mapId_ = v;
92 }
93
94 inline desc_boundaries_type& getLeftBoundaries()
95 {
96 return leftBoundaries_;
97 }
98
99 inline asc_boundaries_type& getRightBoundaries()
100 {
101 return rightBoundaries_;
102 }
103
104 inline desc_boundaries_type& getUpBoundaries()
105 {
106 return upBoundaries_;
107 }
108
109 inline asc_boundaries_type& getDownBoundaries()
110 {
111 return downBoundaries_;
112 }
113
114 inline const Texture& getTileset() const
115 {
116 return tileset_;
117 }
118
119 inline void setTileset(Texture v)
120 {
121 tileset_ = std::move(v);
122 }
123
124 inline const Texture& getFont() const
125 {
126 return font_;
127 }
128
129 inline void setFont(Texture v)
130 {
131 font_ = std::move(v);
132 }
133
134private:
135
136 size_t mapId_ = -1;
137
138 desc_boundaries_type leftBoundaries_;
139 asc_boundaries_type rightBoundaries_;
140 desc_boundaries_type upBoundaries_;
141 asc_boundaries_type downBoundaries_;
142 Texture tileset_;
143 Texture font_;
144};
145
146#endif /* end of include guard: MAPPABLE_H_0B0316FB */
diff --git a/src/components/orientable.h b/src/components/orientable.h new file mode 100644 index 0000000..e356b78 --- /dev/null +++ b/src/components/orientable.h
@@ -0,0 +1,69 @@
1#ifndef ORIENTABLE_H_EDB6C4A1
2#define ORIENTABLE_H_EDB6C4A1
3
4#include "component.h"
5
6class OrientableComponent : public Component {
7public:
8
9 enum class WalkState {
10 still,
11 left,
12 right
13 };
14
15 enum class DropState {
16 none,
17 ready,
18 active
19 };
20
21 inline bool isFacingRight() const
22 {
23 return facingRight_;
24 }
25
26 inline void setFacingRight(bool v)
27 {
28 facingRight_ = v;
29 }
30
31 inline WalkState getWalkState() const
32 {
33 return walkState_;
34 }
35
36 inline void setWalkState(WalkState v)
37 {
38 walkState_ = v;
39 }
40
41 inline bool isJumping() const
42 {
43 return jumping_;
44 }
45
46 inline void setJumping(bool v)
47 {
48 jumping_ = v;
49 }
50
51 inline DropState getDropState() const
52 {
53 return dropState_;
54 }
55
56 inline void setDropState(DropState v)
57 {
58 dropState_ = v;
59 }
60
61private:
62
63 bool facingRight_ = false;
64 WalkState walkState_ = WalkState::still;
65 bool jumping_ = false;
66 DropState dropState_ = DropState::none;
67};
68
69#endif /* end of include guard: ORIENTABLE_H_EDB6C4A1 */
diff --git a/src/components/physics_body.cpp b/src/components/physics_body.cpp deleted file mode 100644 index 97394d1..0000000 --- a/src/components/physics_body.cpp +++ /dev/null
@@ -1,66 +0,0 @@
1#include "physics_body.h"
2#include "game.h"
3#include "consts.h"
4
5void PhysicsBodyComponent::receive(Game&, Entity&, const Message& msg)
6{
7 if (msg.type == Message::Type::walkLeft)
8 {
9 velocity.first = -90;
10 } else if (msg.type == Message::Type::walkRight)
11 {
12 velocity.first = 90;
13 } else if (msg.type == Message::Type::stopWalking)
14 {
15 velocity.first = 0.0;
16 } else if (msg.type == Message::Type::setHorizontalVelocity)
17 {
18 velocity.first = msg.velocity;
19 } else if (msg.type == Message::Type::setVerticalVelocity)
20 {
21 velocity.second = msg.velocity;
22 }
23}
24
25void PhysicsBodyComponent::tick(Game&, Entity& entity, double dt)
26{
27 // Accelerate
28 velocity.first += accel.first * dt;
29 velocity.second += accel.second * dt;
30
31 // Terminal velocity
32#define TERMINAL_VELOCITY_X (2 * TILE_WIDTH * FRAMES_PER_SECOND)
33#define TERMINAL_VELOCITY_Y (2 * TILE_HEIGHT * FRAMES_PER_SECOND)
34 if (velocity.first < -TERMINAL_VELOCITY_X) velocity.first = -TERMINAL_VELOCITY_X;
35 if (velocity.first > TERMINAL_VELOCITY_X) velocity.first = TERMINAL_VELOCITY_X;
36 if (velocity.second < -TERMINAL_VELOCITY_Y) velocity.second = -TERMINAL_VELOCITY_Y;
37 if (velocity.second > TERMINAL_VELOCITY_Y) velocity.second = TERMINAL_VELOCITY_Y;
38
39 // Do the movement
40 entity.position.first += velocity.first * dt;
41 entity.position.second += velocity.second * dt;
42}
43
44void PhysicsBodyComponent::detectCollision(Game& game, Entity& entity, Entity& collider, std::pair<double, double> old_position)
45{
46 // If already colliding, do nothing!
47 if ((old_position.first + collider.size.first > entity.position.first)
48 && (old_position.first < entity.position.first + entity.size.first)
49 && (old_position.second + collider.size.second > entity.position.second)
50 && (old_position.second < entity.position.second + entity.size.second))
51 {
52 return;
53 }
54
55 // If newly colliding, SHOCK AND HORROR!
56 if ((collider.position.first + collider.size.first > entity.position.first)
57 && (collider.position.first < entity.position.first + entity.size.first)
58 && (collider.position.second + collider.size.second > entity.position.second)
59 && (collider.position.second < entity.position.second + entity.size.second))
60 {
61 Message msg(Message::Type::collision);
62 msg.collisionEntity = &collider;
63
64 entity.send(game, msg);
65 }
66}
diff --git a/src/components/physics_body.h b/src/components/physics_body.h deleted file mode 100644 index 079cc51..0000000 --- a/src/components/physics_body.h +++ /dev/null
@@ -1,20 +0,0 @@
1#ifndef PHYSICS_BODY_H
2#define PHYSICS_BODY_H
3
4#include "entity.h"
5#include <utility>
6
7class Game;
8
9class PhysicsBodyComponent : public Component {
10 public:
11 void receive(Game& game, Entity& entity, const Message& msg);
12 void tick(Game& game, Entity& entity, double dt);
13 void detectCollision(Game& game, Entity& entity, Entity& collider, std::pair<double, double> old_position);
14
15 protected:
16 std::pair<double, double> velocity;
17 std::pair<double, double> accel;
18};
19
20#endif
diff --git a/src/components/player_physics.cpp b/src/components/player_physics.cpp deleted file mode 100644 index 40e9948..0000000 --- a/src/components/player_physics.cpp +++ /dev/null
@@ -1,118 +0,0 @@
1#include "player_physics.h"
2#include "muxer.h"
3#include "game.h"
4#include "consts.h"
5
6#define JUMP_VELOCITY(h, l) (-2 * (h) / (l))
7#define JUMP_GRAVITY(h, l) (2 * ((h) / (l)) / (l))
8
9PlayerPhysicsComponent::PlayerPhysicsComponent()
10{
11 jump_velocity = JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3);
12 jump_gravity = JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3);
13 jump_gravity_short = JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233);
14
15 accel.second = jump_gravity_short;
16}
17
18void PlayerPhysicsComponent::receive(Game&, Entity& entity, const Message& msg)
19{
20 if (msg.type == Message::Type::walkLeft)
21 {
22 velocity.first = -90;
23 direction = -1;
24 } else if (msg.type == Message::Type::walkRight)
25 {
26 velocity.first = 90;
27 direction = 1;
28 } else if (msg.type == Message::Type::stopWalking)
29 {
30 velocity.first = 0.0;
31 direction = 0;
32 } else if (msg.type == Message::Type::setHorizontalVelocity)
33 {
34 velocity.first = msg.velocity;
35 } else if (msg.type == Message::Type::setVerticalVelocity)
36 {
37 velocity.second = msg.velocity;
38 } else if (msg.type == Message::Type::hitTheGround)
39 {
40 if (isFalling)
41 {
42 playSound("res/Randomize27.wav", 0.05);
43 isFalling = false;
44 }
45
46 velocity.second = 0.0;
47 } else if (msg.type == Message::Type::jump)
48 {
49 playSound("res/Randomize87.wav", 0.25);
50
51 velocity.second = jump_velocity;
52 accel.second = jump_gravity;
53 } else if (msg.type == Message::Type::stopJump)
54 {
55 accel.second = jump_gravity_short;
56 } else if (msg.type == Message::Type::canDrop)
57 {
58 canDrop = true;
59 } else if (msg.type == Message::Type::cantDrop)
60 {
61 canDrop = false;
62 } else if (msg.type == Message::Type::drop)
63 {
64 if (canDrop)
65 {
66 canDrop = false;
67 } else {
68 entity.position.second = msg.dropAxis - entity.size.second;
69 velocity.second = 0;
70 }
71 } else if (msg.type == Message::Type::die)
72 {
73 frozen = true;
74 } else if (msg.type == Message::Type::stopDying)
75 {
76 frozen = false;
77 }
78}
79
80void PlayerPhysicsComponent::tick(Game& game, Entity& entity, double dt)
81{
82 // If frozen, do nothing
83 if (frozen)
84 {
85 return;
86 }
87
88 // Continue walking even if blocked earlier
89 if (velocity.first == 0)
90 {
91 if (direction < 0)
92 {
93 velocity.first = -90;
94 } else if (direction > 0)
95 {
96 velocity.first = 90;
97 }
98 }
99
100 // Increase gravity at the height of jump
101 if ((accel.second == jump_gravity) && (velocity.second >= 0))
102 {
103 accel.second = jump_gravity_short;
104 }
105
106 // Do the movement
107 std::pair<double, double> old_position = entity.position;
108 PhysicsBodyComponent::tick(game, entity, dt);
109
110 // Check for collisions
111 game.detectCollision(entity, old_position);
112
113 // Are we moving due to gravity?
114 if (velocity.second != 0.0)
115 {
116 isFalling = true;
117 }
118}
diff --git a/src/components/player_physics.h b/src/components/player_physics.h deleted file mode 100644 index 26f1fae..0000000 --- a/src/components/player_physics.h +++ /dev/null
@@ -1,25 +0,0 @@
1#ifndef PLAYER_PHYSICS_H
2#define PLAYER_PHYSICS_H
3
4#include "entity.h"
5#include "physics_body.h"
6
7class Game;
8
9class PlayerPhysicsComponent : public PhysicsBodyComponent {
10 public:
11 PlayerPhysicsComponent();
12 void tick(Game& game, Entity& entity, double dt);
13 void receive(Game& game, Entity& entity, const Message& msg);
14
15 private:
16 double jump_velocity;
17 double jump_gravity;
18 double jump_gravity_short;
19 int direction = 0;
20 bool canDrop = false;
21 bool frozen = false;
22 bool isFalling = false;
23};
24
25#endif
diff --git a/src/components/player_sprite.cpp b/src/components/player_sprite.cpp deleted file mode 100644 index 452a940..0000000 --- a/src/components/player_sprite.cpp +++ /dev/null
@@ -1,60 +0,0 @@
1#include "player_sprite.h"
2
3PlayerSpriteComponent::PlayerSpriteComponent() : sprite("res/Starla.png")
4{
5
6}
7
8void PlayerSpriteComponent::render(Game&, Entity& entity, Texture& buffer)
9{
10 animFrame++;
11
12 int frame = 0;
13 if (isMoving)
14 {
15 frame += 2;
16
17 if (animFrame % 20 < 10)
18 {
19 frame += 2;
20 }
21 }
22
23 if (facingLeft)
24 {
25 frame++;
26 }
27
28 double alpha = 1.0;
29 if (dying && (animFrame % 4 < 2))
30 {
31 alpha = 0.0;
32 }
33
34 Rectangle src_rect {frame*10, 0, 10, 12};
35 Rectangle dst_rect {(int) entity.position.first, (int) entity.position.second, entity.size.first, entity.size.second};
36 buffer.blit(sprite, src_rect, dst_rect, alpha);
37}
38
39void PlayerSpriteComponent::receive(Game&, Entity&, const Message& msg)
40{
41 if (msg.type == Message::Type::walkLeft)
42 {
43 facingLeft = true;
44 isMoving = true;
45 } else if (msg.type == Message::Type::walkRight)
46 {
47 facingLeft = false;
48 isMoving = true;
49 } else if (msg.type == Message::Type::stopWalking)
50 {
51 isMoving = false;
52 } else if (msg.type == Message::Type::die)
53 {
54 dying = true;
55 isMoving = false;
56 } else if (msg.type == Message::Type::stopDying)
57 {
58 dying = false;
59 }
60}
diff --git a/src/components/player_sprite.h b/src/components/player_sprite.h deleted file mode 100644 index b1ac0af..0000000 --- a/src/components/player_sprite.h +++ /dev/null
@@ -1,23 +0,0 @@
1#ifndef PLAYER_SPRITE_H
2#define PLAYER_SPRITE_H
3
4#include "entity.h"
5#include "renderer.h"
6
7class Game;
8
9class PlayerSpriteComponent : public Component {
10 public:
11 PlayerSpriteComponent();
12 void render(Game& game, Entity& entity, Texture& buffer);
13 void receive(Game& game, Entity& entity, const Message& msg);
14
15 private:
16 Texture sprite;
17 int animFrame = 0;
18 bool facingLeft = false;
19 bool isMoving = false;
20 bool dying = false;
21};
22
23#endif
diff --git a/src/components/ponderable.h b/src/components/ponderable.h new file mode 100644 index 0000000..e21cbab --- /dev/null +++ b/src/components/ponderable.h
@@ -0,0 +1,83 @@
1#ifndef TANGIBLE_H_746DB3EE
2#define TANGIBLE_H_746DB3EE
3
4#include "component.h"
5
6class PonderableComponent : public Component {
7public:
8
9 enum class Type {
10 vacuumed,
11 freefalling
12 };
13
14 PonderableComponent(Type type) : type_(type)
15 {
16 }
17
18 inline Type getType() const
19 {
20 return type_;
21 }
22
23 inline double getVelocityX() const
24 {
25 return velX_;
26 }
27
28 inline void setVelocityX(double v)
29 {
30 velX_ = v;
31 }
32
33 inline double getVelocityY() const
34 {
35 return velY_;
36 }
37
38 inline void setVelocityY(double v)
39 {
40 velY_ = v;
41 }
42
43 inline double getAccelX() const
44 {
45 return accelX_;
46 }
47
48 inline void setAccelX(double v)
49 {
50 accelX_ = v;
51 }
52
53 inline double getAccelY() const
54 {
55 return accelY_;
56 }
57
58 inline void setAccelY(double v)
59 {
60 accelY_ = v;
61 }
62
63 inline bool isGrounded() const
64 {
65 return grounded_;
66 }
67
68 inline void setGrounded(bool v)
69 {
70 grounded_ = v;
71 }
72
73private:
74
75 double velX_ = 0.0;
76 double velY_ = 0.0;
77 double accelX_ = 0.0;
78 double accelY_ = 0.0;
79 Type type_ = Type::vacuumed;
80 bool grounded_ = false;
81};
82
83#endif /* end of include guard: TANGIBLE_H_746DB3EE */
diff --git a/src/components/simple_collider.cpp b/src/components/simple_collider.cpp deleted file mode 100644 index f4b414e..0000000 --- a/src/components/simple_collider.cpp +++ /dev/null
@@ -1,14 +0,0 @@
1#include "simple_collider.h"
2
3SimpleColliderComponent::SimpleColliderComponent(std::function<void (Game& game, Entity& collider)> callback) : callback(callback)
4{
5
6}
7
8void SimpleColliderComponent::receive(Game& game, Entity&, const Message& msg)
9{
10 if (msg.type == Message::Type::collision)
11 {
12 callback(game, *msg.collisionEntity);
13 }
14}
diff --git a/src/components/simple_collider.h b/src/components/simple_collider.h deleted file mode 100644 index 15d78cf..0000000 --- a/src/components/simple_collider.h +++ /dev/null
@@ -1,18 +0,0 @@
1#ifndef SIMPLE_COLLIDER_H
2#define SIMPLE_COLLIDER_H
3
4#include "entity.h"
5#include <functional>
6
7class Game;
8
9class SimpleColliderComponent : public Component {
10 public:
11 SimpleColliderComponent(std::function<void (Game& game, Entity& collider)> callback);
12 void receive(Game& game, Entity& entity, const Message& msg);
13
14 private:
15 std::function<void (Game& game, Entity& collider)> callback;
16};
17
18#endif
diff --git a/src/components/static_image.cpp b/src/components/static_image.cpp deleted file mode 100644 index 9fa8dca..0000000 --- a/src/components/static_image.cpp +++ /dev/null
@@ -1,11 +0,0 @@
1#include "static_image.h"
2
3StaticImageComponent::StaticImageComponent(const char* filename) : sprite(Texture(filename))
4{
5
6}
7
8void StaticImageComponent::render(Game&, Entity& entity, Texture& buffer)
9{
10 buffer.blit(sprite, sprite.entirety(), {(int) entity.position.first, (int) entity.position.second, entity.size.first, entity.size.second});
11}
diff --git a/src/components/static_image.h b/src/components/static_image.h deleted file mode 100644 index 2dec78b..0000000 --- a/src/components/static_image.h +++ /dev/null
@@ -1,18 +0,0 @@
1#ifndef STATIC_IMAGE_H
2#define STATIC_IMAGE_H
3
4#include "entity.h"
5#include "renderer.h"
6
7class Game;
8
9class StaticImageComponent : public Component {
10 public:
11 StaticImageComponent(const char* filename);
12 void render(Game& game, Entity& entity, Texture& buffer);
13
14 private:
15 Texture sprite;
16};
17
18#endif
diff --git a/src/components/transformable.h b/src/components/transformable.h new file mode 100644 index 0000000..6ed2637 --- /dev/null +++ b/src/components/transformable.h
@@ -0,0 +1,69 @@
1#ifndef LOCATABLE_H_39E526CA
2#define LOCATABLE_H_39E526CA
3
4#include "component.h"
5
6class TransformableComponent : public Component {
7public:
8
9 TransformableComponent(
10 double x,
11 double y,
12 int w,
13 int h) :
14 x_(x),
15 y_(y),
16 w_(w),
17 h_(h)
18 {
19 }
20
21 inline double getX() const
22 {
23 return x_;
24 }
25
26 inline void setX(double v)
27 {
28 x_ = v;
29 }
30
31 inline double getY() const
32 {
33 return y_;
34 }
35
36 inline void setY(double v)
37 {
38 y_ = v;
39 }
40
41 inline int getW() const
42 {
43 return w_;
44 }
45
46 inline void setW(int v)
47 {
48 w_ = v;
49 }
50
51 inline int getH() const
52 {
53 return h_;
54 }
55
56 inline void setH(int v)
57 {
58 h_ = v;
59 }
60
61private:
62
63 double x_;
64 double y_;
65 int w_;
66 int h_;
67};
68
69#endif /* end of include guard: LOCATABLE_H_39E526CA */
diff --git a/src/components/user_movement.cpp b/src/components/user_movement.cpp deleted file mode 100644 index e499fee..0000000 --- a/src/components/user_movement.cpp +++ /dev/null
@@ -1,100 +0,0 @@
1#include "user_movement.h"
2#include "renderer.h"
3
4void UserMovementComponent::input(Game& game, Entity& entity, int key, int action)
5{
6 if (action == GLFW_PRESS)
7 {
8 if (key == GLFW_KEY_LEFT)
9 {
10 holdingLeft = true;
11
12 if (!frozen)
13 {
14 entity.send(game, Message::Type::walkLeft);
15 }
16 } else if (key == GLFW_KEY_RIGHT)
17 {
18 holdingRight = true;
19
20 if (!frozen)
21 {
22 entity.send(game, Message::Type::walkRight);
23 }
24 } else if (key == GLFW_KEY_UP)
25 {
26 if (!frozen)
27 {
28 entity.send(game, Message::Type::jump);
29 }
30 } else if (key == GLFW_KEY_DOWN)
31 {
32 if (!frozen)
33 {
34 entity.send(game, Message::Type::canDrop);
35 }
36 }
37 } else if (action == GLFW_RELEASE)
38 {
39 if (key == GLFW_KEY_LEFT)
40 {
41 holdingLeft = false;
42
43 if (!frozen)
44 {
45 if (holdingRight)
46 {
47 entity.send(game, Message::Type::walkRight);
48 } else {
49 entity.send(game, Message::Type::stopWalking);
50 }
51 }
52 } else if (key == GLFW_KEY_RIGHT)
53 {
54 holdingRight = false;
55
56 if (!frozen)
57 {
58 if (holdingLeft)
59 {
60 entity.send(game, Message::Type::walkLeft);
61 } else {
62 entity.send(game, Message::Type::stopWalking);
63 }
64 }
65 } else if (key == GLFW_KEY_DOWN)
66 {
67 if (!frozen)
68 {
69 entity.send(game, Message::Type::cantDrop);
70 }
71 } else if (key == GLFW_KEY_UP)
72 {
73 if (!frozen)
74 {
75 entity.send(game, Message::Type::stopJump);
76 }
77 }
78 }
79}
80
81void UserMovementComponent::receive(Game& game, Entity& entity, const Message& msg)
82{
83 if (msg.type == Message::Type::die)
84 {
85 frozen = true;
86
87 entity.send(game, Message::Type::stopWalking);
88 } else if (msg.type == Message::Type::stopDying)
89 {
90 frozen = false;
91
92 if (holdingLeft)
93 {
94 entity.send(game, Message::Type::walkLeft);
95 } else if (holdingRight)
96 {
97 entity.send(game, Message::Type::walkRight);
98 }
99 }
100}
diff --git a/src/components/user_movement.h b/src/components/user_movement.h deleted file mode 100644 index 1bcf05e..0000000 --- a/src/components/user_movement.h +++ /dev/null
@@ -1,19 +0,0 @@
1#ifndef USER_MOVEMENT_H
2#define USER_MOVEMENT_H
3
4#include "entity.h"
5
6class Game;
7
8class UserMovementComponent : public Component {
9 public:
10 void input(Game& game, Entity& entity, int key, int action);
11 void receive(Game&, Entity&, const Message& msg);
12
13 private:
14 bool holdingLeft = false;
15 bool holdingRight = false;
16 bool frozen = false;
17};
18
19#endif