summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/collision.cpp97
-rw-r--r--src/collision.h81
-rw-r--r--src/components/mappable.h10
-rw-r--r--src/components/playable.h15
-rw-r--r--src/consts.h2
-rw-r--r--src/entity_manager.h10
-rw-r--r--src/game.cpp27
-rw-r--r--src/map.h70
-rw-r--r--src/systems/mapping.cpp28
-rw-r--r--src/systems/playing.cpp98
-rw-r--r--src/systems/playing.h21
-rw-r--r--src/systems/pondering.cpp347
-rw-r--r--src/systems/pondering.h11
-rw-r--r--src/world.cpp58
15 files changed, 717 insertions, 160 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e7bcb8..155063e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(Aromatherapy
55 src/animation.cpp 55 src/animation.cpp
56 src/world.cpp 56 src/world.cpp
57 src/util.cpp 57 src/util.cpp
58 src/collision.cpp
58 src/renderer/renderer.cpp 59 src/renderer/renderer.cpp
59 src/renderer/mesh.cpp 60 src/renderer/mesh.cpp
60 src/renderer/shader.cpp 61 src/renderer/shader.cpp
@@ -64,6 +65,7 @@ add_executable(Aromatherapy
64 src/systems/animating.cpp 65 src/systems/animating.cpp
65 src/systems/mapping.cpp 66 src/systems/mapping.cpp
66 src/systems/orienting.cpp 67 src/systems/orienting.cpp
68 src/systems/playing.cpp
67) 69)
68 70
69set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 11) 71set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 11)
diff --git a/src/collision.cpp b/src/collision.cpp new file mode 100644 index 0000000..b747a90 --- /dev/null +++ b/src/collision.cpp
@@ -0,0 +1,97 @@
1#include "collision.h"
2
3bool Collision::operator<(const Collision& other) const
4{
5 // Most important is the type of collision
6 if (type_ != other.type_)
7 {
8 return (static_cast<int>(type_) > static_cast<int>(other.type_));
9 }
10
11 // Next, categorize the collisions arbitrarily based on direction
12 if (dir_ != other.dir_)
13 {
14 return (static_cast<int>(dir_) < static_cast<int>(other.dir_));
15 }
16
17 // We want to process closer collisions first
18 if (axis_ != other.axis_)
19 {
20 switch (dir_)
21 {
22 case Direction::left:
23 case Direction::up:
24 {
25 return (axis_ < other.axis_);
26 }
27
28 case Direction::right:
29 case Direction::down:
30 {
31 return (axis_ > other.axis_);
32 }
33 }
34 }
35
36 // Order the remaining attributes arbitrarily
37 return std::tie(collider_, lower_, upper_) <
38 std::tie(other.collider_, other.lower_, other.upper_);
39}
40
41bool Collision::isColliding(
42 double x,
43 double y,
44 int w,
45 int h) const
46{
47 int right = x + w;
48 int bottom = y + h;
49
50 switch (dir_)
51 {
52 case Direction::left:
53 case Direction::right:
54 {
55 if (!((bottom > lower_) && (y < upper_)))
56 {
57 return false;
58 }
59
60 break;
61 }
62
63 case Direction::up:
64 case Direction::down:
65 {
66 if (!((right > lower_) && (x < upper_)))
67 {
68 return false;
69 }
70
71 break;
72 }
73 }
74
75 switch (dir_)
76 {
77 case Direction::left:
78 {
79 return (axis_ >= x);
80 }
81
82 case Direction::right:
83 {
84 return (axis_ <= right);
85 }
86
87 case Direction::up:
88 {
89 return (axis_ >= y);
90 }
91
92 case Direction::down:
93 {
94 return (axis_ <= bottom);
95 }
96 }
97}
diff --git a/src/collision.h b/src/collision.h new file mode 100644 index 0000000..e5371f8 --- /dev/null +++ b/src/collision.h
@@ -0,0 +1,81 @@
1#ifndef COLLISION_H_53D84877
2#define COLLISION_H_53D84877
3
4#include "entity_manager.h"
5#include "direction.h"
6
7class Collision {
8public:
9
10 using id_type = EntityManager::id_type;
11
12 // Types are defined in descending priority order
13 enum class Type {
14 wall,
15 platform,
16 adjacency,
17 warp,
18 danger
19 };
20
21 Collision(
22 id_type collider,
23 Direction dir,
24 Type type,
25 int axis,
26 double lower,
27 double upper) :
28 collider_(collider),
29 dir_(dir),
30 type_(type),
31 axis_(axis),
32 lower_(lower),
33 upper_(upper)
34 {
35 }
36
37 inline id_type getCollider() const
38 {
39 return collider_;
40 }
41
42 inline Direction getDirection() const
43 {
44 return dir_;
45 }
46
47 inline Type getType() const
48 {
49 return type_;
50 }
51
52 inline int getAxis() const
53 {
54 return axis_;
55 }
56
57 inline double getLower() const
58 {
59 return lower_;
60 }
61
62 inline double getUpper() const
63 {
64 return upper_;
65 }
66
67 bool operator<(const Collision& other) const;
68
69 bool isColliding(double x, double y, int w, int h) const;
70
71private:
72
73 id_type collider_;
74 Direction dir_;
75 Type type_;
76 int axis_;
77 double lower_;
78 double upper_;
79};
80
81#endif /* end of include guard: COLLISION_H_53D84877 */
diff --git a/src/components/mappable.h b/src/components/mappable.h index 2dbab77..633cdf4 100644 --- a/src/components/mappable.h +++ b/src/components/mappable.h
@@ -4,6 +4,7 @@
4#include <map> 4#include <map>
5#include "component.h" 5#include "component.h"
6#include "renderer/texture.h" 6#include "renderer/texture.h"
7#include "collision.h"
7#include "map.h" 8#include "map.h"
8 9
9class MappableComponent : public Component { 10class MappableComponent : public Component {
@@ -12,14 +13,7 @@ public:
12 class Boundary { 13 class Boundary {
13 public: 14 public:
14 15
15 enum class Type { 16 using Type = Collision::Type;
16 wall,
17 wrap,
18 teleport,
19 reverse,
20 platform,
21 danger
22 };
23 17
24 Boundary( 18 Boundary(
25 double axis, 19 double axis,
diff --git a/src/components/playable.h b/src/components/playable.h new file mode 100644 index 0000000..a6e71b0 --- /dev/null +++ b/src/components/playable.h
@@ -0,0 +1,15 @@
1#ifndef PLAYABLE_H_DDC566C3
2#define PLAYABLE_H_DDC566C3
3
4#include "component.h"
5
6class PlayableComponent : public Component {
7public:
8
9 bool changingMap = false;
10 int newMapId = -1;
11 double newMapX = 0;
12 double newMapY = 0;
13};
14
15#endif /* end of include guard: PLAYABLE_H_DDC566C3 */
diff --git a/src/consts.h b/src/consts.h index 581018d..a065159 100644 --- a/src/consts.h +++ b/src/consts.h
@@ -7,7 +7,7 @@ const int GAME_WIDTH = 320;
7const int GAME_HEIGHT = 200; 7const int GAME_HEIGHT = 200;
8const int MAP_WIDTH = GAME_WIDTH/TILE_WIDTH; 8const int MAP_WIDTH = GAME_WIDTH/TILE_WIDTH;
9const int MAP_HEIGHT = GAME_HEIGHT/TILE_HEIGHT - 1; 9const int MAP_HEIGHT = GAME_HEIGHT/TILE_HEIGHT - 1;
10const int WALL_GAP = 6; 10const int WALL_GAP = 5;
11const int TILESET_COLS = 8; 11const int TILESET_COLS = 8;
12const int FONT_COLS = 16; 12const int FONT_COLS = 16;
13 13
diff --git a/src/entity_manager.h b/src/entity_manager.h index 65fa6ca..1e8d31c 100644 --- a/src/entity_manager.h +++ b/src/entity_manager.h
@@ -26,6 +26,7 @@ private:
26 26
27 database_type entities; 27 database_type entities;
28 std::vector<bool> slotAvailable; 28 std::vector<bool> slotAvailable;
29 std::set<id_type> allEntities;
29 std::map<std::set<std::type_index>, std::set<id_type>> cachedComponents; 30 std::map<std::set<std::type_index>, std::set<id_type>> cachedComponents;
30 31
31 id_type nextEntityID = 0; 32 id_type nextEntityID = 0;
@@ -59,12 +60,14 @@ public:
59 // If the database is saturated, add a new element for the new entity. 60 // If the database is saturated, add a new element for the new entity.
60 entities.emplace_back(); 61 entities.emplace_back();
61 slotAvailable.push_back(false); 62 slotAvailable.push_back(false);
63 allEntities.insert(nextEntityID);
62 64
63 return nextEntityID++; 65 return nextEntityID++;
64 } else { 66 } else {
65 // If there is an available slot in the database, use it. 67 // If there is an available slot in the database, use it.
66 id_type id = nextEntityID++; 68 id_type id = nextEntityID++;
67 slotAvailable[id] = false; 69 slotAvailable[id] = false;
70 allEntities.insert(id);
68 71
69 // Fast forward the next available slot pointer to an available slot. 72 // Fast forward the next available slot pointer to an available slot.
70 while ((nextEntityID < entities.size()) && !slotAvailable[nextEntityID]) 73 while ((nextEntityID < entities.size()) && !slotAvailable[nextEntityID])
@@ -89,6 +92,8 @@ public:
89 cache.second.erase(entity); 92 cache.second.erase(entity);
90 } 93 }
91 94
95 allEntities.erase(entity);
96
92 // Destroy the data 97 // Destroy the data
93 entities[entity].components.clear(); 98 entities[entity].components.clear();
94 99
@@ -202,6 +207,11 @@ public:
202 207
203 return getEntitiesWithComponentsHelper<R...>(componentTypes); 208 return getEntitiesWithComponentsHelper<R...>(componentTypes);
204 } 209 }
210
211 const std::set<id_type>& getEntities() const
212 {
213 return allEntities;
214 }
205}; 215};
206 216
207template <> 217template <>
diff --git a/src/game.cpp b/src/game.cpp index 228ff23..f245e7c 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -9,6 +9,7 @@
9#include "systems/animating.h" 9#include "systems/animating.h"
10#include "systems/mapping.h" 10#include "systems/mapping.h"
11#include "systems/orienting.h" 11#include "systems/orienting.h"
12#include "systems/playing.h"
12#include "animation.h" 13#include "animation.h"
13#include "consts.h" 14#include "consts.h"
14 15
@@ -28,36 +29,14 @@ void key_callback(GLFWwindow* window, int key, int, int action, int)
28 29
29Game::Game() : world_("res/maps.xml") 30Game::Game() : world_("res/maps.xml")
30{ 31{
32 systemManager_.emplaceSystem<PlayingSystem>(*this);
31 systemManager_.emplaceSystem<ControllingSystem>(*this); 33 systemManager_.emplaceSystem<ControllingSystem>(*this);
32 systemManager_.emplaceSystem<OrientingSystem>(*this); 34 systemManager_.emplaceSystem<OrientingSystem>(*this);
33 systemManager_.emplaceSystem<PonderingSystem>(*this); 35 systemManager_.emplaceSystem<PonderingSystem>(*this);
34 systemManager_.emplaceSystem<MappingSystem>(*this); 36 systemManager_.emplaceSystem<MappingSystem>(*this);
35 systemManager_.emplaceSystem<AnimatingSystem>(*this); 37 systemManager_.emplaceSystem<AnimatingSystem>(*this);
36 38
37 int player = entityManager_.emplaceEntity(); 39 systemManager_.getSystem<PlayingSystem>().initPlayer();
38
39 AnimationSet playerGraphics {"res/Starla.png", 10, 12, 6};
40 playerGraphics.emplaceAnimation("stillLeft", 3, 1, 1);
41 playerGraphics.emplaceAnimation("stillRight", 0, 1, 1);
42 playerGraphics.emplaceAnimation("walkingLeft", 4, 2, 10);
43 playerGraphics.emplaceAnimation("walkingRight", 1, 2, 10);
44
45 entityManager_.emplaceComponent<AnimatableComponent>(
46 player,
47 std::move(playerGraphics),
48 "stillLeft");
49
50 entityManager_.emplaceComponent<TransformableComponent>(
51 player,
52 203, 44, 10, 12);
53
54 systemManager_.getSystem<PonderingSystem>().initializeBody(
55 player,
56 PonderableComponent::Type::freefalling);
57
58 entityManager_.emplaceComponent<ControllableComponent>(player);
59 entityManager_.emplaceComponent<OrientableComponent>(player);
60
61 systemManager_.getSystem<MappingSystem>().loadMap(world_.getStartingMapId()); 40 systemManager_.getSystem<MappingSystem>().loadMap(world_.getStartingMapId());
62 41
63 glfwSwapInterval(1); 42 glfwSwapInterval(1);
diff --git a/src/map.h b/src/map.h index 9177870..6fe1e62 100644 --- a/src/map.h +++ b/src/map.h
@@ -10,13 +10,55 @@
10class Map { 10class Map {
11public: 11public:
12 12
13 class Adjacent {
14 public:
15
16 enum class Type {
17 wall,
18 wrap,
19 warp,
20 reverse
21 };
22
23 Adjacent(
24 Type type = Type::wall,
25 int mapId = -1) :
26 type_(type),
27 mapId_(mapId)
28 {
29 }
30
31 inline Type getType() const
32 {
33 return type_;
34 }
35
36 inline int getMapId() const
37 {
38 return mapId_;
39 }
40
41 private:
42
43 Type type_;
44 int mapId_;
45 };
46
13 Map( 47 Map(
14 int id, 48 int id,
15 std::vector<int> tiles, 49 std::vector<int> tiles,
16 std::string title) : 50 std::string title,
51 Adjacent leftAdjacent,
52 Adjacent rightAdjacent,
53 Adjacent upAdjacent,
54 Adjacent downAdjacent) :
17 id_(id), 55 id_(id),
18 tiles_(std::move(tiles)), 56 tiles_(std::move(tiles)),
19 title_(std::move(title)) 57 title_(std::move(title)),
58 leftAdjacent_(std::move(leftAdjacent)),
59 rightAdjacent_(std::move(rightAdjacent)),
60 upAdjacent_(std::move(upAdjacent)),
61 downAdjacent_(std::move(downAdjacent))
20 { 62 {
21 } 63 }
22 64
@@ -35,11 +77,35 @@ public:
35 return title_; 77 return title_;
36 } 78 }
37 79
80 inline const Adjacent& getLeftAdjacent() const
81 {
82 return leftAdjacent_;
83 }
84
85 inline const Adjacent& getRightAdjacent() const
86 {
87 return rightAdjacent_;
88 }
89
90 inline const Adjacent& getUpAdjacent() const
91 {
92 return upAdjacent_;
93 }
94
95 inline const Adjacent& getDownAdjacent() const
96 {
97 return downAdjacent_;
98 }
99
38private: 100private:
39 101
40 int id_; 102 int id_;
41 std::vector<int> tiles_; 103 std::vector<int> tiles_;
42 std::string title_; 104 std::string title_;
105 Adjacent leftAdjacent_;
106 Adjacent rightAdjacent_;
107 Adjacent upAdjacent_;
108 Adjacent downAdjacent_;
43}; 109};
44 110
45#endif /* end of include guard: MAP_H_74055FC0 */ 111#endif /* end of include guard: MAP_H_74055FC0 */
diff --git a/src/systems/mapping.cpp b/src/systems/mapping.cpp index 120a27a..05167c1 100644 --- a/src/systems/mapping.cpp +++ b/src/systems/mapping.cpp
@@ -93,6 +93,34 @@ void MappingSystem::loadMap(size_t mapId)
93 93
94 const Map& map = game_.getWorld().getMap(mappable.getMapId()); 94 const Map& map = game_.getWorld().getMap(mappable.getMapId());
95 95
96 addBoundary(
97 mappable.getLeftBoundaries(),
98 -WALL_GAP,
99 0,
100 MAP_HEIGHT * TILE_HEIGHT,
101 MappableComponent::Boundary::Type::adjacency);
102
103 addBoundary(
104 mappable.getRightBoundaries(),
105 GAME_WIDTH + WALL_GAP,
106 0,
107 MAP_HEIGHT * TILE_HEIGHT,
108 MappableComponent::Boundary::Type::adjacency);
109
110 addBoundary(
111 mappable.getUpBoundaries(),
112 -WALL_GAP,
113 0,
114 GAME_WIDTH,
115 MappableComponent::Boundary::Type::adjacency);
116
117 addBoundary(
118 mappable.getDownBoundaries(),
119 MAP_HEIGHT * TILE_HEIGHT + WALL_GAP,
120 0,
121 GAME_WIDTH,
122 MappableComponent::Boundary::Type::adjacency);
123
96 for (size_t i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++) 124 for (size_t i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++)
97 { 125 {
98 size_t x = i % MAP_WIDTH; 126 size_t x = i % MAP_WIDTH;
diff --git a/src/systems/playing.cpp b/src/systems/playing.cpp new file mode 100644 index 0000000..2c6a419 --- /dev/null +++ b/src/systems/playing.cpp
@@ -0,0 +1,98 @@
1#include "playing.h"
2#include "game.h"
3#include "components/transformable.h"
4#include "components/animatable.h"
5#include "components/playable.h"
6#include "components/controllable.h"
7#include "components/orientable.h"
8#include "systems/mapping.h"
9#include "systems/pondering.h"
10#include "animation.h"
11
12void PlayingSystem::tick(double)
13{
14 // Check if we need to change the map
15 auto players = game_.getEntityManager().getEntitiesWithComponents<
16 PlayableComponent>();
17
18 for (id_type player : players)
19 {
20 auto& playable = game_.getEntityManager().
21 getComponent<PlayableComponent>(player);
22
23 if (playable.changingMap)
24 {
25 // Change the map!
26 auto entities = game_.getEntityManager().getEntities();
27
28 for (id_type entity : entities)
29 {
30 if (entity != player)
31 {
32 game_.getEntityManager().deleteEntity(entity);
33 }
34 }
35
36 game_.getSystemManager().getSystem<MappingSystem>().
37 loadMap(playable.newMapId);
38
39 auto& transformable = game_.getEntityManager().
40 getComponent<TransformableComponent>(player);
41
42 transformable.setX(playable.newMapX);
43 transformable.setY(playable.newMapY);
44
45 playable.changingMap = false;
46
47 break;
48 }
49 }
50}
51
52void PlayingSystem::initPlayer()
53{
54 id_type player = game_.getEntityManager().emplaceEntity();
55
56 AnimationSet playerGraphics {"res/Starla.png", 10, 12, 6};
57 playerGraphics.emplaceAnimation("stillLeft", 3, 1, 1);
58 playerGraphics.emplaceAnimation("stillRight", 0, 1, 1);
59 playerGraphics.emplaceAnimation("walkingLeft", 4, 2, 10);
60 playerGraphics.emplaceAnimation("walkingRight", 1, 2, 10);
61
62 game_.getEntityManager().emplaceComponent<AnimatableComponent>(
63 player,
64 std::move(playerGraphics),
65 "stillLeft");
66
67 game_.getEntityManager().emplaceComponent<TransformableComponent>(
68 player,
69 203, 44, 10, 12);
70
71 game_.getSystemManager().getSystem<PonderingSystem>().initializeBody(
72 player,
73 PonderableComponent::Type::freefalling);
74
75 game_.getEntityManager().emplaceComponent<ControllableComponent>(player);
76 game_.getEntityManager().emplaceComponent<OrientableComponent>(player);
77 game_.getEntityManager().emplaceComponent<PlayableComponent>(player);
78}
79
80void PlayingSystem::changeMap(
81 size_t mapId,
82 double x,
83 double y)
84{
85 auto players = game_.getEntityManager().getEntitiesWithComponents<
86 PlayableComponent>();
87
88 for (id_type player : players)
89 {
90 auto& playable = game_.getEntityManager().
91 getComponent<PlayableComponent>(player);
92
93 playable.changingMap = true;
94 playable.newMapId = mapId;
95 playable.newMapX = x;
96 playable.newMapY = y;
97 }
98}
diff --git a/src/systems/playing.h b/src/systems/playing.h new file mode 100644 index 0000000..c98a464 --- /dev/null +++ b/src/systems/playing.h
@@ -0,0 +1,21 @@
1#ifndef PLAYING_H_70A54F7D
2#define PLAYING_H_70A54F7D
3
4#include "system.h"
5
6class PlayingSystem : public System {
7public:
8
9 PlayingSystem(Game& game) : System(game)
10 {
11 }
12
13 void tick(double dt);
14
15 void initPlayer();
16
17 void changeMap(size_t mapId, double x, double y);
18
19};
20
21#endif /* end of include guard: PLAYING_H_70A54F7D */
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index 4a165b1..2490dc9 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp
@@ -1,11 +1,14 @@
1#include "pondering.h" 1#include "pondering.h"
2#include <queue>
2#include "game.h" 3#include "game.h"
3#include "components/ponderable.h" 4#include "components/ponderable.h"
4#include "components/transformable.h" 5#include "components/transformable.h"
5#include "components/orientable.h" 6#include "components/orientable.h"
6#include "components/mappable.h" 7#include "components/mappable.h"
7#include "systems/orienting.h" 8#include "systems/orienting.h"
9#include "systems/playing.h"
8#include "consts.h" 10#include "consts.h"
11#include "collision.h"
9 12
10void PonderingSystem::tick(double dt) 13void PonderingSystem::tick(double dt)
11{ 14{
@@ -42,6 +45,9 @@ void PonderingSystem::tick(double dt)
42 bool oldGrounded = ponderable.isGrounded(); 45 bool oldGrounded = ponderable.isGrounded();
43 ponderable.setGrounded(false); 46 ponderable.setGrounded(false);
44 47
48 std::priority_queue<Collision> collisions;
49
50 // Find collisions
45 for (id_type mapEntity : maps) 51 for (id_type mapEntity : maps)
46 { 52 {
47 auto& mappable = game_.getEntityManager(). 53 auto& mappable = game_.getEntityManager().
@@ -57,13 +63,13 @@ void PonderingSystem::tick(double dt)
57 && (oldY < it->second.getUpper())) 63 && (oldY < it->second.getUpper()))
58 { 64 {
59 // We have a collision! 65 // We have a collision!
60 processCollision( 66 collisions.emplace(
61 entity, 67 mapEntity,
62 Direction::left, 68 Direction::left,
63 newX, 69 it->second.getType(),
64 newY,
65 it->first, 70 it->first,
66 it->second.getType()); 71 it->second.getLower(),
72 it->second.getUpper());
67 } 73 }
68 } 74 }
69 } else if (newX > oldX) 75 } else if (newX > oldX)
@@ -77,13 +83,13 @@ void PonderingSystem::tick(double dt)
77 && (oldY < it->second.getUpper())) 83 && (oldY < it->second.getUpper()))
78 { 84 {
79 // We have a collision! 85 // We have a collision!
80 processCollision( 86 collisions.emplace(
81 entity, 87 mapEntity,
82 Direction::right, 88 Direction::right,
83 newX, 89 it->second.getType(),
84 newY,
85 it->first, 90 it->first,
86 it->second.getType()); 91 it->second.getLower(),
92 it->second.getUpper());
87 } 93 }
88 } 94 }
89 } 95 }
@@ -98,13 +104,13 @@ void PonderingSystem::tick(double dt)
98 && (oldX < it->second.getUpper())) 104 && (oldX < it->second.getUpper()))
99 { 105 {
100 // We have a collision! 106 // We have a collision!
101 processCollision( 107 collisions.emplace(
102 entity, 108 mapEntity,
103 Direction::up, 109 Direction::up,
104 newX, 110 it->second.getType(),
105 newY,
106 it->first, 111 it->first,
107 it->second.getType()); 112 it->second.getLower(),
113 it->second.getUpper());
108 } 114 }
109 } 115 }
110 } else if (newY > oldY) 116 } else if (newY > oldY)
@@ -118,13 +124,221 @@ void PonderingSystem::tick(double dt)
118 && (oldX < it->second.getUpper())) 124 && (oldX < it->second.getUpper()))
119 { 125 {
120 // We have a collision! 126 // We have a collision!
121 processCollision( 127 collisions.emplace(
122 entity, 128 mapEntity,
123 Direction::down, 129 Direction::down,
124 newX, 130 it->second.getType(),
125 newY,
126 it->first, 131 it->first,
127 it->second.getType()); 132 it->second.getLower(),
133 it->second.getUpper());
134 }
135 }
136 }
137 }
138
139 // Process collisions in order of priority
140 while (!collisions.empty())
141 {
142 Collision collision = collisions.top();
143 collisions.pop();
144
145 // Make sure that they are still colliding
146 if (!collision.isColliding(
147 newX,
148 newY,
149 transformable.getW(),
150 transformable.getH()))
151 {
152 continue;
153 }
154
155 bool touchedWall = false;
156 bool stopProcessing = false;
157
158 switch (collision.getType())
159 {
160 case Collision::Type::wall:
161 {
162 touchedWall = true;
163
164 break;
165 }
166
167 case Collision::Type::platform:
168 {
169 if (game_.getEntityManager().
170 hasComponent<OrientableComponent>(entity))
171 {
172 auto& orientable = game_.getEntityManager().
173 getComponent<OrientableComponent>(entity);
174
175 if (orientable.getDropState() !=
176 OrientableComponent::DropState::none)
177 {
178 orientable.setDropState(OrientableComponent::DropState::active);
179 } else {
180 touchedWall = true;
181 }
182 } else {
183 touchedWall = true;
184 }
185
186 break;
187 }
188
189 case Collision::Type::adjacency:
190 {
191 auto& mappable = game_.getEntityManager().
192 getComponent<MappableComponent>(collision.getCollider());
193 const Map& map = game_.getWorld().getMap(mappable.getMapId());
194 auto& adj = [&] () -> const Map::Adjacent& {
195 switch (collision.getDirection())
196 {
197 case Direction::left: return map.getLeftAdjacent();
198 case Direction::right: return map.getRightAdjacent();
199 case Direction::up: return map.getUpAdjacent();
200 case Direction::down: return map.getDownAdjacent();
201 }
202 }();
203
204 switch (adj.getType())
205 {
206 case Map::Adjacent::Type::wall:
207 {
208 touchedWall = true;
209
210 break;
211 }
212
213 case Map::Adjacent::Type::wrap:
214 {
215 switch (collision.getDirection())
216 {
217 case Direction::left:
218 {
219 newX = GAME_WIDTH + WALL_GAP - transformable.getW();
220
221 break;
222 }
223
224 case Direction::right:
225 {
226 newX = -WALL_GAP;
227
228 break;
229 }
230
231 case Direction::up:
232 {
233 newY = MAP_HEIGHT * TILE_HEIGHT + WALL_GAP -
234 transformable.getH();
235
236 break;
237 }
238
239 case Direction::down:
240 {
241 newY = -WALL_GAP;
242
243 break;
244 }
245 }
246 }
247
248 case Map::Adjacent::Type::warp:
249 {
250 double warpX = newX;
251 double warpY = newY;
252
253 switch (collision.getDirection())
254 {
255 case Direction::left:
256 {
257 warpX = GAME_WIDTH + WALL_GAP - transformable.getW();
258
259 break;
260 }
261
262 case Direction::right:
263 {
264 warpX = -WALL_GAP;
265
266 break;
267 }
268
269 case Direction::up:
270 {
271 warpY = MAP_HEIGHT * TILE_HEIGHT - transformable.getH();
272
273 break;
274 }
275
276 case Direction::down:
277 {
278 warpY = -WALL_GAP;
279
280 break;
281 }
282 }
283
284 game_.getSystemManager().getSystem<PlayingSystem>().
285 changeMap(adj.getMapId(), warpX, warpY);
286
287 stopProcessing = true;
288
289 break;
290 }
291 }
292 }
293
294 default:
295 {
296 // Not yet implemented.
297
298 break;
299 }
300 }
301
302 if (stopProcessing)
303 {
304 break;
305 }
306
307 if (touchedWall)
308 {
309 switch (collision.getDirection())
310 {
311 case Direction::left:
312 {
313 newX = collision.getAxis();
314 ponderable.setVelocityX(0.0);
315
316 break;
317 }
318
319 case Direction::right:
320 {
321 newX = collision.getAxis() - transformable.getW();
322 ponderable.setVelocityX(0.0);
323
324 break;
325 }
326
327 case Direction::up:
328 {
329 newY = collision.getAxis();
330 ponderable.setVelocityY(0.0);
331
332 break;
333 }
334
335 case Direction::down:
336 {
337 newY = collision.getAxis() - transformable.getH();
338 ponderable.setVelocityY(0.0);
339 ponderable.setGrounded(true);
340
341 break;
128 } 342 }
129 } 343 }
130 } 344 }
@@ -173,96 +387,3 @@ void PonderingSystem::initializeBody(
173 ponderable.setAccelY(NORMAL_GRAVITY); 387 ponderable.setAccelY(NORMAL_GRAVITY);
174 } 388 }
175} 389}
176
177void PonderingSystem::processCollision(
178 id_type entity,
179 Direction dir,
180 double& newX,
181 double& newY,
182 int axis,
183 MappableComponent::Boundary::Type type)
184{
185 auto& ponderable = game_.getEntityManager().
186 getComponent<PonderableComponent>(entity);
187
188 auto& transformable = game_.getEntityManager().
189 getComponent<TransformableComponent>(entity);
190
191 bool touchedGround = false;
192
193 switch (type)
194 {
195 case MappableComponent::Boundary::Type::wall:
196 {
197 switch (dir)
198 {
199 case Direction::left:
200 {
201 newX = axis;
202 ponderable.setVelocityX(0.0);
203
204 break;
205 }
206
207 case Direction::right:
208 {
209 newX = axis - transformable.getW();
210 ponderable.setVelocityX(0.0);
211
212 break;
213 }
214
215 case Direction::up:
216 {
217 newY = axis;
218 ponderable.setVelocityY(0.0);
219
220 break;
221 }
222
223 case Direction::down:
224 {
225 touchedGround = true;
226
227 break;
228 }
229 }
230
231 break;
232 }
233
234 case MappableComponent::Boundary::Type::platform:
235 {
236 if (game_.getEntityManager().hasComponent<OrientableComponent>(entity))
237 {
238 auto& orientable = game_.getEntityManager().
239 getComponent<OrientableComponent>(entity);
240
241 if (orientable.getDropState() != OrientableComponent::DropState::none)
242 {
243 orientable.setDropState(OrientableComponent::DropState::active);
244 } else {
245 touchedGround = true;
246 }
247 } else {
248 touchedGround = true;
249 }
250
251 break;
252 }
253
254 default:
255 {
256 // Not yet implemented.
257
258 break;
259 }
260 }
261
262 if (touchedGround)
263 {
264 newY = axis - transformable.getH();
265 ponderable.setVelocityY(0.0);
266 ponderable.setGrounded(true);
267 }
268}
diff --git a/src/systems/pondering.h b/src/systems/pondering.h index a16622b..d70525b 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h
@@ -2,7 +2,6 @@
2#define PONDERING_H_F2530E0E 2#define PONDERING_H_F2530E0E
3 3
4#include "system.h" 4#include "system.h"
5#include "components/mappable.h"
6#include "components/ponderable.h" 5#include "components/ponderable.h"
7#include "direction.h" 6#include "direction.h"
8 7
@@ -17,16 +16,6 @@ public:
17 16
18 void initializeBody(id_type entity, PonderableComponent::Type type); 17 void initializeBody(id_type entity, PonderableComponent::Type type);
19 18
20private:
21
22 void processCollision(
23 id_type entity,
24 Direction dir,
25 double& newX,
26 double& newY,
27 int axis,
28 MappableComponent::Boundary::Type type);
29
30}; 19};
31 20
32#endif /* end of include guard: PONDERING_H_F2530E0E */ 21#endif /* end of include guard: PONDERING_H_F2530E0E */
diff --git a/src/world.cpp b/src/world.cpp index 9b1e4f6..3b6bd41 100644 --- a/src/world.cpp +++ b/src/world.cpp
@@ -63,6 +63,10 @@ World::World(std::string filename)
63 xmlFree(key); 63 xmlFree(key);
64 64
65 std::vector<int> mapTiles; 65 std::vector<int> mapTiles;
66 Map::Adjacent leftAdj;
67 Map::Adjacent rightAdj;
68 Map::Adjacent upAdj;
69 Map::Adjacent downAdj;
66 70
67 for (xmlNodePtr mapNode = node->xmlChildrenNode; 71 for (xmlNodePtr mapNode = node->xmlChildrenNode;
68 mapNode != nullptr; 72 mapNode != nullptr;
@@ -82,6 +86,54 @@ World::World(std::string filename)
82 } 86 }
83 87
84 xmlFree(key); 88 xmlFree(key);
89 } else if (!xmlStrcmp(
90 mapNode->name,
91 reinterpret_cast<const xmlChar*>("adjacent")))
92 {
93 key = getProp(mapNode, "type");
94 std::string adjTypeStr(reinterpret_cast<char*>(key));
95 xmlFree(key);
96
97 Map::Adjacent::Type adjType;
98 if (adjTypeStr == "wall")
99 {
100 adjType = Map::Adjacent::Type::wall;
101 } else if (adjTypeStr == "wrap")
102 {
103 adjType = Map::Adjacent::Type::wrap;
104 } else if (adjTypeStr == "warp")
105 {
106 adjType = Map::Adjacent::Type::warp;
107 } else if (adjTypeStr == "reverseWarp")
108 {
109 adjType = Map::Adjacent::Type::reverse;
110 } else {
111 throw std::logic_error("Invalid adjacency type");
112 }
113
114 key = getProp(mapNode, "map");
115 int adjMapId = atoi(reinterpret_cast<char*>(key));
116 xmlFree(key);
117
118 key = getProp(mapNode, "dir");
119 std::string adjDir(reinterpret_cast<char*>(key));
120 xmlFree(key);
121
122 if (adjDir == "left")
123 {
124 leftAdj = {adjType, adjMapId};
125 } else if (adjDir == "right")
126 {
127 rightAdj = {adjType, adjMapId};
128 } else if (adjDir == "up")
129 {
130 upAdj = {adjType, adjMapId};
131 } else if (adjDir == "down")
132 {
133 downAdj = {adjType, adjMapId};
134 } else {
135 throw std::logic_error("Invalid adjacency direction");
136 }
85 } 137 }
86 } 138 }
87 139
@@ -91,7 +143,11 @@ World::World(std::string filename)
91 std::forward_as_tuple( 143 std::forward_as_tuple(
92 mapId, 144 mapId,
93 std::move(mapTiles), 145 std::move(mapTiles),
94 std::move(mapTitle))); 146 std::move(mapTitle),
147 leftAdj,
148 rightAdj,
149 upAdj,
150 downAdj));
95 } 151 }
96 } 152 }
97 153