summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-02-11 12:34:52 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-02-11 12:34:52 -0500
commit77be863f4f15d2481a64e4e8dadb4060a6e4e590 (patch)
treeca571702d2148a75b5b847e77d26270257f54ebc /src
parent1400ade977e13e3b535d3c2fddb6e15de3c9b5a5 (diff)
downloadtherapy-77be863f4f15d2481a64e4e8dadb4060a6e4e590.tar.gz
therapy-77be863f4f15d2481a64e4e8dadb4060a6e4e590.tar.bz2
therapy-77be863f4f15d2481a64e4e8dadb4060a6e4e590.zip
Implemented map rendering and basic collision
Only wall and platform collision currently works, and map edges are not currently implemented.
Diffstat (limited to 'src')
-rw-r--r--src/components/mappable.h146
-rw-r--r--src/components/ponderable.h23
-rw-r--r--src/consts.h3
-rw-r--r--src/direction.h8
-rw-r--r--src/entity_manager.h20
-rw-r--r--src/game.cpp14
-rw-r--r--src/game.h9
-rw-r--r--src/map.h45
-rw-r--r--src/systems/controlling.cpp22
-rw-r--r--src/systems/mapping.cpp143
-rw-r--r--src/systems/mapping.h19
-rw-r--r--src/systems/pondering.cpp248
-rw-r--r--src/systems/pondering.h16
-rw-r--r--src/world.cpp99
-rw-r--r--src/world.h41
15 files changed, 825 insertions, 31 deletions
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/ponderable.h b/src/components/ponderable.h index dfbf908..ac759b6 100644 --- a/src/components/ponderable.h +++ b/src/components/ponderable.h
@@ -6,13 +6,27 @@
6class PonderableComponent : public Component { 6class PonderableComponent : public Component {
7public: 7public:
8 8
9 enum class state { 9 enum class Type {
10 vacuumed,
11 freefalling
12 };
13
14 enum class State {
10 grounded, 15 grounded,
11 jumping, 16 jumping,
12 falling, 17 falling,
13 dropping 18 dropping
14 }; 19 };
15 20
21 PonderableComponent(Type type) : type_(type)
22 {
23 }
24
25 inline Type getType() const
26 {
27 return type_;
28 }
29
16 inline double getVelocityX() const 30 inline double getVelocityX() const
17 { 31 {
18 return velX_; 32 return velX_;
@@ -53,12 +67,12 @@ public:
53 accelY_ = v; 67 accelY_ = v;
54 } 68 }
55 69
56 inline state getState() const 70 inline State getState() const
57 { 71 {
58 return state_; 72 return state_;
59 } 73 }
60 74
61 inline void setState(state arg) 75 inline void setState(State arg)
62 { 76 {
63 state_ = arg; 77 state_ = arg;
64 } 78 }
@@ -69,7 +83,8 @@ private:
69 double velY_ = 0.0; 83 double velY_ = 0.0;
70 double accelX_ = 0.0; 84 double accelX_ = 0.0;
71 double accelY_ = 0.0; 85 double accelY_ = 0.0;
72 state state_ = state::grounded; 86 Type type_ = Type::vacuumed;
87 State state_ = State::grounded;
73}; 88};
74 89
75#endif /* end of include guard: TANGIBLE_H_746DB3EE */ 90#endif /* end of include guard: TANGIBLE_H_746DB3EE */
diff --git a/src/consts.h b/src/consts.h index 4595719..a6c9985 100644 --- a/src/consts.h +++ b/src/consts.h
@@ -7,6 +7,9 @@ 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;
11const int TILESET_COLS = 8;
12const int FONT_COLS = 16;
10 13
11const int FRAMES_PER_SECOND = 60; 14const int FRAMES_PER_SECOND = 60;
12const double SECONDS_PER_FRAME = 1.0 / FRAMES_PER_SECOND; 15const double SECONDS_PER_FRAME = 1.0 / FRAMES_PER_SECOND;
diff --git a/src/direction.h b/src/direction.h index 32d6b41..9a4c801 100644 --- a/src/direction.h +++ b/src/direction.h
@@ -2,10 +2,10 @@
2#define DIRECTION_H_9C49EAFD 2#define DIRECTION_H_9C49EAFD
3 3
4enum class Direction { 4enum class Direction {
5 Left, 5 left,
6 Right, 6 right,
7 Up, 7 up,
8 Down 8 down
9}; 9};
10 10
11#endif /* end of include guard: DIRECTION_H_9C49EAFD */ 11#endif /* end of include guard: DIRECTION_H_9C49EAFD */
diff --git a/src/entity_manager.h b/src/entity_manager.h index 9068fe3..7fd82fc 100644 --- a/src/entity_manager.h +++ b/src/entity_manager.h
@@ -106,7 +106,7 @@ public:
106 { 106 {
107 if ((entity >= entities.size()) || slotAvailable[entity]) 107 if ((entity >= entities.size()) || slotAvailable[entity])
108 { 108 {
109 throw std::invalid_argument("Cannot delete non-existent entity"); 109 throw std::invalid_argument("Cannot get non-existent entity");
110 } 110 }
111 111
112 EntityData& data = entities[entity]; 112 EntityData& data = entities[entity];
@@ -138,7 +138,7 @@ public:
138 { 138 {
139 if ((entity >= entities.size()) || slotAvailable[entity]) 139 if ((entity >= entities.size()) || slotAvailable[entity])
140 { 140 {
141 throw std::invalid_argument("Cannot delete non-existent entity"); 141 throw std::invalid_argument("Cannot get non-existent entity");
142 } 142 }
143 143
144 EntityData& data = entities[entity]; 144 EntityData& data = entities[entity];
@@ -167,7 +167,7 @@ public:
167 { 167 {
168 if ((entity >= entities.size()) || slotAvailable[entity]) 168 if ((entity >= entities.size()) || slotAvailable[entity])
169 { 169 {
170 throw std::invalid_argument("Cannot delete non-existent entity"); 170 throw std::invalid_argument("Cannot get non-existent entity");
171 } 171 }
172 172
173 EntityData& data = entities[entity]; 173 EntityData& data = entities[entity];
@@ -181,6 +181,20 @@ public:
181 return *dynamic_cast<T*>(data.components[componentType].get()); 181 return *dynamic_cast<T*>(data.components[componentType].get());
182 } 182 }
183 183
184 template <class T>
185 bool hasComponent(id_type entity)
186 {
187 if ((entity >= entities.size()) || slotAvailable[entity])
188 {
189 throw std::invalid_argument("Cannot get non-existent entity");
190 }
191
192 EntityData& data = entities[entity];
193 std::type_index componentType = typeid(T);
194
195 return data.components.count(componentType);
196 }
197
184 template <class... R> 198 template <class... R>
185 std::set<id_type> getEntitiesWithComponents() 199 std::set<id_type> getEntitiesWithComponents()
186 { 200 {
diff --git a/src/game.cpp b/src/game.cpp index dfe700e..7cbe7e0 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -8,6 +8,7 @@
8#include "systems/controlling.h" 8#include "systems/controlling.h"
9#include "systems/pondering.h" 9#include "systems/pondering.h"
10#include "systems/animating.h" 10#include "systems/animating.h"
11#include "systems/mapping.h"
11#include "animation.h" 12#include "animation.h"
12#include "renderer.h" 13#include "renderer.h"
13#include "consts.h" 14#include "consts.h"
@@ -26,10 +27,14 @@ void key_callback(GLFWwindow* window, int key, int, int action, int)
26 game.systemManager_.input(key, action); 27 game.systemManager_.input(key, action);
27} 28}
28 29
29Game::Game(GLFWwindow* window) : window_(window) 30Game::Game(
31 GLFWwindow* window) :
32 window_(window),
33 world_("res/maps.xml")
30{ 34{
31 systemManager_.emplaceSystem<ControllingSystem>(*this); 35 systemManager_.emplaceSystem<ControllingSystem>(*this);
32 systemManager_.emplaceSystem<PonderingSystem>(*this); 36 systemManager_.emplaceSystem<PonderingSystem>(*this);
37 systemManager_.emplaceSystem<MappingSystem>(*this);
33 systemManager_.emplaceSystem<AnimatingSystem>(*this); 38 systemManager_.emplaceSystem<AnimatingSystem>(*this);
34 39
35 int player = entityManager_.emplaceEntity(); 40 int player = entityManager_.emplaceEntity();
@@ -49,11 +54,16 @@ Game::Game(GLFWwindow* window) : window_(window)
49 player, 54 player,
50 203, 44, 10, 12); 55 203, 44, 10, 12);
51 56
57 systemManager_.getSystem<PonderingSystem>().initializeBody(
58 player,
59 PonderableComponent::Type::freefalling);
60
52 entityManager_.emplaceComponent<DroppableComponent>(player); 61 entityManager_.emplaceComponent<DroppableComponent>(player);
53 entityManager_.emplaceComponent<PonderableComponent>(player);
54 entityManager_.emplaceComponent<ControllableComponent>(player); 62 entityManager_.emplaceComponent<ControllableComponent>(player);
55 entityManager_.emplaceComponent<OrientableComponent>(player); 63 entityManager_.emplaceComponent<OrientableComponent>(player);
56 64
65 systemManager_.getSystem<MappingSystem>().loadMap(world_.getStartingMapId());
66
57 glfwSwapInterval(1); 67 glfwSwapInterval(1);
58 glfwSetWindowUserPointer(window_, this); 68 glfwSetWindowUserPointer(window_, this);
59 glfwSetKeyCallback(window_, key_callback); 69 glfwSetKeyCallback(window_, key_callback);
diff --git a/src/game.h b/src/game.h index 7bd038e..346d67e 100644 --- a/src/game.h +++ b/src/game.h
@@ -4,6 +4,7 @@
4#include "renderer.h" 4#include "renderer.h"
5#include "entity_manager.h" 5#include "entity_manager.h"
6#include "system_manager.h" 6#include "system_manager.h"
7#include "world.h"
7 8
8class Game { 9class Game {
9public: 10public:
@@ -22,6 +23,11 @@ public:
22 return systemManager_; 23 return systemManager_;
23 } 24 }
24 25
26 inline const World& getWorld()
27 {
28 return world_;
29 }
30
25 friend void key_callback( 31 friend void key_callback(
26 GLFWwindow* window, 32 GLFWwindow* window,
27 int key, 33 int key,
@@ -31,9 +37,10 @@ public:
31 37
32private: 38private:
33 39
40 GLFWwindow* const window_;
34 EntityManager entityManager_; 41 EntityManager entityManager_;
35 SystemManager systemManager_; 42 SystemManager systemManager_;
36 GLFWwindow* const window_; 43 World world_;
37 bool shouldQuit_ = false; 44 bool shouldQuit_ = false;
38}; 45};
39 46
diff --git a/src/map.h b/src/map.h new file mode 100644 index 0000000..9177870 --- /dev/null +++ b/src/map.h
@@ -0,0 +1,45 @@
1#ifndef MAP_H_74055FC0
2#define MAP_H_74055FC0
3
4#include <vector>
5#include <string>
6#include <list>
7#include <stdexcept>
8#include <map>
9
10class Map {
11public:
12
13 Map(
14 int id,
15 std::vector<int> tiles,
16 std::string title) :
17 id_(id),
18 tiles_(std::move(tiles)),
19 title_(std::move(title))
20 {
21 }
22
23 inline size_t getId() const
24 {
25 return id_;
26 }
27
28 inline const std::vector<int>& getTiles() const
29 {
30 return tiles_;
31 }
32
33 inline const std::string& getTitle() const
34 {
35 return title_;
36 }
37
38private:
39
40 int id_;
41 std::vector<int> tiles_;
42 std::string title_;
43};
44
45#endif /* end of include guard: MAP_H_74055FC0 */
diff --git a/src/systems/controlling.cpp b/src/systems/controlling.cpp index 3647ff8..fa09d11 100644 --- a/src/systems/controlling.cpp +++ b/src/systems/controlling.cpp
@@ -123,7 +123,7 @@ void ControllingSystem::walkLeft(id_type entity)
123 123
124 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 124 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
125 125
126 if (ponderable.getState() == PonderableComponent::state::grounded) 126 if (ponderable.getState() == PonderableComponent::State::grounded)
127 { 127 {
128 animating.startAnimation(entity, "walkingLeft"); 128 animating.startAnimation(entity, "walkingLeft");
129 } else { 129 } else {
@@ -141,7 +141,7 @@ void ControllingSystem::walkRight(id_type entity)
141 141
142 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 142 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
143 143
144 if (ponderable.getState() == PonderableComponent::state::grounded) 144 if (ponderable.getState() == PonderableComponent::State::grounded)
145 { 145 {
146 animating.startAnimation(entity, "walkingRight"); 146 animating.startAnimation(entity, "walkingRight");
147 } else { 147 } else {
@@ -156,7 +156,7 @@ void ControllingSystem::stopWalking(id_type entity)
156 156
157 ponderable.setVelocityX(0); 157 ponderable.setVelocityX(0);
158 158
159 if (ponderable.getState() == PonderableComponent::state::grounded) 159 if (ponderable.getState() == PonderableComponent::State::grounded)
160 { 160 {
161 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 161 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
162 162
@@ -173,13 +173,13 @@ void ControllingSystem::jump(id_type entity)
173{ 173{
174 auto& ponderable = game_.getEntityManager().getComponent<PonderableComponent>(entity); 174 auto& ponderable = game_.getEntityManager().getComponent<PonderableComponent>(entity);
175 175
176 if (ponderable.getState() == PonderableComponent::state::grounded) 176 if (ponderable.getState() == PonderableComponent::State::grounded)
177 { 177 {
178 playSound("res/Randomize87.wav", 0.25); 178 playSound("res/Randomize87.wav", 0.25);
179 179
180 ponderable.setVelocityY(JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3)); 180 ponderable.setVelocityY(JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3));
181 ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3)); 181 ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3));
182 ponderable.setState(PonderableComponent::state::jumping); 182 ponderable.setState(PonderableComponent::State::jumping);
183 } 183 }
184} 184}
185 185
@@ -187,10 +187,10 @@ void ControllingSystem::stopJumping(id_type entity)
187{ 187{
188 auto& ponderable = game_.getEntityManager().getComponent<PonderableComponent>(entity); 188 auto& ponderable = game_.getEntityManager().getComponent<PonderableComponent>(entity);
189 189
190 if (ponderable.getState() == PonderableComponent::state::jumping) 190 if (ponderable.getState() == PonderableComponent::State::jumping)
191 { 191 {
192 ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233)); 192 ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233));
193 ponderable.setState(PonderableComponent::state::falling); 193 ponderable.setState(PonderableComponent::State::falling);
194 } 194 }
195} 195}
196 196
@@ -199,12 +199,12 @@ void ControllingSystem::drop(id_type entity, bool start)
199 auto& droppable = game_.getEntityManager().getComponent<DroppableComponent>(entity); 199 auto& droppable = game_.getEntityManager().getComponent<DroppableComponent>(entity);
200 auto& ponderable = game_.getEntityManager().getComponent<PonderableComponent>(entity); 200 auto& ponderable = game_.getEntityManager().getComponent<PonderableComponent>(entity);
201 201
202 if (start && (ponderable.getState() == PonderableComponent::state::grounded)) 202 if (start && (ponderable.getState() == PonderableComponent::State::grounded))
203 { 203 {
204 ponderable.setState(PonderableComponent::state::dropping); 204 ponderable.setState(PonderableComponent::State::dropping);
205 } else if ((!start) && (ponderable.getState() == PonderableComponent::state::dropping)) 205 } else if ((!start) && (ponderable.getState() == PonderableComponent::State::dropping))
206 { 206 {
207 ponderable.setState(PonderableComponent::state::grounded); 207 ponderable.setState(PonderableComponent::State::grounded);
208 } 208 }
209 droppable.setDroppable(start); 209 droppable.setDroppable(start);
210} 210}
diff --git a/src/systems/mapping.cpp b/src/systems/mapping.cpp new file mode 100644 index 0000000..8723e16 --- /dev/null +++ b/src/systems/mapping.cpp
@@ -0,0 +1,143 @@
1#include "mapping.h"
2#include "components/mappable.h"
3#include "game.h"
4#include "consts.h"
5
6#include <iostream>
7
8template <typename Storage>
9inline void addBoundary(
10 Storage& boundaries,
11 int axis,
12 int lower,
13 int upper,
14 MappableComponent::Boundary::Type type)
15{
16 boundaries.emplace(std::piecewise_construct,
17 std::tie(axis),
18 std::tie(axis, lower, upper, type));
19}
20
21void MappingSystem::render(Texture& texture)
22{
23 auto entities = game_.getEntityManager().getEntitiesWithComponents<
24 MappableComponent>();
25
26 for (id_type entity : entities)
27 {
28 auto& mappable = game_.getEntityManager().
29 getComponent<MappableComponent>(entity);
30
31 const Map& map = game_.getWorld().getMap(mappable.getMapId());
32
33 for (int i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++)
34 {
35 int x = i % MAP_WIDTH;
36 int y = i / MAP_WIDTH;
37 int tile = map.getTiles()[i];
38
39 if (tile > 0)
40 {
41 Rectangle dst {
42 x * TILE_WIDTH,
43 y * TILE_HEIGHT,
44 TILE_WIDTH,
45 TILE_HEIGHT};
46
47 Rectangle src {
48 (tile % TILESET_COLS) * TILE_WIDTH,
49 (tile / TILESET_COLS) * TILE_HEIGHT,
50 TILE_WIDTH,
51 TILE_HEIGHT};
52
53 texture.blit(mappable.getTileset(), std::move(src), std::move(dst));
54 }
55 }
56
57 int startX = ((GAME_WIDTH / TILE_WIDTH) / 2) - (map.getTitle().size() / 2);
58 for (size_t i = 0; i < map.getTitle().size(); i++)
59 {
60 Rectangle src {
61 (map.getTitle()[i] % FONT_COLS) * TILE_WIDTH,
62 (map.getTitle()[i] / FONT_COLS) * TILE_HEIGHT,
63 TILE_WIDTH,
64 TILE_HEIGHT};
65
66 Rectangle dst {
67 (startX + static_cast<int>(i)) * TILE_WIDTH,
68 24 * TILE_HEIGHT,
69 TILE_WIDTH,
70 TILE_HEIGHT};
71
72 texture.blit(mappable.getFont(), std::move(src), std::move(dst));
73 }
74 }
75}
76
77void MappingSystem::loadMap(size_t mapId)
78{
79 id_type mapEntity = game_.getEntityManager().emplaceEntity();
80
81 auto& mappable = game_.getEntityManager().
82 emplaceComponent<MappableComponent>(mapEntity,
83 Texture("res/tiles.png"),
84 Texture("res/font.bmp"));
85
86 mappable.setMapId(mapId);
87
88 const Map& map = game_.getWorld().getMap(mappable.getMapId());
89
90 for (size_t i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++)
91 {
92 size_t x = i % MAP_WIDTH;
93 size_t y = i / MAP_WIDTH;
94 int tile = map.getTiles()[i];
95
96 if ((tile >= 5) && (tile <= 7))
97 {
98 addBoundary(
99 mappable.getDownBoundaries(),
100 y * TILE_HEIGHT,
101 x * TILE_WIDTH,
102 (x + 1) * TILE_WIDTH,
103 MappableComponent::Boundary::Type::platform);
104 } else if ((tile > 0) && (tile < 28))
105 {
106 addBoundary(
107 mappable.getRightBoundaries(),
108 x * TILE_WIDTH,
109 y * TILE_HEIGHT,
110 (y+1) * TILE_HEIGHT,
111 MappableComponent::Boundary::Type::wall);
112
113 addBoundary(
114 mappable.getLeftBoundaries(),
115 (x+1) * TILE_WIDTH,
116 y * TILE_HEIGHT,
117 (y+1) * TILE_HEIGHT,
118 MappableComponent::Boundary::Type::wall);
119
120 addBoundary(
121 mappable.getDownBoundaries(),
122 y * TILE_HEIGHT,
123 x * TILE_WIDTH,
124 (x+1) * TILE_WIDTH,
125 MappableComponent::Boundary::Type::wall);
126
127 addBoundary(
128 mappable.getUpBoundaries(),
129 (y+1) * TILE_HEIGHT,
130 x * TILE_WIDTH,
131 (x+1) * TILE_WIDTH,
132 MappableComponent::Boundary::Type::wall);
133 } else if (tile == 42)
134 {
135 addBoundary(
136 mappable.getDownBoundaries(),
137 y * TILE_HEIGHT,
138 x * TILE_WIDTH,
139 (x+1) * TILE_WIDTH,
140 MappableComponent::Boundary::Type::danger);
141 }
142 }
143}
diff --git a/src/systems/mapping.h b/src/systems/mapping.h new file mode 100644 index 0000000..53d054b --- /dev/null +++ b/src/systems/mapping.h
@@ -0,0 +1,19 @@
1#ifndef MAPPING_H_33FC2294
2#define MAPPING_H_33FC2294
3
4#include "system.h"
5
6class MappingSystem : public System {
7public:
8
9 MappingSystem(Game& game) : System(game)
10 {
11 }
12
13 void render(Texture& texture);
14
15 void loadMap(size_t mapId);
16
17};
18
19#endif /* end of include guard: MAPPING_H_33FC2294 */
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index e40db1d..26a6f56 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp
@@ -2,6 +2,8 @@
2#include "game.h" 2#include "game.h"
3#include "components/ponderable.h" 3#include "components/ponderable.h"
4#include "components/transformable.h" 4#include "components/transformable.h"
5#include "components/droppable.h"
6#include "consts.h"
5 7
6void PonderingSystem::tick(double dt) 8void PonderingSystem::tick(double dt)
7{ 9{
@@ -9,17 +11,251 @@ void PonderingSystem::tick(double dt)
9 PonderableComponent, 11 PonderableComponent,
10 TransformableComponent>(); 12 TransformableComponent>();
11 13
14 auto maps = game_.getEntityManager().getEntitiesWithComponents<
15 MappableComponent>();
16
12 for (id_type entity : entities) 17 for (id_type entity : entities)
13 { 18 {
14 auto& transformable = game_.getEntityManager().getComponent<TransformableComponent>(entity); 19 auto& transformable = game_.getEntityManager().
15 auto& ponderable = game_.getEntityManager().getComponent<PonderableComponent>(entity); 20 getComponent<TransformableComponent>(entity);
21
22 auto& ponderable = game_.getEntityManager().
23 getComponent<PonderableComponent>(entity);
16 24
17 // Accelerate 25 // Accelerate
18 ponderable.setVelocityX(ponderable.getVelocityX() + ponderable.getAccelX() * dt); 26 ponderable.setVelocityX(
19 ponderable.setVelocityY(ponderable.getVelocityY() + ponderable.getAccelY() * dt); 27 ponderable.getVelocityX() + ponderable.getAccelX() * dt);
28
29 ponderable.setVelocityY(
30 ponderable.getVelocityY() + ponderable.getAccelY() * dt);
31
32 const double oldX = transformable.getX();
33 const double oldY = transformable.getY();
34 const double oldRight = oldX + transformable.getW();
35 const double oldBottom = oldY + transformable.getH();
36
37 double newX = oldX + ponderable.getVelocityX() * dt;
38 double newY = oldY + ponderable.getVelocityY() * dt;
39
40 if (ponderable.getVelocityY() > 0.0)
41 {
42 ponderable.setState(PonderableComponent::State::falling);
43 }
44
45 for (id_type mapEntity : maps)
46 {
47 auto& mappable = game_.getEntityManager().
48 getComponent<MappableComponent>(mapEntity);
49
50 if (newX < oldX)
51 {
52 for (auto it = mappable.getLeftBoundaries().lower_bound(oldX);
53 (it != std::end(mappable.getLeftBoundaries())) && (it->first >= newX);
54 it++)
55 {
56 if ((oldBottom > it->second.getLower())
57 && (oldY < it->second.getUpper()))
58 {
59 // We have a collision!
60 processCollision(
61 entity,
62 Direction::left,
63 newX,
64 newY,
65 it->first,
66 it->second.getType());
67
68 break;
69 }
70 }
71 } else if (newX > oldX)
72 {
73 for (auto it = mappable.getRightBoundaries().lower_bound(oldRight);
74 (it != std::end(mappable.getRightBoundaries()))
75 && (it->first <= (newX + transformable.getW()));
76 it++)
77 {
78 if ((oldBottom > it->second.getLower())
79 && (oldY < it->second.getUpper()))
80 {
81 // We have a collision!
82 processCollision(
83 entity,
84 Direction::right,
85 newX,
86 newY,
87 it->first,
88 it->second.getType());
89
90 break;
91 }
92 }
93 }
94
95 if (newY < oldY)
96 {
97 for (auto it = mappable.getUpBoundaries().lower_bound(oldY);
98 (it != std::end(mappable.getUpBoundaries())) && (it->first >= newY);
99 it++)
100 {
101 if ((oldRight > it->second.getLower())
102 && (oldX < it->second.getUpper()))
103 {
104 // We have a collision!
105 processCollision(
106 entity,
107 Direction::up,
108 newX,
109 newY,
110 it->first,
111 it->second.getType());
112
113 break;
114 }
115 }
116 } else if (newY > oldY)
117 {
118 for (auto it = mappable.getDownBoundaries().lower_bound(oldBottom);
119 (it != std::end(mappable.getDownBoundaries()))
120 && (it->first <= (newY + transformable.getH()));
121 it++)
122 {
123 if ((oldRight > it->second.getLower())
124 && (oldX < it->second.getUpper()))
125 {
126 // We have a collision!
127 processCollision(
128 entity,
129 Direction::down,
130 newX,
131 newY,
132 it->first,
133 it->second.getType());
134
135 break;
136 }
137 }
138 }
139 }
20 140
21 // Move 141 // Move
22 transformable.setX(transformable.getX() + ponderable.getVelocityX() * dt); 142 transformable.setX(newX);
23 transformable.setY(transformable.getY() + ponderable.getVelocityY() * dt); 143 transformable.setY(newY);
144 }
145}
146
147void PonderingSystem::initializeBody(
148 id_type entity,
149 PonderableComponent::Type type)
150{
151 auto& ponderable = game_.getEntityManager().
152 emplaceComponent<PonderableComponent>(entity, type);
153
154 if (type == PonderableComponent::Type::freefalling)
155 {
156 ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233));
157 ponderable.setState(PonderableComponent::State::falling);
158 }
159}
160
161void PonderingSystem::processCollision(
162 id_type entity,
163 Direction dir,
164 double& newX,
165 double& newY,
166 int axis,
167 MappableComponent::Boundary::Type type)
168{
169 auto& ponderable = game_.getEntityManager().
170 getComponent<PonderableComponent>(entity);
171
172 auto& transformable = game_.getEntityManager().
173 getComponent<TransformableComponent>(entity);
174
175 switch (type)
176 {
177 case MappableComponent::Boundary::Type::wall:
178 {
179 switch (dir)
180 {
181 case Direction::left:
182 {
183 newX = axis;
184 ponderable.setVelocityX(0.0);
185
186 break;
187 }
188
189 case Direction::right:
190 {
191 newX = axis - transformable.getW();
192 ponderable.setVelocityX(0.0);
193
194 break;
195 }
196
197 case Direction::up:
198 {
199 newY = axis;
200 ponderable.setVelocityY(0.0);
201
202 break;
203 }
204
205 case Direction::down:
206 {
207 newY = axis - transformable.getH();
208 ponderable.setVelocityY(0.0);
209
210 if (ponderable.getState() == PonderableComponent::State::falling)
211 {
212 ponderable.setState(PonderableComponent::State::grounded);
213 }
214
215 break;
216 }
217 }
218
219 break;
220 }
221
222 case MappableComponent::Boundary::Type::platform:
223 {
224 if (game_.getEntityManager().hasComponent<DroppableComponent>(entity))
225 {
226 auto& droppable = game_.getEntityManager().
227 getComponent<DroppableComponent>(entity);
228
229 if (droppable.isDroppable())
230 {
231 droppable.setDroppable(false);
232 } else {
233 newY = axis - transformable.getH();
234 ponderable.setVelocityY(0.0);
235
236 if (ponderable.getState() == PonderableComponent::State::falling)
237 {
238 ponderable.setState(PonderableComponent::State::grounded);
239 }
240 }
241 } else {
242 newY = axis - transformable.getH();
243 ponderable.setVelocityY(0.0);
244
245 if (ponderable.getState() == PonderableComponent::State::falling)
246 {
247 ponderable.setState(PonderableComponent::State::grounded);
248 }
249 }
250
251 break;
252 }
253
254 default:
255 {
256 // Not yet implemented.
257
258 break;
259 }
24 } 260 }
25} 261}
diff --git a/src/systems/pondering.h b/src/systems/pondering.h index 44e7600..a16622b 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h
@@ -2,6 +2,9 @@
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"
7#include "direction.h"
5 8
6class PonderingSystem : public System { 9class PonderingSystem : public System {
7public: 10public:
@@ -11,6 +14,19 @@ public:
11 } 14 }
12 15
13 void tick(double dt); 16 void tick(double dt);
17
18 void initializeBody(id_type entity, PonderableComponent::Type type);
19
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
14}; 30};
15 31
16#endif /* end of include guard: PONDERING_H_F2530E0E */ 32#endif /* end of include guard: PONDERING_H_F2530E0E */
diff --git a/src/world.cpp b/src/world.cpp new file mode 100644 index 0000000..9b1e4f6 --- /dev/null +++ b/src/world.cpp
@@ -0,0 +1,99 @@
1#include "world.h"
2#include <libxml/parser.h>
3#include <stdexcept>
4#include <cstring>
5#include "consts.h"
6
7inline xmlChar* getProp(xmlNodePtr node, const char* attr)
8{
9 xmlChar* key = xmlGetProp(node, reinterpret_cast<const xmlChar*>(attr));
10 if (key == nullptr)
11 {
12 throw std::invalid_argument("Error parsing world file");
13 }
14
15 return key;
16}
17
18World::World(std::string filename)
19{
20 xmlDocPtr doc = xmlParseFile(filename.c_str());
21 if (doc == nullptr)
22 {
23 throw std::invalid_argument("Cannot find world file");
24 }
25
26 xmlNodePtr top = xmlDocGetRootElement(doc);
27 if (top == nullptr)
28 {
29 throw std::invalid_argument("Error parsing world file");
30 }
31
32 if (xmlStrcmp(top->name, reinterpret_cast<const xmlChar*>("world")))
33 {
34 throw std::invalid_argument("Error parsing world file");
35 }
36
37 xmlChar* key = nullptr;
38
39 key = getProp(top, "startx");
40 startX_ = atoi(reinterpret_cast<char*>(key));
41 xmlFree(key);
42
43 key = getProp(top, "starty");
44 startY_ = atoi(reinterpret_cast<char*>(key));
45 xmlFree(key);
46
47 key = getProp(top, "startmap");
48 startMap_ = atoi(reinterpret_cast<char*>(key));
49 xmlFree(key);
50
51 for (xmlNodePtr node = top->xmlChildrenNode;
52 node != nullptr;
53 node = node->next)
54 {
55 if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("map")))
56 {
57 key = getProp(node, "id");
58 size_t mapId = atoi(reinterpret_cast<char*>(key));
59 xmlFree(key);
60
61 key = getProp(node, "title");
62 std::string mapTitle(reinterpret_cast<char*>(key));
63 xmlFree(key);
64
65 std::vector<int> mapTiles;
66
67 for (xmlNodePtr mapNode = node->xmlChildrenNode;
68 mapNode != nullptr;
69 mapNode = mapNode->next)
70 {
71 if (!xmlStrcmp(
72 mapNode->name,
73 reinterpret_cast<const xmlChar*>("environment")))
74 {
75 key = xmlNodeGetContent(mapNode);
76
77 mapTiles.clear();
78 mapTiles.push_back(atoi(strtok(reinterpret_cast<char*>(key), ",\n")));
79 for (size_t i = 1; i < (MAP_WIDTH * MAP_HEIGHT); i++)
80 {
81 mapTiles.push_back(atoi(strtok(nullptr, ",\n")));
82 }
83
84 xmlFree(key);
85 }
86 }
87
88 maps_.emplace(
89 std::piecewise_construct,
90 std::forward_as_tuple(mapId),
91 std::forward_as_tuple(
92 mapId,
93 std::move(mapTiles),
94 std::move(mapTitle)));
95 }
96 }
97
98 xmlFreeDoc(doc);
99}
diff --git a/src/world.h b/src/world.h new file mode 100644 index 0000000..b88adf4 --- /dev/null +++ b/src/world.h
@@ -0,0 +1,41 @@
1#ifndef WORLD_H_153C698B
2#define WORLD_H_153C698B
3
4#include <map>
5#include <string>
6#include "map.h"
7
8class World {
9public:
10
11 explicit World(std::string filename);
12
13 inline const Map& getMap(size_t id) const
14 {
15 return maps_.at(id);
16 }
17
18 inline size_t getStartingMapId() const
19 {
20 return startMap_;
21 }
22
23 inline int getStartingX() const
24 {
25 return startX_;
26 }
27
28 inline int getStartingY() const
29 {
30 return startY_;
31 }
32
33private:
34
35 std::map<size_t, Map> maps_;
36 size_t startMap_;
37 int startX_;
38 int startY_;
39};
40
41#endif /* end of include guard: WORLD_H_153C698B */