summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/algorithms.h12
-rw-r--r--src/component.h11
-rw-r--r--src/components/ai.cpp142
-rw-r--r--src/components/ai.h73
-rw-r--r--src/components/animatable.cpp27
-rw-r--r--src/components/animatable.h31
-rw-r--r--src/components/controllable.cpp71
-rw-r--r--src/components/controllable.h36
-rw-r--r--src/components/droppable.cpp11
-rw-r--r--src/components/droppable.h15
-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/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.cpp41
-rw-r--r--src/components/ponderable.h24
-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.cpp47
-rw-r--r--src/components/transformable.h27
-rw-r--r--src/components/user_movement.cpp100
-rw-r--r--src/components/user_movement.h19
-rw-r--r--src/consts.h3
-rw-r--r--src/direction.h11
-rw-r--r--src/entity.cpp46
-rw-r--r--src/entity.h64
-rw-r--r--src/entity_manager.cpp39
-rw-r--r--src/entity_manager.h197
-rw-r--r--src/entityfactory.cpp182
-rw-r--r--src/entityfactory.h15
-rw-r--r--src/game.cpp179
-rw-r--r--src/game.h51
-rw-r--r--src/main.cpp18
-rw-r--r--src/map.cpp151
-rw-r--r--src/map.h70
-rw-r--r--src/muxer.cpp61
-rw-r--r--src/renderer.cpp229
-rw-r--r--src/renderer.h2
-rw-r--r--src/system.h20
-rw-r--r--src/system_manager.h44
-rw-r--r--src/systems/controlling.cpp168
-rw-r--r--src/systems/controlling.h26
-rw-r--r--src/systems/pondering.cpp23
-rw-r--r--src/systems/pondering.h14
-rw-r--r--src/systems/rendering.cpp21
-rw-r--r--src/systems/rendering.h19
-rw-r--r--src/world.cpp150
-rw-r--r--src/world.h21
56 files changed, 1149 insertions, 2082 deletions
diff --git a/src/algorithms.h b/src/algorithms.h new file mode 100644 index 0000000..80e3e27 --- /dev/null +++ b/src/algorithms.h
@@ -0,0 +1,12 @@
1#ifndef ALGORITHMS_H_1DDC517E
2#define ALGORITHMS_H_1DDC517E
3
4template< typename ContainerT, typename PredicateT >
5void erase_if( ContainerT& items, const PredicateT& predicate ) {
6 for( auto it = items.begin(); it != items.end(); ) {
7 if( predicate(*it) ) it = items.erase(it);
8 else ++it;
9 }
10};
11
12#endif /* end of include guard: ALGORITHMS_H_1DDC517E */
diff --git a/src/component.h b/src/component.h new file mode 100644 index 0000000..b81dbee --- /dev/null +++ b/src/component.h
@@ -0,0 +1,11 @@
1#ifndef COMPONENT_H_F0CE4573
2#define COMPONENT_H_F0CE4573
3
4class Component {
5public:
6
7 virtual ~Component() = default;
8
9};
10
11#endif /* end of include guard: COMPONENT_H_F0CE4573 */
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.cpp b/src/components/animatable.cpp new file mode 100644 index 0000000..fcd277c --- /dev/null +++ b/src/components/animatable.cpp
@@ -0,0 +1,27 @@
1#include "animatable.h"
2
3AnimatableComponent::AnimatableComponent(const char* filename, int frame_width, int frame_height, int frames_across)
4 : texture(filename), frame_width(frame_width), frame_height(frame_height), frames_across(frames_across)
5{
6
7}
8
9int AnimatableComponent::getFrame() const
10{
11 return frame;
12}
13
14void AnimatableComponent::setFrame(int frame)
15{
16 this->frame = frame;
17}
18
19const Texture& AnimatableComponent::getTexture() const
20{
21 return texture;
22}
23
24Rectangle AnimatableComponent::getFrameRect() const
25{
26 return {frame_width * (frame % frames_across), frame_height * (frame / frames_across), frame_width, frame_height};
27}
diff --git a/src/components/animatable.h b/src/components/animatable.h new file mode 100644 index 0000000..cf6ee54 --- /dev/null +++ b/src/components/animatable.h
@@ -0,0 +1,31 @@
1#ifndef SPRITE_RENDERABLE_H_D3AACBBF
2#define SPRITE_RENDERABLE_H_D3AACBBF
3
4#include "component.h"
5#include "renderer.h"
6#include "direction.h"
7
8class AnimatableComponent : public Component {
9 public:
10 AnimatableComponent(const char* filename, int frame_width, int frame_height, int frames_across);
11
12 int getFrame() const;
13 void setFrame(int frame);
14
15 const Texture& getTexture() const;
16 Rectangle getFrameRect() const;
17
18 void setDirection(Direction dir) {};
19 void setWalking(bool w) {};
20 void setJumping(bool w) {};
21 void setCrouching(bool w) {};
22
23 private:
24 Texture texture;
25 int frame_width;
26 int frame_height;
27 int frames_across;
28 int frame = 0;
29};
30
31#endif /* end of include guard: SPRITE_RENDERABLE_H_D3AACBBF */
diff --git a/src/components/controllable.cpp b/src/components/controllable.cpp new file mode 100644 index 0000000..a4d45f2 --- /dev/null +++ b/src/components/controllable.cpp
@@ -0,0 +1,71 @@
1#include "controllable.h"
2
3int ControllableComponent::getLeftKey() const
4{
5 return leftKey;
6}
7
8void ControllableComponent::setLeftKey(int k)
9{
10 leftKey = k;
11}
12
13int ControllableComponent::getRightKey() const
14{
15 return rightKey;
16}
17
18void ControllableComponent::setRightKey(int k)
19{
20 rightKey = k;
21}
22
23int ControllableComponent::getJumpKey() const
24{
25 return jumpKey;
26}
27
28void ControllableComponent::setJumpKey(int k)
29{
30 jumpKey = k;
31}
32
33int ControllableComponent::getDropKey() const
34{
35 return dropKey;
36}
37
38void ControllableComponent::setDropKey(int k)
39{
40 dropKey = k;
41}
42
43bool ControllableComponent::isFrozen() const
44{
45 return frozen;
46}
47
48void ControllableComponent::setFrozen(bool f)
49{
50 frozen = f;
51}
52
53bool ControllableComponent::isHoldingLeft() const
54{
55 return holdingLeft;
56}
57
58void ControllableComponent::setHoldingLeft(bool f)
59{
60 holdingLeft = f;
61}
62
63bool ControllableComponent::isHoldingRight() const
64{
65 return holdingRight;
66}
67
68void ControllableComponent::setHoldingRight(bool f)
69{
70 holdingRight = f;
71}
diff --git a/src/components/controllable.h b/src/components/controllable.h new file mode 100644 index 0000000..baccf13 --- /dev/null +++ b/src/components/controllable.h
@@ -0,0 +1,36 @@
1#ifndef CONTROLLABLE_H_4E0B85B4
2#define CONTROLLABLE_H_4E0B85B4
3
4#include "component.h"
5#include "renderer.h"
6
7class ControllableComponent : public Component {
8 public:
9 int getLeftKey() const;
10 void setLeftKey(int k);
11 int getRightKey() const;
12 void setRightKey(int k);
13 int getJumpKey() const;
14 void setJumpKey(int k);
15 int getDropKey() const;
16 void setDropKey(int k);
17
18 bool isFrozen() const;
19 void setFrozen(bool f);
20 bool isHoldingLeft() const;
21 void setHoldingLeft(bool f);
22 bool isHoldingRight() const;
23 void setHoldingRight(bool f);
24
25 private:
26 int leftKey = GLFW_KEY_LEFT;
27 int rightKey = GLFW_KEY_RIGHT;
28 int jumpKey = GLFW_KEY_UP;
29 int dropKey = GLFW_KEY_DOWN;
30
31 bool frozen = false;
32 bool holdingLeft = false;
33 bool holdingRight = false;
34};
35
36#endif /* end of include guard: CONTROLLABLE_H_4E0B85B4 */
diff --git a/src/components/droppable.cpp b/src/components/droppable.cpp new file mode 100644 index 0000000..534fd9a --- /dev/null +++ b/src/components/droppable.cpp
@@ -0,0 +1,11 @@
1#include "droppable.h"
2
3void DroppableComponent::setDroppable(bool can)
4{
5 droppable = can;
6}
7
8bool DroppableComponent::isDroppable() const
9{
10 return droppable;
11}
diff --git a/src/components/droppable.h b/src/components/droppable.h new file mode 100644 index 0000000..83fcb9d --- /dev/null +++ b/src/components/droppable.h
@@ -0,0 +1,15 @@
1#ifndef DROPPABLE_H_5DB254EF
2#define DROPPABLE_H_5DB254EF
3
4#include "component.h"
5
6class DroppableComponent : public Component {
7 public:
8 void setDroppable(bool can);
9 bool isDroppable() const;
10
11 private:
12 bool droppable = false;
13};
14
15#endif /* end of include guard: DROPPABLE_H_5DB254EF */
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/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.cpp b/src/components/ponderable.cpp new file mode 100644 index 0000000..2cfa6a6 --- /dev/null +++ b/src/components/ponderable.cpp
@@ -0,0 +1,41 @@
1#include "ponderable.h"
2
3double PonderableComponent::getVelocityX() const
4{
5 return velocityX;
6}
7
8void PonderableComponent::setVelocityX(double v)
9{
10 velocityX = v;
11}
12
13double PonderableComponent::getVelocityY() const
14{
15 return velocityY;
16}
17
18void PonderableComponent::setVelocityY(double v)
19{
20 velocityY = v;
21}
22
23double PonderableComponent::getAccelX() const
24{
25 return accelX;
26}
27
28void PonderableComponent::setAccelX(double v)
29{
30 accelX = v;
31}
32
33double PonderableComponent::getAccelY() const
34{
35 return accelY;
36}
37
38void PonderableComponent::setAccelY(double v)
39{
40 accelY = v;
41}
diff --git a/src/components/ponderable.h b/src/components/ponderable.h new file mode 100644 index 0000000..c836d2a --- /dev/null +++ b/src/components/ponderable.h
@@ -0,0 +1,24 @@
1#ifndef TANGIBLE_H_746DB3EE
2#define TANGIBLE_H_746DB3EE
3
4#include "component.h"
5
6class PonderableComponent : public Component {
7 public:
8 double getVelocityX() const;
9 void setVelocityX(double v);
10 double getVelocityY() const;
11 void setVelocityY(double v);
12 double getAccelX() const;
13 void setAccelX(double v);
14 double getAccelY() const;
15 void setAccelY(double v);
16
17 private:
18 double velocityX = 0.0;
19 double velocityY = 0.0;
20 double accelX = 0.0;
21 double accelY = 0.0;
22};
23
24#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.cpp b/src/components/transformable.cpp new file mode 100644 index 0000000..89b1e5d --- /dev/null +++ b/src/components/transformable.cpp
@@ -0,0 +1,47 @@
1#include "transformable.h"
2
3TransformableComponent::TransformableComponent(double x, double y, int w, int h)
4 : x(x), y(y), w(w), h(h)
5{
6
7}
8
9double TransformableComponent::getX() const
10{
11 return x;
12}
13
14double TransformableComponent::getY() const
15{
16 return y;
17}
18
19int TransformableComponent::getW() const
20{
21 return w;
22}
23
24int TransformableComponent::getH() const
25{
26 return h;
27}
28
29void TransformableComponent::setX(double v)
30{
31 x = v;
32}
33
34void TransformableComponent::setY(double v)
35{
36 y = v;
37}
38
39void TransformableComponent::setW(int v)
40{
41 w = v;
42}
43
44void TransformableComponent::setH(int v)
45{
46 h = v;
47}
diff --git a/src/components/transformable.h b/src/components/transformable.h new file mode 100644 index 0000000..69f4f0e --- /dev/null +++ b/src/components/transformable.h
@@ -0,0 +1,27 @@
1#ifndef LOCATABLE_H_39E526CA
2#define LOCATABLE_H_39E526CA
3
4#include "component.h"
5
6class TransformableComponent : public Component {
7 public:
8 TransformableComponent(double x, double y, int w, int h);
9
10 double getX() const;
11 double getY() const;
12 int getW() const;
13 int getH() const;
14
15 void setX(double v);
16 void setY(double v);
17 void setW(int v);
18 void setH(int v);
19
20 private:
21 double x;
22 double y;
23 int w;
24 int h;
25};
26
27#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
diff --git a/src/consts.h b/src/consts.h index 804c761..4595719 100644 --- a/src/consts.h +++ b/src/consts.h
@@ -11,4 +11,7 @@ const int MAP_HEIGHT = GAME_HEIGHT/TILE_HEIGHT - 1;
11const int FRAMES_PER_SECOND = 60; 11const int FRAMES_PER_SECOND = 60;
12const double SECONDS_PER_FRAME = 1.0 / FRAMES_PER_SECOND; 12const double SECONDS_PER_FRAME = 1.0 / FRAMES_PER_SECOND;
13 13
14#define JUMP_VELOCITY(h, l) (-2 * (h) / (l))
15#define JUMP_GRAVITY(h, l) (2 * ((h) / (l)) / (l))
16
14#endif 17#endif
diff --git a/src/direction.h b/src/direction.h new file mode 100644 index 0000000..32d6b41 --- /dev/null +++ b/src/direction.h
@@ -0,0 +1,11 @@
1#ifndef DIRECTION_H_9C49EAFD
2#define DIRECTION_H_9C49EAFD
3
4enum class Direction {
5 Left,
6 Right,
7 Up,
8 Down
9};
10
11#endif /* end of include guard: DIRECTION_H_9C49EAFD */
diff --git a/src/entity.cpp b/src/entity.cpp deleted file mode 100644 index 2b6cd7f..0000000 --- a/src/entity.cpp +++ /dev/null
@@ -1,46 +0,0 @@
1#include "entity.h"
2
3void Entity::addComponent(std::shared_ptr<Component> c)
4{
5 components.push_back(c);
6}
7
8void Entity::send(Game& game, const Message& msg)
9{
10 for (auto component : components)
11 {
12 component->receive(game, *this, msg);
13 }
14}
15
16void Entity::tick(Game& game, double dt)
17{
18 for (auto component : components)
19 {
20 component->tick(game, *this, dt);
21 }
22}
23
24void Entity::input(Game& game, int key, int action)
25{
26 for (auto component : components)
27 {
28 component->input(game, *this, key, action);
29 }
30}
31
32void Entity::render(Game& game, Texture& buffer)
33{
34 for (auto component : components)
35 {
36 component->render(game, *this, buffer);
37 }
38}
39
40void Entity::detectCollision(Game& game, Entity& collider, std::pair<double, double> old_position)
41{
42 for (auto component : components)
43 {
44 component->detectCollision(game, *this, collider, old_position);
45 }
46}
diff --git a/src/entity.h b/src/entity.h deleted file mode 100644 index 7f09f2d..0000000 --- a/src/entity.h +++ /dev/null
@@ -1,64 +0,0 @@
1#ifndef ENTITY_H
2#define ENTITY_H
3
4#include <list>
5#include "renderer.h"
6
7class Game;
8class Map;
9class Entity;
10class Component;
11
12class Message {
13 public:
14 enum class Type {
15 walkLeft,
16 walkRight,
17 stopWalking,
18 setHorizontalVelocity,
19 setVerticalVelocity,
20 collision,
21 jump,
22 stopJump,
23 drop,
24 canDrop,
25 cantDrop,
26 die,
27 stopDying,
28 hitTheGround
29 };
30
31 Message(Type type) : type(type) {}
32
33 Type type;
34 Entity* collisionEntity;
35 int dropAxis;
36 double velocity;
37};
38
39class Entity {
40 public:
41 void addComponent(std::shared_ptr<Component> c);
42 void send(Game& game, const Message& msg);
43 void tick(Game& game, double dt);
44 void input(Game& game, int key, int action);
45 void render(Game& game, Texture& buffer);
46 void detectCollision(Game& game, Entity& collider, std::pair<double, double> old_position);
47
48 std::pair<double, double> position;
49 std::pair<int, int> size;
50
51 private:
52 std::list<std::shared_ptr<Component>> components;
53};
54
55class Component {
56 public:
57 virtual void receive(Game&, Entity&, const Message&) {}
58 virtual void render(Game&, Entity&, Texture&) {}
59 virtual void tick(Game&, Entity&, double) {}
60 virtual void input(Game&, Entity&, int, int) {}
61 virtual void detectCollision(Game&, Entity&, Entity&, std::pair<double, double>) {}
62};
63
64#endif
diff --git a/src/entity_manager.cpp b/src/entity_manager.cpp new file mode 100644 index 0000000..f792e17 --- /dev/null +++ b/src/entity_manager.cpp
@@ -0,0 +1,39 @@
1#ifndef ENTITY_MANAGER_CPP_42D78C22
2#define ENTITY_MANAGER_CPP_42D78C22
3
4#include "entity_manager.h"
5
6template <>
7std::set<EntityManager::id_type> EntityManager::getEntitiesWithComponents<>(
8 std::set<std::type_index>& componentTypes)
9{
10 if (cachedComponents.count(componentTypes) == 1)
11 {
12 return cachedComponents[componentTypes];
13 }
14
15 std::set<id_type>& cache = cachedComponents[componentTypes];
16 for (id_type entity = 0; entity < entities.size(); entity++)
17 {
18 EntityData& data = entities[entity];
19 bool cacheEntity = true;
20
21 for (auto& componentType : componentTypes)
22 {
23 if (data.components.count(componentType) == 0)
24 {
25 cacheEntity = false;
26 break;
27 }
28 }
29
30 if (cacheEntity)
31 {
32 cache.insert(entity);
33 }
34 }
35
36 return cache;
37}
38
39#endif /* end of include guard: ENTITY_MANAGER_CPP_42D78C22 */
diff --git a/src/entity_manager.h b/src/entity_manager.h new file mode 100644 index 0000000..9068fe3 --- /dev/null +++ b/src/entity_manager.h
@@ -0,0 +1,197 @@
1#ifndef ENTITY_MANAGER_H_C5832F11
2#define ENTITY_MANAGER_H_C5832F11
3
4#include <map>
5#include <vector>
6#include <typeindex>
7#include <set>
8#include <stdexcept>
9#include "component.h"
10#include "algorithms.h"
11
12class EntityManager {
13private:
14
15 struct EntityData {
16 std::map<std::type_index, std::unique_ptr<Component>> components;
17 };
18
19 using database_type = std::vector<EntityData>;
20
21public:
22
23 using id_type = database_type::size_type;
24
25private:
26
27 database_type entities;
28 std::vector<bool> slotAvailable;
29 std::map<std::set<std::type_index>, std::set<id_type>> cachedComponents;
30
31 id_type nextEntityID = 0;
32
33 template <class T, class... R>
34 std::set<id_type> getEntitiesWithComponentsHelper(
35 std::set<std::type_index>& componentTypes)
36 {
37 componentTypes.insert(typeid(T));
38
39 return getEntitiesWithComponents<R...>(componentTypes);
40 }
41
42 template <class... R>
43 std::set<id_type> getEntitiesWithComponents(
44 std::set<std::type_index>& componentTypes)
45 {
46 return getEntitiesWithComponentsHelper<R...>(componentTypes);
47 }
48
49public:
50
51 EntityManager() = default;
52
53 EntityManager(const EntityManager& copy) = delete;
54
55 id_type emplaceEntity()
56 {
57 if (nextEntityID >= entities.size())
58 {
59 // If the database is saturated, add a new element for the new entity.
60 entities.emplace_back();
61 slotAvailable.push_back(false);
62
63 return nextEntityID++;
64 } else {
65 // If there is an available slot in the database, use it.
66 id_type id = nextEntityID++;
67 slotAvailable[id] = false;
68
69 // Fast forward the next available slot pointer to an available slot.
70 while ((nextEntityID < entities.size()) && !slotAvailable[nextEntityID])
71 {
72 nextEntityID++;
73 }
74
75 return id;
76 }
77 }
78
79 void deleteEntity(id_type entity)
80 {
81 if ((entity >= entities.size()) || slotAvailable[entity])
82 {
83 throw std::invalid_argument("Cannot delete non-existent entity");
84 }
85
86 // Uncache components
87 for (auto& cache : cachedComponents)
88 {
89 cache.second.erase(entity);
90 }
91
92 // Destroy the data
93 entities[entity].components.clear();
94
95 // Mark the slot as available
96 slotAvailable[entity] = true;
97
98 if (entity < nextEntityID)
99 {
100 nextEntityID = entity;
101 }
102 }
103
104 template <class T, class... Args>
105 T& emplaceComponent(id_type entity, Args&&... args)
106 {
107 if ((entity >= entities.size()) || slotAvailable[entity])
108 {
109 throw std::invalid_argument("Cannot delete non-existent entity");
110 }
111
112 EntityData& data = entities[entity];
113 std::type_index componentType = typeid(T);
114
115 if (data.components.count(componentType))
116 {
117 throw std::invalid_argument("Cannot emplace already-existent component");
118 }
119
120 // Initialize the component
121 std::unique_ptr<T> ptr(new T(std::forward<Args>(args)...));
122 T& component = *ptr;
123 data.components[componentType] = std::move(ptr);
124
125 // Invalidate related caches
126 erase_if(
127 cachedComponents,
128 [&componentType] (
129 std::pair<const std::set<std::type_index>, std::set<id_type>>& cache) {
130 return cache.first.count(componentType) == 1;
131 });
132
133 return component;
134 }
135
136 template <class T>
137 void removeComponent(id_type entity)
138 {
139 if ((entity >= entities.size()) || slotAvailable[entity])
140 {
141 throw std::invalid_argument("Cannot delete non-existent entity");
142 }
143
144 EntityData& data = entities[entity];
145 std::type_index componentType = typeid(T);
146
147 if (!data.components.count(componentType))
148 {
149 throw std::invalid_argument("Cannot delete non-existent component");
150 }
151
152 // Destroy the component
153 data.components.erase(componentType);
154
155 // Uncache the component
156 for (auto& cache : cachedComponents)
157 {
158 if (cache.first.count(componentType) == 1)
159 {
160 cache.second.erase(entity);
161 }
162 }
163 }
164
165 template <class T>
166 T& getComponent(id_type entity)
167 {
168 if ((entity >= entities.size()) || slotAvailable[entity])
169 {
170 throw std::invalid_argument("Cannot delete non-existent entity");
171 }
172
173 EntityData& data = entities[entity];
174 std::type_index componentType = typeid(T);
175
176 if (!data.components.count(componentType))
177 {
178 throw std::invalid_argument("Cannot get non-existent component");
179 }
180
181 return *dynamic_cast<T*>(data.components[componentType].get());
182 }
183
184 template <class... R>
185 std::set<id_type> getEntitiesWithComponents()
186 {
187 std::set<std::type_index> componentTypes;
188
189 return getEntitiesWithComponentsHelper<R...>(componentTypes);
190 }
191};
192
193template <>
194std::set<EntityManager::id_type> EntityManager::getEntitiesWithComponents<>(
195 std::set<std::type_index>& componentTypes);
196
197#endif /* end of include guard: ENTITY_MANAGER_H_C5832F11 */
diff --git a/src/entityfactory.cpp b/src/entityfactory.cpp deleted file mode 100644 index b80fe99..0000000 --- a/src/entityfactory.cpp +++ /dev/null
@@ -1,182 +0,0 @@
1#include "entityfactory.h"
2#include <libxml/parser.h>
3#include "muxer.h"
4#include <cstdio>
5#include <map>
6#include <list>
7#include "components/static_image.h"
8#include "components/simple_collider.h"
9#include "components/physics_body.h"
10#include "components/ai.h"
11#include "game.h"
12
13void parseEntityAIData(AI& ai, xmlNodePtr node, const std::map<std::string, int>& items)
14{
15 xmlChar* key;
16
17 for (xmlNodePtr aiNode = node->xmlChildrenNode; aiNode != NULL; aiNode = aiNode->next)
18 {
19 if (!xmlStrcmp(aiNode->name, (xmlChar*) "move"))
20 {
21 MoveAIAction::Direction dir;
22 int len;
23 int speed;
24
25 key = xmlGetProp(aiNode, (xmlChar*) "direction");
26 if (key == 0) exit(2);
27 if (!xmlStrcmp(key, (xmlChar*) "left"))
28 {
29 dir = MoveAIAction::Direction::Left;
30 } else if (!xmlStrcmp(key, (xmlChar*) "right"))
31 {
32 dir = MoveAIAction::Direction::Right;
33 } else if (!xmlStrcmp(key, (xmlChar*) "up"))
34 {
35 dir = MoveAIAction::Direction::Up;
36 } else if (!xmlStrcmp(key, (xmlChar*) "down"))
37 {
38 dir = MoveAIAction::Direction::Down;
39 } else {
40 exit(2);
41 }
42 xmlFree(key);
43
44 key = xmlGetProp(aiNode, (xmlChar*) "length");
45 if (key != 0)
46 {
47 len = atoi((char*) key);
48 } else {
49 key = xmlGetProp(aiNode, (xmlChar*) "length-var");
50 if (key == 0) exit(2);
51 std::string varName = (char*) key;
52 len = items.at(varName);
53 }
54 xmlFree(key);
55
56 key = xmlGetProp(aiNode, (xmlChar*) "speed");
57 if (key != 0)
58 {
59 speed = atoi((char*) key);
60 } else {
61 key = xmlGetProp(aiNode, (xmlChar*) "speed-var");
62 if (key == 0) exit(2);
63 std::string varName = (char*) key;
64 speed = items.at(varName);
65 }
66 xmlFree(key);
67
68 ai.addAction(std::make_shared<MoveAIAction>(dir, len, speed));
69 } else if (!xmlStrcmp(aiNode->name, (xmlChar*) "switch"))
70 {
71 key = xmlGetProp(aiNode, (xmlChar*) "item");
72 if (key == 0) exit(2);
73 std::string switchItem = (char*) key;
74 xmlFree(key);
75
76 for (xmlNodePtr switchNode = aiNode->xmlChildrenNode; switchNode != NULL; switchNode = switchNode->next)
77 {
78 if (!xmlStrcmp(switchNode->name, (xmlChar*) "case"))
79 {
80 key = xmlGetProp(switchNode, (xmlChar*) "value");
81 if (key == 0) exit(2);
82 int caseValue = atoi((char*) key);
83 xmlFree(key);
84
85 if (items.at(switchItem) == caseValue)
86 {
87 parseEntityAIData(ai, switchNode, items);
88 }
89 }
90 }
91 }
92 }
93}
94
95std::shared_ptr<Entity> EntityFactory::createNamedEntity(const std::string name, const std::map<std::string, int>& items)
96{
97 xmlDocPtr doc = xmlParseFile("res/entities.xml");
98 if (doc == nullptr)
99 {
100 fprintf(stderr, "Error reading entities\n");
101 exit(-1);
102 }
103
104 xmlNodePtr top = xmlDocGetRootElement(doc);
105 if (top == nullptr)
106 {
107 fprintf(stderr, "Empty entities file\n");
108 exit(-1);
109 }
110
111 if (xmlStrcmp(top->name, (const xmlChar*) "entities"))
112 {
113 fprintf(stderr, "Invalid entities definition\n");
114 exit(-1);
115 }
116
117 auto entity = std::make_shared<Entity>();
118
119 xmlChar* key;
120 for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next)
121 {
122 if (!xmlStrcmp(node->name, (xmlChar*) "entity"))
123 {
124 key = xmlGetProp(node, (xmlChar*) "id");
125 if (key == 0) exit(-1);
126 std::string entityID = (char*) key;
127 xmlFree(key);
128
129 if (entityID == name)
130 {
131 key = xmlGetProp(node, (xmlChar*) "sprite");
132 if (key == 0) exit(-1);
133 auto spriteComponent = std::make_shared<StaticImageComponent>((char*) key);
134 entity->addComponent(spriteComponent);
135 xmlFree(key);
136
137 auto physicsComponent = std::make_shared<PhysicsBodyComponent>();
138 entity->addComponent(physicsComponent);
139
140 key = xmlGetProp(node, (xmlChar*) "width");
141 if (key == 0) exit(-1);
142 entity->size.first = atoi((char*) key);
143 xmlFree(key);
144
145 key = xmlGetProp(node, (xmlChar*) "height");
146 if (key == 0) exit(-1);
147 entity->size.second = atoi((char*) key);
148 xmlFree(key);
149
150 bool addAI = false;
151 auto aiComponent = std::make_shared<AIComponent>();
152
153 for (xmlNodePtr entityNode = node->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next)
154 {
155 if (!xmlStrcmp(entityNode->name, (xmlChar*) "ai"))
156 {
157 addAI = true;
158
159 xmlChar* chanceKey = xmlGetProp(entityNode, (xmlChar*) "chance");
160 if (chanceKey == 0) exit(2);
161 int chance = atoi((char*) chanceKey);
162 xmlFree(chanceKey);
163
164 AI& ai = aiComponent->emplaceAI(chance);
165 parseEntityAIData(ai, entityNode, items);
166 }
167 }
168
169 if (addAI)
170 {
171 entity->addComponent(aiComponent);
172 }
173
174 break;
175 }
176 }
177 }
178
179 xmlFreeDoc(doc);
180
181 return entity;
182}
diff --git a/src/entityfactory.h b/src/entityfactory.h deleted file mode 100644 index 56f7216..0000000 --- a/src/entityfactory.h +++ /dev/null
@@ -1,15 +0,0 @@
1#ifndef ENTITYFACTORY_H
2#define ENTITYFACTORY_H
3
4#include <string>
5#include <map>
6
7class Entity;
8class Map;
9
10class EntityFactory {
11 public:
12 static std::shared_ptr<Entity> createNamedEntity(const std::string name, const std::map<std::string, int>& items);
13};
14
15#endif
diff --git a/src/game.cpp b/src/game.cpp index 673c804..5d1ec18 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -1,178 +1,75 @@
1#include "game.h" 1#include "game.h"
2#include <cstdlib> 2#include "components/animatable.h"
3#include "renderer.h" 3#include "components/transformable.h"
4#include "muxer.h" 4#include "components/controllable.h"
5#include "map.h" 5#include "components/droppable.h"
6#include "components/user_movement.h" 6#include "components/ponderable.h"
7#include "components/player_physics.h" 7#include "systems/rendering.h"
8#include "components/player_sprite.h" 8#include "systems/controlling.h"
9#include "components/map_render.h" 9#include "systems/pondering.h"
10#include "components/map_collision.h"
11#include "consts.h"
12
13Game::Game(const char* mapfile) : world(mapfile)
14{
15 // Set up entities
16 player = std::make_shared<Entity>();
17 player->position = world.getStartingPosition();
18 player->size = std::make_pair(10.0,12.0);
19
20 auto player_input = std::make_shared<UserMovementComponent>();
21 player->addComponent(player_input);
22
23 auto player_physics = std::make_shared<PlayerPhysicsComponent>();
24 player->addComponent(player_physics);
25
26 auto player_anim = std::make_shared<PlayerSpriteComponent>();
27 player->addComponent(player_anim);
28
29 const Map& startingMap = world.getStartingMap();
30 save = {&startingMap, player->position};
31
32 loadMap(startingMap, player->position);
33}
34 10
35void key_callback(GLFWwindow* window, int key, int, int action, int) 11void key_callback(GLFWwindow* window, int key, int, int action, int)
36{ 12{
37 Game* game = (Game*) glfwGetWindowUserPointer(window); 13 Game& game = *((Game*) glfwGetWindowUserPointer(window));
38 14
39 if ((key == GLFW_KEY_ESCAPE) && (action == GLFW_PRESS)) 15 if ((action == GLFW_PRESS) && (key == GLFW_KEY_ESCAPE))
40 { 16 {
41 game->shouldQuit = true; 17 game.shouldQuit = true;
18
19 return;
42 } 20 }
43 21
44 for (auto entity : game->entities) 22 game.systemManager.getSystem<ControllingSystem>().input(key, action);
45 {
46 entity->input(*game, key, action);
47 }
48} 23}
49 24
50void Game::execute(GLFWwindow* window) 25Game::Game(GLFWwindow* window) : window(window)
51{ 26{
27 systemManager.emplaceSystem<ControllingSystem>(*this);
28 systemManager.emplaceSystem<RenderingSystem>(*this);
29 systemManager.emplaceSystem<PonderingSystem>(*this);
30
31 int player = entityManager.emplaceEntity();
32 entityManager.emplaceComponent<AnimatableComponent>(player, "res/Starla.png", 10, 12, 6);
33 entityManager.emplaceComponent<TransformableComponent>(player, 203, 44, 10, 12);
34 entityManager.emplaceComponent<DroppableComponent>(player);
35 entityManager.emplaceComponent<PonderableComponent>(player);
36 entityManager.emplaceComponent<ControllableComponent>(player);
37
52 glfwSwapInterval(1); 38 glfwSwapInterval(1);
53 glfwSetWindowUserPointer(window, this); 39 glfwSetWindowUserPointer(window, this);
54 glfwSetKeyCallback(window, key_callback); 40 glfwSetKeyCallback(window, key_callback);
55 41}
56 Texture buffer(GAME_WIDTH, GAME_HEIGHT);
57 42
43void Game::execute()
44{
58 double lastTime = glfwGetTime(); 45 double lastTime = glfwGetTime();
59 const double dt = 0.01; 46 const double dt = 0.01;
60 double accumulator = 0.0; 47 double accumulator = 0.0;
61 48
62 while (!(shouldQuit || glfwWindowShouldClose(window))) 49 while (!(shouldQuit || glfwWindowShouldClose(window)))
63 { 50 {
64 double currentTime = glfwGetTime(); 51 double currentTime = glfwGetTime();
65 double frameTime = currentTime - lastTime; 52 double frameTime = currentTime - lastTime;
66 lastTime = currentTime; 53 lastTime = currentTime;
67 54
68 // Should we load a new world?
69 if (newWorld)
70 {
71 newWorld = false;
72 entities.clear();
73 entities = std::move(nextEntities);
74
75 player->position = nextPosition;
76 }
77
78 // Handle input
79 glfwPollEvents(); 55 glfwPollEvents();
80 56
81 // Tick!
82 accumulator += frameTime; 57 accumulator += frameTime;
83 while (accumulator >= dt) 58 while (accumulator >= dt)
84 { 59 {
85 for (auto entity : entities) 60 systemManager.getSystem<ControllingSystem>().tick(dt);
86 { 61 systemManager.getSystem<PonderingSystem>().tick(dt);
87 entity->tick(*this, dt); 62
88 }
89
90 accumulator -= dt; 63 accumulator -= dt;
91 } 64 }
92
93 // Do any scheduled tasks
94 for (auto& task : scheduled)
95 {
96 task.first -= frameTime;
97
98 if (task.first <= 0)
99 {
100 task.second();
101 }
102 }
103
104 scheduled.remove_if([] (std::pair<double, std::function<void ()>> value) { return value.first <= 0; });
105
106 // Do rendering
107 buffer.fill(buffer.entirety(), 0, 0, 0);
108 for (auto entity : entities)
109 {
110 entity->render(*this, buffer);
111 }
112
113 buffer.renderScreen();
114 }
115}
116
117void Game::loadMap(const Map& map, std::pair<double, double> position)
118{
119 auto mapEn = std::make_shared<Entity>();
120
121 auto map_render = std::make_shared<MapRenderComponent>(map);
122 mapEn->addComponent(map_render);
123
124 auto map_collision = std::make_shared<MapCollisionComponent>(map);
125 mapEn->addComponent(map_collision);
126
127 // Map in the back, player on top, rest of entities in between
128 nextEntities.clear();
129 nextEntities.push_back(mapEn);
130 map.createEntities(nextEntities);
131 nextEntities.push_back(player);
132
133 newWorld = true;
134
135 currentMap = &map;
136 nextPosition = position;
137}
138 65
139void Game::detectCollision(Entity& collider, std::pair<double, double> old_position) 66 systemManager.getSystem<RenderingSystem>().tick(frameTime);
140{
141 for (auto entity : entities)
142 {
143 entity->detectCollision(*this, collider, old_position);
144 } 67 }
145} 68}
146 69
147void Game::saveGame() 70EntityManager& Game::getEntityManager()
148{ 71{
149 save = {currentMap, player->position}; 72 return entityManager;
150} 73}
151 74
152void Game::schedule(double time, std::function<void ()> callback)
153{
154 scheduled.emplace_front(time, std::move(callback));
155}
156
157void Game::playerDie()
158{
159 player->send(*this, Message::Type::die);
160
161 playSound("res/Hit_Hurt5.wav", 0.25);
162
163 schedule(0.75, [&] () {
164 if (*currentMap != *save.map)
165 {
166 loadMap(*save.map, save.position);
167 } else {
168 player->position = save.position;
169 }
170
171 player->send(*this, Message::Type::stopDying);
172 });
173}
174 75
175const World& Game::getWorld() const
176{
177 return world;
178}
diff --git a/src/game.h b/src/game.h index dd4b2f7..ec667c8 100644 --- a/src/game.h +++ b/src/game.h
@@ -1,45 +1,24 @@
1#ifndef GAME_H 1#ifndef GAME_H_1014DDC9
2#define GAME_H 2#define GAME_H_1014DDC9
3 3
4#include <memory> 4#include "renderer.h"
5#include <functional> 5#include "entity_manager.h"
6#include <list> 6#include "system_manager.h"
7#include <map>
8#include "map.h"
9#include "world.h"
10
11class Entity;
12struct GLFWwindow;
13
14struct Savefile {
15 const Map* map;
16 std::pair<double, double> position;
17};
18 7
19class Game { 8class Game {
20 public: 9 public:
21 Game(const char* maps); 10 Game(GLFWwindow* window);
22 void execute(GLFWwindow* window); 11
23 void loadMap(const Map& map, std::pair<double, double> position); 12 void execute();
24 void detectCollision(Entity& collider, std::pair<double, double> old_position); 13 EntityManager& getEntityManager();
25 void saveGame(); 14
26 void schedule(double time, std::function<void ()> callback);
27 void playerDie();
28 const World& getWorld() const;
29
30 private:
31 friend void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); 15 friend void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
32 16
33 std::list<std::shared_ptr<Entity>> entities; 17 private:
34 std::list<std::shared_ptr<Entity>> nextEntities; 18 EntityManager entityManager;
35 std::pair<double, double> nextPosition; 19 SystemManager systemManager;
36 bool newWorld; 20 GLFWwindow* const window;
37 std::shared_ptr<Entity> player;
38 const Map* currentMap;
39 Savefile save;
40 std::list<std::pair<double, std::function<void ()>>> scheduled;
41 bool shouldQuit = false; 21 bool shouldQuit = false;
42 World world;
43}; 22};
44 23
45#endif 24#endif /* end of include guard: GAME_H_1014DDC9 */
diff --git a/src/main.cpp b/src/main.cpp index 4157350..d51da7d 100644 --- a/src/main.cpp +++ b/src/main.cpp
@@ -1,25 +1,27 @@
1#include <ctime> 1#include <ctime>
2#include <list> 2#include <list>
3#include "renderer.h"
4#include <cstdlib> 3#include <cstdlib>
5#include "game.h" 4#include "renderer.h"
6#include "muxer.h" 5#include "muxer.h"
6#include "game.h"
7 7
8int main() 8int main()
9{ 9{
10 srand(time(NULL)); 10 srand(time(NULL));
11 11
12 GLFWwindow* window = initRenderer(); 12 GLFWwindow* window = initRenderer();
13 glfwSwapInterval(1);
14
13 initMuxer(); 15 initMuxer();
14 16
15 // Put this in a block so game goes out of scope before we destroy the renderer 17 // Put this in a block so game goes out of scope before we destroy the renderer
16 { 18 {
17 Game game {"res/maps.xml"}; 19 Game game {window};
18 game.execute(window); 20 game.execute();
19 } 21 }
20 22
21 destroyMuxer(); 23 destroyMuxer();
22 destroyRenderer(); 24 destroyRenderer();
23 25
24 return 0; 26 return 0;
25} 27}
diff --git a/src/map.cpp b/src/map.cpp deleted file mode 100644 index e3725b2..0000000 --- a/src/map.cpp +++ /dev/null
@@ -1,151 +0,0 @@
1#include "map.h"
2#include <cstdlib>
3#include <cstring>
4#include <map>
5#include "entityfactory.h"
6#include "entity.h"
7#include "game.h"
8#include "consts.h"
9
10Map::Map(int id)
11{
12 this->id = id;
13 mapdata = (int*) calloc(1, sizeof(int));
14}
15
16Map::Map(const Map& map)
17{
18 mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int));
19 memcpy(mapdata, map.mapdata, MAP_WIDTH*MAP_HEIGHT*sizeof(int));
20
21 id = map.id;
22 title = map.title;
23 adjacents = map.adjacents;
24 entities = map.entities;
25}
26
27Map::Map(Map&& map) : Map()
28{
29 swap(*this, map);
30}
31
32Map::~Map()
33{
34 free(mapdata);
35}
36
37Map& Map::operator= (Map map)
38{
39 swap(*this, map);
40
41 return *this;
42}
43
44void swap(Map& first, Map& second)
45{
46 std::swap(first.mapdata, second.mapdata);
47 std::swap(first.title, second.title);
48 std::swap(first.adjacents, second.adjacents);
49 std::swap(first.id, second.id);
50 std::swap(first.entities, second.entities);
51}
52
53int Map::getID() const
54{
55 return id;
56}
57
58const int* Map::getMapdata() const
59{
60 return mapdata;
61}
62
63std::string Map::getTitle() const
64{
65 return title;
66}
67
68void Map::createEntities(std::list<std::shared_ptr<Entity>>& entities) const
69{
70 for (auto data : this->entities)
71 {
72 auto entity = EntityFactory::createNamedEntity(data.name, data.items);
73 entity->position = data.position;
74
75 entities.push_back(entity);
76 }
77}
78
79bool Map::operator==(const Map& other) const
80{
81 return id == other.id;
82}
83
84bool Map::operator!=(const Map& other) const
85{
86 return id != other.id;
87}
88
89Map::MoveType Map::moveTypeForShort(std::string str)
90{
91 if (str == "wrap") return MoveType::Wrap;
92 if (str == "warp") return MoveType::Warp;
93 if (str == "reverseWarp") return MoveType::ReverseWarp;
94
95 return MoveType::Wall;
96}
97
98Map::MoveDir Map::moveDirForShort(std::string str)
99{
100 if (str == "right") return MoveDir::Right;
101 if (str == "up") return MoveDir::Up;
102 if (str == "down") return MoveDir::Down;
103
104 return MoveDir::Left;
105}
106
107static const Map::Adjacent defaultAdjacent {};
108const Map::Adjacent& Map::getAdjacent(MoveDir dir) const
109{
110 if (adjacents.count(dir) > 0)
111 {
112 return adjacents.at(dir);
113 } else {
114 return defaultAdjacent;
115 }
116}
117
118bool Map::moveTypeTakesMap(MoveType type)
119{
120 switch (type)
121 {
122 case MoveType::Wall: return false;
123 case MoveType::Wrap: return false;
124 case MoveType::Warp: return true;
125 case MoveType::ReverseWarp: return true;
126 }
127}
128
129void Map::setMapdata(int* mapdata)
130{
131 free(this->mapdata);
132 this->mapdata = mapdata;
133}
134
135void Map::setTitle(std::string title)
136{
137 this->title = title;
138}
139
140void Map::setAdjacent(MoveDir dir, MoveType type, int map)
141{
142 Adjacent& cur = adjacents[dir];
143 cur.type = type;
144 if (map != -1) cur.map = map;
145}
146
147void Map::addEntity(EntityData& data)
148{
149 entities.push_back(data);
150}
151
diff --git a/src/map.h b/src/map.h deleted file mode 100644 index 22333aa..0000000 --- a/src/map.h +++ /dev/null
@@ -1,70 +0,0 @@
1#ifndef MAP_H
2#define MAP_H
3
4#include <string>
5#include <list>
6#include <map>
7
8class Entity;
9
10class Map {
11 public:
12 Map(int id);
13 Map() : Map(-1) {}
14 Map(const Map& map);
15 Map(Map&& map);
16 ~Map();
17 Map& operator= (Map other);
18 friend void swap(Map& first, Map& second);
19
20 enum class MoveType {
21 Wall,
22 Wrap,
23 Warp,
24 ReverseWarp
25 };
26
27 enum class MoveDir {
28 Left,
29 Right,
30 Up,
31 Down
32 };
33
34 struct EntityData {
35 std::string name;
36 std::pair<int, int> position;
37 std::map<std::string, int> items;
38 };
39
40 struct Adjacent {
41 MoveType type = MoveType::Wall;
42 int map = -1;
43 };
44
45 static MoveType moveTypeForShort(std::string str);
46 static MoveDir moveDirForShort(std::string str);
47 static bool moveTypeTakesMap(MoveType type);
48
49 int getID() const;
50 const int* getMapdata() const;
51 std::string getTitle() const;
52 const Adjacent& getAdjacent(MoveDir dir) const;
53
54 void createEntities(std::list<std::shared_ptr<Entity>>& entities) const;
55 bool operator==(const Map& other) const;
56 bool operator!=(const Map& other) const;
57
58 void setMapdata(int* mapdata);
59 void setTitle(std::string title);
60 void setAdjacent(MoveDir dir, MoveType type, int map);
61 void addEntity(EntityData& data);
62 private:
63 int* mapdata;
64 std::string title;
65 int id;
66 std::list<EntityData> entities;
67 std::map<MoveDir, Adjacent> adjacents;
68};
69
70#endif
diff --git a/src/muxer.cpp b/src/muxer.cpp index d831e6d..ecce82b 100644 --- a/src/muxer.cpp +++ b/src/muxer.cpp
@@ -4,6 +4,9 @@
4#include <portaudio.h> 4#include <portaudio.h>
5#include <list> 5#include <list>
6#include <cmath> 6#include <cmath>
7#include <vector>
8#include <stdexcept>
9#include <sstream>
7 10
8#define SAMPLE_RATE (44100) 11#define SAMPLE_RATE (44100)
9#define DELAY_IN_SECS (0.075) 12#define DELAY_IN_SECS (0.075)
@@ -17,11 +20,14 @@ const int delaySize = SAMPLE_RATE * DELAY_IN_SECS;
17class Sound { 20class Sound {
18 public: 21 public:
19 Sound(const char* filename, float vol); 22 Sound(const char* filename, float vol);
20 ~Sound(); 23
21 24 inline bool isDone() const
22 float* ptr; 25 {
26 return pos >= data.size();
27 }
28
29 std::vector<float> data;
23 unsigned long pos; 30 unsigned long pos;
24 unsigned long len;
25 float vol; 31 float vol;
26}; 32};
27 33
@@ -45,29 +51,29 @@ int paMuxerCallback(const void*, void* outputBuffer, unsigned long framesPerBuff
45{ 51{
46 Muxer* muxer = (Muxer*) userData; 52 Muxer* muxer = (Muxer*) userData;
47 float* out = (float*) outputBuffer; 53 float* out = (float*) outputBuffer;
48 54
49 for (unsigned long i = 0; i<framesPerBuffer; i++) 55 for (unsigned long i = 0; i<framesPerBuffer; i++)
50 { 56 {
51 float in = 0.0; 57 float in = 0.0;
52 58
53 for (auto& sound : muxer->playing) 59 for (auto& sound : muxer->playing)
54 { 60 {
55 if (sound.pos < sound.len) 61 if (sound.pos < sound.data.size())
56 { 62 {
57 in += sound.ptr[sound.pos++] * sound.vol; 63 in += sound.data[sound.pos++] * sound.vol;
58 } 64 }
59 } 65 }
60 66
61 if (in > 1) in = 1; 67 if (in > 1) in = 1;
62 if (in < -1) in = -1; 68 if (in < -1) in = -1;
63 69
64 float sample = muxer->delay[muxer->delayPos] * GAIN; 70 float sample = muxer->delay[muxer->delayPos] * GAIN;
65 muxer->delay[muxer->delayPos] = in + (muxer->delay[muxer->delayPos] * FEEDBACK); 71 muxer->delay[muxer->delayPos] = in + (muxer->delay[muxer->delayPos] * FEEDBACK);
66 muxer->delayPos++; 72 muxer->delayPos++;
67 if (muxer->delayPos > delaySize) muxer->delayPos = 0; 73 if (muxer->delayPos > delaySize) muxer->delayPos = 0;
68 *out++ = (in * DRY) + (sample * WET); 74 *out++ = (in * DRY) + (sample * WET);
69 } 75 }
70 76
71 return 0; 77 return 0;
72} 78}
73 79
@@ -76,11 +82,11 @@ static Muxer* muxer;
76void initMuxer() 82void initMuxer()
77{ 83{
78 muxer = new Muxer(); 84 muxer = new Muxer();
79 85
80 dealWithPaError(Pa_Initialize()); 86 dealWithPaError(Pa_Initialize());
81 dealWithPaError(Pa_OpenDefaultStream(&muxer->stream, 0, 1, paFloat32, SAMPLE_RATE, paFramesPerBufferUnspecified, paMuxerCallback, muxer)); 87 dealWithPaError(Pa_OpenDefaultStream(&muxer->stream, 0, 1, paFloat32, SAMPLE_RATE, paFramesPerBufferUnspecified, paMuxerCallback, muxer));
82 dealWithPaError(Pa_StartStream(muxer->stream)); 88 dealWithPaError(Pa_StartStream(muxer->stream));
83 89
84 muxer->delay = (float*) calloc(delaySize, sizeof(float)); 90 muxer->delay = (float*) calloc(delaySize, sizeof(float));
85} 91}
86 92
@@ -89,7 +95,7 @@ void destroyMuxer()
89 dealWithPaError(Pa_AbortStream(muxer->stream)); 95 dealWithPaError(Pa_AbortStream(muxer->stream));
90 dealWithPaError(Pa_CloseStream(muxer->stream)); 96 dealWithPaError(Pa_CloseStream(muxer->stream));
91 dealWithPaError(Pa_Terminate()); 97 dealWithPaError(Pa_Terminate());
92 98
93 free(muxer->delay); 99 free(muxer->delay);
94 delete muxer; 100 delete muxer;
95 muxer = 0; 101 muxer = 0;
@@ -98,8 +104,8 @@ void destroyMuxer()
98void playSound(const char* filename, float vol) 104void playSound(const char* filename, float vol)
99{ 105{
100 // First, clear out any sounds that have finished playing 106 // First, clear out any sounds that have finished playing
101 muxer->playing.remove_if([] (Sound& value) { return value.pos >= value.len; }); 107 muxer->playing.remove_if([] (Sound& value) { return value.isDone(); });
102 108
103 // Then, add the new sound 109 // Then, add the new sound
104 muxer->playing.emplace_back(filename, vol); 110 muxer->playing.emplace_back(filename, vol);
105} 111}
@@ -110,21 +116,18 @@ Sound::Sound(const char* filename, float vol)
110 SNDFILE* file = sf_open(filename, SFM_READ, &info); 116 SNDFILE* file = sf_open(filename, SFM_READ, &info);
111 if (file == nullptr) 117 if (file == nullptr)
112 { 118 {
113 printf("LibSndFile error: %s\n", sf_strerror(file)); 119 std::ostringstream errmsg;
114 exit(-1); 120 errmsg << "LibSndFile error: ";
121 errmsg << sf_strerror(file);
122
123 throw std::logic_error(errmsg.str());
115 } 124 }
116 125
117 ptr = (float*) malloc(info.frames * info.channels * sizeof(float)); 126 data.resize(info.frames * info.channels);
118 len = info.frames * info.channels;
119 pos = 0; 127 pos = 0;
120 this->vol = vol; 128 this->vol = vol;
121
122 sf_readf_float(file, ptr, info.frames);
123
124 sf_close(file);
125}
126 129
127Sound::~Sound() 130 sf_readf_float(file, data.data(), info.frames);
128{ 131
129 free(ptr); 132 sf_close(file);
130} 133}
diff --git a/src/renderer.cpp b/src/renderer.cpp index ffe9d47..3945e09 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp
@@ -56,11 +56,11 @@ static GLuint mesh_normalbuffer;
56static int mesh_numvertices; 56static int mesh_numvertices;
57 57
58GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) 58GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
59{ 59{
60 // Create the shaders 60 // Create the shaders
61 GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); 61 GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
62 GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); 62 GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
63 63
64 // Read the Vertex Shader code from the file 64 // Read the Vertex Shader code from the file
65 std::string VertexShaderCode; 65 std::string VertexShaderCode;
66 std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); 66 std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
@@ -71,7 +71,7 @@ GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
71 VertexShaderCode += "\n" + Line; 71 VertexShaderCode += "\n" + Line;
72 VertexShaderStream.close(); 72 VertexShaderStream.close();
73 } 73 }
74 74
75 // Read the Fragment Shader code from the file 75 // Read the Fragment Shader code from the file
76 std::string FragmentShaderCode; 76 std::string FragmentShaderCode;
77 std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); 77 std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
@@ -81,53 +81,53 @@ GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
81 FragmentShaderCode += "\n" + Line; 81 FragmentShaderCode += "\n" + Line;
82 FragmentShaderStream.close(); 82 FragmentShaderStream.close();
83 } 83 }
84 84
85 GLint Result = GL_FALSE; 85 GLint Result = GL_FALSE;
86 int InfoLogLength; 86 int InfoLogLength;
87 87
88 // Compile Vertex Shader 88 // Compile Vertex Shader
89 printf("Compiling shader : %s\n", vertex_file_path); 89 printf("Compiling shader : %s\n", vertex_file_path);
90 char const * VertexSourcePointer = VertexShaderCode.c_str(); 90 char const * VertexSourcePointer = VertexShaderCode.c_str();
91 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , nullptr); 91 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , nullptr);
92 glCompileShader(VertexShaderID); 92 glCompileShader(VertexShaderID);
93 93
94 // Check Vertex Shader 94 // Check Vertex Shader
95 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); 95 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
96 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); 96 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
97 std::vector<char> VertexShaderErrorMessage(InfoLogLength); 97 std::vector<char> VertexShaderErrorMessage(InfoLogLength);
98 glGetShaderInfoLog(VertexShaderID, InfoLogLength, nullptr, &VertexShaderErrorMessage[0]); 98 glGetShaderInfoLog(VertexShaderID, InfoLogLength, nullptr, &VertexShaderErrorMessage[0]);
99 fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]); 99 fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
100 100
101 // Compile Fragment Shader 101 // Compile Fragment Shader
102 printf("Compiling shader : %s\n", fragment_file_path); 102 printf("Compiling shader : %s\n", fragment_file_path);
103 char const * FragmentSourcePointer = FragmentShaderCode.c_str(); 103 char const * FragmentSourcePointer = FragmentShaderCode.c_str();
104 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , nullptr); 104 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , nullptr);
105 glCompileShader(FragmentShaderID); 105 glCompileShader(FragmentShaderID);
106 106
107 // Check Fragment Shader 107 // Check Fragment Shader
108 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); 108 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
109 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); 109 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
110 std::vector<char> FragmentShaderErrorMessage(InfoLogLength); 110 std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
111 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, nullptr, &FragmentShaderErrorMessage[0]); 111 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, nullptr, &FragmentShaderErrorMessage[0]);
112 fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]); 112 fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
113 113
114 // Link the program 114 // Link the program
115 fprintf(stdout, "Linking program\n"); 115 fprintf(stdout, "Linking program\n");
116 GLuint ProgramID = glCreateProgram(); 116 GLuint ProgramID = glCreateProgram();
117 glAttachShader(ProgramID, VertexShaderID); 117 glAttachShader(ProgramID, VertexShaderID);
118 glAttachShader(ProgramID, FragmentShaderID); 118 glAttachShader(ProgramID, FragmentShaderID);
119 glLinkProgram(ProgramID); 119 glLinkProgram(ProgramID);
120 120
121 // Check the program 121 // Check the program
122 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); 122 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
123 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); 123 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
124 std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) ); 124 std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) );
125 glGetProgramInfoLog(ProgramID, InfoLogLength, nullptr, &ProgramErrorMessage[0]); 125 glGetProgramInfoLog(ProgramID, InfoLogLength, nullptr, &ProgramErrorMessage[0]);
126 fprintf(stdout, "%s\n", &ProgramErrorMessage[0]); 126 fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
127 127
128 glDeleteShader(VertexShaderID); 128 glDeleteShader(VertexShaderID);
129 glDeleteShader(FragmentShaderID); 129 glDeleteShader(FragmentShaderID);
130 130
131 return ProgramID; 131 return ProgramID;
132} 132}
133 133
@@ -135,14 +135,14 @@ void flipImageData(unsigned char* data, int width, int height, int comps)
135{ 135{
136 unsigned char* data_copy = (unsigned char*) malloc(width*height*comps*sizeof(unsigned char)); 136 unsigned char* data_copy = (unsigned char*) malloc(width*height*comps*sizeof(unsigned char));
137 memcpy(data_copy, data, width*height*comps); 137 memcpy(data_copy, data, width*height*comps);
138 138
139 int row_size = width * comps; 139 int row_size = width * comps;
140 140
141 for (int i=0;i<height;i++) 141 for (int i=0;i<height;i++)
142 { 142 {
143 memcpy(data + (row_size*i), data_copy + (row_size*(height-i-1)), row_size); 143 memcpy(data + (row_size*i), data_copy + (row_size*(height-i-1)), row_size);
144 } 144 }
145 145
146 free(data_copy); 146 free(data_copy);
147} 147}
148 148
@@ -154,11 +154,11 @@ void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::v
154 fprintf(stderr, "Could not open mesh file %s\n", filename); 154 fprintf(stderr, "Could not open mesh file %s\n", filename);
155 exit(1); 155 exit(1);
156 } 156 }
157 157
158 std::vector<glm::vec3> temp_vertices; 158 std::vector<glm::vec3> temp_vertices;
159 std::vector<glm::vec2> temp_uvs; 159 std::vector<glm::vec2> temp_uvs;
160 std::vector<glm::vec3> temp_normals; 160 std::vector<glm::vec3> temp_normals;
161 161
162 for (;;) 162 for (;;)
163 { 163 {
164 char lineHeader[256]; 164 char lineHeader[256];
@@ -167,7 +167,7 @@ void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::v
167 { 167 {
168 break; 168 break;
169 } 169 }
170 170
171 if (!strncmp(lineHeader, "v", 2)) 171 if (!strncmp(lineHeader, "v", 2))
172 { 172 {
173 glm::vec3 vertex; 173 glm::vec3 vertex;
@@ -187,7 +187,7 @@ void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::v
187 { 187 {
188 int vertexIDs[3], uvIDs[3], normalIDs[3]; 188 int vertexIDs[3], uvIDs[3], normalIDs[3];
189 fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIDs[0], &uvIDs[0], &normalIDs[0], &vertexIDs[1], &uvIDs[1], &normalIDs[1], &vertexIDs[2], &uvIDs[2], &normalIDs[2]); 189 fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIDs[0], &uvIDs[0], &normalIDs[0], &vertexIDs[1], &uvIDs[1], &normalIDs[1], &vertexIDs[2], &uvIDs[2], &normalIDs[2]);
190 190
191 for (int i=0; i<3; i++) 191 for (int i=0; i<3; i++)
192 { 192 {
193 out_vertices.push_back(temp_vertices[vertexIDs[i] - 1]); 193 out_vertices.push_back(temp_vertices[vertexIDs[i] - 1]);
@@ -202,24 +202,24 @@ void setFramebufferSize(GLFWwindow* w, int width, int height)
202{ 202{
203 buffer_width = width; 203 buffer_width = width;
204 buffer_height = height; 204 buffer_height = height;
205 205
206 glDeleteFramebuffers(1, &bloom_framebuffer); 206 glDeleteFramebuffers(1, &bloom_framebuffer);
207 glDeleteRenderbuffers(1, &bloom_depthbuffer); 207 glDeleteRenderbuffers(1, &bloom_depthbuffer);
208 208
209 glGenFramebuffers(1, &bloom_framebuffer); 209 glGenFramebuffers(1, &bloom_framebuffer);
210 glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer); 210 glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer);
211 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT1}; 211 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT1};
212 glDrawBuffers(1, DrawBuffers); 212 glDrawBuffers(1, DrawBuffers);
213 213
214 glGenRenderbuffers(1, &bloom_depthbuffer); 214 glGenRenderbuffers(1, &bloom_depthbuffer);
215 glBindRenderbuffer(GL_RENDERBUFFER, bloom_depthbuffer); 215 glBindRenderbuffer(GL_RENDERBUFFER, bloom_depthbuffer);
216 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); 216 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
217 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bloom_depthbuffer); 217 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bloom_depthbuffer);
218 218
219 glDeleteTextures(1, &preBloomTex); 219 glDeleteTextures(1, &preBloomTex);
220 glDeleteTextures(1, &bloomPassTex1); 220 glDeleteTextures(1, &bloomPassTex1);
221 glDeleteTextures(1, &bloomPassTex2); 221 glDeleteTextures(1, &bloomPassTex2);
222 222
223 glGenTextures(1, &preBloomTex); 223 glGenTextures(1, &preBloomTex);
224 glBindTexture(GL_TEXTURE_2D, preBloomTex); 224 glBindTexture(GL_TEXTURE_2D, preBloomTex);
225 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 225 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
@@ -227,7 +227,7 @@ void setFramebufferSize(GLFWwindow* w, int width, int height)
227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
230 230
231 glGenTextures(1, &bloomPassTex1); 231 glGenTextures(1, &bloomPassTex1);
232 glBindTexture(GL_TEXTURE_2D, bloomPassTex1); 232 glBindTexture(GL_TEXTURE_2D, bloomPassTex1);
233 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/4, height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 233 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/4, height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
@@ -235,7 +235,7 @@ void setFramebufferSize(GLFWwindow* w, int width, int height)
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
238 238
239 glGenTextures(1, &bloomPassTex2); 239 glGenTextures(1, &bloomPassTex2);
240 glBindTexture(GL_TEXTURE_2D, bloomPassTex2); 240 glBindTexture(GL_TEXTURE_2D, bloomPassTex2);
241 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/4, height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 241 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/4, height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
@@ -252,20 +252,20 @@ GLFWwindow* initRenderer()
252 fprintf(stderr, "Renderer already initialized\n"); 252 fprintf(stderr, "Renderer already initialized\n");
253 exit(-1); 253 exit(-1);
254 } 254 }
255 255
256 // Initialize GLFW 256 // Initialize GLFW
257 if (!glfwInit()) 257 if (!glfwInit())
258 { 258 {
259 fprintf(stderr, "Failed to initialize GLFW\n"); 259 fprintf(stderr, "Failed to initialize GLFW\n");
260 exit(-1); 260 exit(-1);
261 } 261 }
262 262
263 glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing 263 glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
264 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want version 3.3 264 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want version 3.3
265 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 265 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
266 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac requires this 266 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac requires this
267 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 267 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
268 268
269 // Create a window 269 // Create a window
270 window = glfwCreateWindow(1024, 768, "Aromatherapy", nullptr, nullptr); 270 window = glfwCreateWindow(1024, 768, "Aromatherapy", nullptr, nullptr);
271 if (window == nullptr) 271 if (window == nullptr)
@@ -274,7 +274,7 @@ GLFWwindow* initRenderer()
274 glfwTerminate(); 274 glfwTerminate();
275 exit(-1); 275 exit(-1);
276 } 276 }
277 277
278 glfwMakeContextCurrent(window); 278 glfwMakeContextCurrent(window);
279 glewExperimental = true; // Needed in core profile 279 glewExperimental = true; // Needed in core profile
280 if (glewInit() != GLEW_OK) 280 if (glewInit() != GLEW_OK)
@@ -282,37 +282,37 @@ GLFWwindow* initRenderer()
282 fprintf(stderr, "Failed to initialize GLEW\n"); 282 fprintf(stderr, "Failed to initialize GLEW\n");
283 exit(-1); 283 exit(-1);
284 } 284 }
285 285
286 glfwSetFramebufferSizeCallback(window, &setFramebufferSize); 286 glfwSetFramebufferSizeCallback(window, &setFramebufferSize);
287 287
288 // Set up vertex array object 288 // Set up vertex array object
289 glGenVertexArrays(1, &VertexArrayID); 289 glGenVertexArrays(1, &VertexArrayID);
290 glBindVertexArray(VertexArrayID); 290 glBindVertexArray(VertexArrayID);
291 291
292 // Enable depth testing 292 // Enable depth testing
293 glEnable(GL_DEPTH_TEST); 293 glEnable(GL_DEPTH_TEST);
294 glDepthFunc(GL_LESS); 294 glDepthFunc(GL_LESS);
295 295
296 // Enable blending 296 // Enable blending
297 glEnable(GL_BLEND); 297 glEnable(GL_BLEND);
298 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 298 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
299 299
300 // Set up the framebuffer 300 // Set up the framebuffer
301 glGenFramebuffers(1, &generic_framebuffer); 301 glGenFramebuffers(1, &generic_framebuffer);
302 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); 302 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer);
303 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; 303 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
304 glDrawBuffers(1, DrawBuffers); 304 glDrawBuffers(1, DrawBuffers);
305 305
306 glGenFramebuffers(1, &bloom_framebuffer); 306 glGenFramebuffers(1, &bloom_framebuffer);
307 glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer); 307 glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer);
308 GLenum DrawBuffers2[1] = {GL_COLOR_ATTACHMENT1}; 308 GLenum DrawBuffers2[1] = {GL_COLOR_ATTACHMENT1};
309 glDrawBuffers(1, DrawBuffers2); 309 glDrawBuffers(1, DrawBuffers2);
310 310
311 glGenRenderbuffers(1, &bloom_depthbuffer); 311 glGenRenderbuffers(1, &bloom_depthbuffer);
312 glBindRenderbuffer(GL_RENDERBUFFER, bloom_depthbuffer); 312 glBindRenderbuffer(GL_RENDERBUFFER, bloom_depthbuffer);
313 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1024, 768); 313 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1024, 768);
314 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bloom_depthbuffer); 314 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bloom_depthbuffer);
315 315
316 // Set up the NTSC rendering buffers 316 // Set up the NTSC rendering buffers
317 glGenTextures(1, &renderedTex1); 317 glGenTextures(1, &renderedTex1);
318 glBindTexture(GL_TEXTURE_2D, renderedTex1); 318 glBindTexture(GL_TEXTURE_2D, renderedTex1);
@@ -322,7 +322,7 @@ GLFWwindow* initRenderer()
322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
324 renderedTexBufs[0] = renderedTex1; 324 renderedTexBufs[0] = renderedTex1;
325 325
326 glGenTextures(1, &renderedTex2); 326 glGenTextures(1, &renderedTex2);
327 glBindTexture(GL_TEXTURE_2D, renderedTex2); 327 glBindTexture(GL_TEXTURE_2D, renderedTex2);
328 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 328 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
@@ -331,7 +331,7 @@ GLFWwindow* initRenderer()
331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
332 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 332 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
333 renderedTexBufs[1] = renderedTex2; 333 renderedTexBufs[1] = renderedTex2;
334 334
335 // Set up bloom rendering buffers 335 // Set up bloom rendering buffers
336 glGenTextures(1, &preBloomTex); 336 glGenTextures(1, &preBloomTex);
337 glBindTexture(GL_TEXTURE_2D, preBloomTex); 337 glBindTexture(GL_TEXTURE_2D, preBloomTex);
@@ -340,7 +340,7 @@ GLFWwindow* initRenderer()
340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
343 343
344 glGenTextures(1, &bloomPassTex1); 344 glGenTextures(1, &bloomPassTex1);
345 glBindTexture(GL_TEXTURE_2D, bloomPassTex1); 345 glBindTexture(GL_TEXTURE_2D, bloomPassTex1);
346 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024/4, 768/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 346 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024/4, 768/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
@@ -348,7 +348,7 @@ GLFWwindow* initRenderer()
348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
351 351
352 glGenTextures(1, &bloomPassTex2); 352 glGenTextures(1, &bloomPassTex2);
353 glBindTexture(GL_TEXTURE_2D, bloomPassTex2); 353 glBindTexture(GL_TEXTURE_2D, bloomPassTex2);
354 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024/4, 768/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 354 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024/4, 768/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
@@ -356,31 +356,32 @@ GLFWwindow* initRenderer()
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
359 359
360 curBuf = 0; 360 curBuf = 0;
361 361
362 // Load the mesh! 362 // Load the mesh!
363 std::vector<glm::vec3> mesh_vertices; 363 std::vector<glm::vec3> mesh_vertices;
364 std::vector<glm::vec2> mesh_uvs; 364 std::vector<glm::vec2> mesh_uvs;
365 std::vector<glm::vec3> mesh_normals; 365 std::vector<glm::vec3> mesh_normals;
366
366 loadMesh("res/monitor-old.obj", mesh_vertices, mesh_uvs, mesh_normals); 367 loadMesh("res/monitor-old.obj", mesh_vertices, mesh_uvs, mesh_normals);
367 368
368 mesh_numvertices = mesh_vertices.size(); 369 mesh_numvertices = mesh_vertices.size();
369 370
370 glGenBuffers(1, &mesh_vertexbuffer); 371 glGenBuffers(1, &mesh_vertexbuffer);
371 glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); 372 glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer);
372 glBufferData(GL_ARRAY_BUFFER, mesh_vertices.size() * sizeof(glm::vec3), &mesh_vertices[0], GL_STATIC_DRAW); 373 glBufferData(GL_ARRAY_BUFFER, mesh_vertices.size() * sizeof(glm::vec3), &mesh_vertices[0], GL_STATIC_DRAW);
373 374
374 glGenBuffers(1, &mesh_uvbuffer); 375 glGenBuffers(1, &mesh_uvbuffer);
375 glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); 376 glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer);
376 glBufferData(GL_ARRAY_BUFFER, mesh_uvs.size() * sizeof(glm::vec3), &mesh_uvs[0], GL_STATIC_DRAW); 377 glBufferData(GL_ARRAY_BUFFER, mesh_uvs.size() * sizeof(glm::vec3), &mesh_uvs[0], GL_STATIC_DRAW);
377 378
378 glGenBuffers(1, &mesh_normalbuffer); 379 glGenBuffers(1, &mesh_normalbuffer);
379 glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); 380 glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer);
380 glBufferData(GL_ARRAY_BUFFER, mesh_normals.size() * sizeof(glm::vec3), &mesh_normals[0], GL_STATIC_DRAW); 381 glBufferData(GL_ARRAY_BUFFER, mesh_normals.size() * sizeof(glm::vec3), &mesh_normals[0], GL_STATIC_DRAW);
381 382
382 // Load the vertices of a flat surface 383 // Load the vertices of a flat surface
383 GLfloat g_quad_vertex_buffer_data[] = { 384 GLfloat g_quad_vertex_buffer_data[] = {
384 -1.0f, -1.0f, 0.0f, 385 -1.0f, -1.0f, 0.0f,
385 1.0f, -1.0f, 0.0f, 386 1.0f, -1.0f, 0.0f,
386 -1.0f, 1.0f, 0.0f, 387 -1.0f, 1.0f, 0.0f,
@@ -392,7 +393,7 @@ GLFWwindow* initRenderer()
392 glGenBuffers(1, &quad_vertexbuffer); 393 glGenBuffers(1, &quad_vertexbuffer);
393 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); 394 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
394 glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW); 395 glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
395 396
396 glGenTextures(1, &artifactsTex); 397 glGenTextures(1, &artifactsTex);
397 glBindTexture(GL_TEXTURE_2D, artifactsTex); 398 glBindTexture(GL_TEXTURE_2D, artifactsTex);
398 int atdw, atdh; 399 int atdw, atdh;
@@ -403,7 +404,7 @@ GLFWwindow* initRenderer()
403 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); 405 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
405 glGenerateMipmap(GL_TEXTURE_2D); 406 glGenerateMipmap(GL_TEXTURE_2D);
406 407
407 glGenTextures(1, &scanlinesTex); 408 glGenTextures(1, &scanlinesTex);
408 glBindTexture(GL_TEXTURE_2D, scanlinesTex); 409 glBindTexture(GL_TEXTURE_2D, scanlinesTex);
409 int stdw, stdh; 410 int stdw, stdh;
@@ -414,7 +415,7 @@ GLFWwindow* initRenderer()
414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 415 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
415 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); 416 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
416 glGenerateMipmap(GL_TEXTURE_2D); 417 glGenerateMipmap(GL_TEXTURE_2D);
417 418
418 // Load the shaders 419 // Load the shaders
419 ntscShader = LoadShaders("shaders/ntsc.vertex", "shaders/ntsc.fragment"); 420 ntscShader = LoadShaders("shaders/ntsc.vertex", "shaders/ntsc.fragment");
420 finalShader = LoadShaders("shaders/final.vertex", "shaders/final.fragment"); 421 finalShader = LoadShaders("shaders/final.vertex", "shaders/final.fragment");
@@ -422,9 +423,9 @@ GLFWwindow* initRenderer()
422 fillShader = LoadShaders("shaders/fill.vertex", "shaders/fill.fragment"); 423 fillShader = LoadShaders("shaders/fill.vertex", "shaders/fill.fragment");
423 bloom1Shader = LoadShaders("shaders/bloom1.vertex", "shaders/bloom1.fragment"); 424 bloom1Shader = LoadShaders("shaders/bloom1.vertex", "shaders/bloom1.fragment");
424 bloom2Shader = LoadShaders("shaders/bloom2.vertex", "shaders/bloom2.fragment"); 425 bloom2Shader = LoadShaders("shaders/bloom2.vertex", "shaders/bloom2.fragment");
425 426
426 rendererInitialized = true; 427 rendererInitialized = true;
427 428
428 return window; 429 return window;
429} 430}
430 431
@@ -435,13 +436,13 @@ void destroyRenderer()
435 fprintf(stderr, "Renderer not initialized\n"); 436 fprintf(stderr, "Renderer not initialized\n");
436 exit(-1); 437 exit(-1);
437 } 438 }
438 439
439 // Delete the plane buffer 440 // Delete the plane buffer
440 glDeleteBuffers(1, &quad_vertexbuffer); 441 glDeleteBuffers(1, &quad_vertexbuffer);
441 glDeleteBuffers(1, &mesh_vertexbuffer); 442 glDeleteBuffers(1, &mesh_vertexbuffer);
442 glDeleteBuffers(1, &mesh_uvbuffer); 443 glDeleteBuffers(1, &mesh_uvbuffer);
443 glDeleteBuffers(1, &mesh_normalbuffer); 444 glDeleteBuffers(1, &mesh_normalbuffer);
444 445
445 // Delete the shaders 446 // Delete the shaders
446 glDeleteProgram(ntscShader); 447 glDeleteProgram(ntscShader);
447 glDeleteProgram(finalShader); 448 glDeleteProgram(finalShader);
@@ -449,7 +450,7 @@ void destroyRenderer()
449 glDeleteProgram(fillShader); 450 glDeleteProgram(fillShader);
450 glDeleteProgram(bloom1Shader); 451 glDeleteProgram(bloom1Shader);
451 glDeleteProgram(bloom2Shader); 452 glDeleteProgram(bloom2Shader);
452 453
453 // Delete the NTSC rendering buffers 454 // Delete the NTSC rendering buffers
454 glDeleteTextures(1, &renderedTex1); 455 glDeleteTextures(1, &renderedTex1);
455 glDeleteTextures(1, &renderedTex2); 456 glDeleteTextures(1, &renderedTex2);
@@ -458,18 +459,18 @@ void destroyRenderer()
458 glDeleteTextures(1, &preBloomTex); 459 glDeleteTextures(1, &preBloomTex);
459 glDeleteTextures(1, &bloomPassTex1); 460 glDeleteTextures(1, &bloomPassTex1);
460 glDeleteTextures(1, &bloomPassTex2); 461 glDeleteTextures(1, &bloomPassTex2);
461 462
462 // Delete the framebuffer 463 // Delete the framebuffer
463 glDeleteRenderbuffers(1, &bloom_depthbuffer); 464 glDeleteRenderbuffers(1, &bloom_depthbuffer);
464 glDeleteFramebuffers(1, &bloom_framebuffer); 465 glDeleteFramebuffers(1, &bloom_framebuffer);
465 glDeleteFramebuffers(1, &generic_framebuffer); 466 glDeleteFramebuffers(1, &generic_framebuffer);
466 467
467 // Delete the VAO 468 // Delete the VAO
468 glDeleteVertexArrays(1, &VertexArrayID); 469 glDeleteVertexArrays(1, &VertexArrayID);
469 470
470 // Kill the window 471 // Kill the window
471 glfwTerminate(); 472 glfwTerminate();
472 473
473 rendererInitialized = false; 474 rendererInitialized = false;
474} 475}
475 476
@@ -480,10 +481,10 @@ Texture::Texture(int width, int height)
480 fprintf(stderr, "Renderer not initialized\n"); 481 fprintf(stderr, "Renderer not initialized\n");
481 exit(-1); 482 exit(-1);
482 } 483 }
483 484
484 this->width = width; 485 this->width = width;
485 this->height = height; 486 this->height = height;
486 487
487 glGenTextures(1, &texID); 488 glGenTextures(1, &texID);
488 glBindTexture(GL_TEXTURE_2D, texID); 489 glBindTexture(GL_TEXTURE_2D, texID);
489 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); 490 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
@@ -500,7 +501,7 @@ Texture::Texture(const char* filename)
500 fprintf(stderr, "Renderer not initialized\n"); 501 fprintf(stderr, "Renderer not initialized\n");
501 exit(-1); 502 exit(-1);
502 } 503 }
503 504
504 glGenTextures(1, &texID); 505 glGenTextures(1, &texID);
505 glBindTexture(GL_TEXTURE_2D, texID); 506 glBindTexture(GL_TEXTURE_2D, texID);
506 unsigned char* data = stbi_load(filename, &width, &height, 0, 4); 507 unsigned char* data = stbi_load(filename, &width, &height, 0, 4);
@@ -520,14 +521,14 @@ Texture::Texture(const Texture& tex)
520 fprintf(stderr, "Renderer not initialized\n"); 521 fprintf(stderr, "Renderer not initialized\n");
521 exit(-1); 522 exit(-1);
522 } 523 }
523 524
524 width = tex.width; 525 width = tex.width;
525 height = tex.height; 526 height = tex.height;
526 527
527 unsigned char* data = (unsigned char*) malloc(4 * width * height); 528 unsigned char* data = (unsigned char*) malloc(4 * width * height);
528 glBindTexture(GL_TEXTURE_2D, tex.texID); 529 glBindTexture(GL_TEXTURE_2D, tex.texID);
529 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 530 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
530 531
531 glGenTextures(1, &texID); 532 glGenTextures(1, &texID);
532 glBindTexture(GL_TEXTURE_2D, texID); 533 glBindTexture(GL_TEXTURE_2D, texID);
533 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 534 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
@@ -535,7 +536,7 @@ Texture::Texture(const Texture& tex)
535 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 536 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
536 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 537 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
537 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 538 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
538 539
539 free(data); 540 free(data);
540} 541}
541 542
@@ -551,14 +552,14 @@ Texture::~Texture()
551 fprintf(stderr, "Renderer not initialized\n"); 552 fprintf(stderr, "Renderer not initialized\n");
552 exit(-1); 553 exit(-1);
553 } 554 }
554 555
555 glDeleteTextures(1, &texID); 556 glDeleteTextures(1, &texID);
556} 557}
557 558
558Texture& Texture::operator= (Texture tex) 559Texture& Texture::operator= (Texture tex)
559{ 560{
560 swap(*this, tex); 561 swap(*this, tex);
561 562
562 return *this; 563 return *this;
563} 564}
564 565
@@ -576,17 +577,17 @@ void Texture::fill(Rectangle dstrect, int r, int g, int b)
576 fprintf(stderr, "Renderer not initialized\n"); 577 fprintf(stderr, "Renderer not initialized\n");
577 exit(-1); 578 exit(-1);
578 } 579 }
579 580
580 // Target the framebuffer 581 // Target the framebuffer
581 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); 582 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer);
582 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0); 583 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0);
583 584
584 // Set up the vertex attributes 585 // Set up the vertex attributes
585 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0; 586 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0;
586 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0); 587 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0);
587 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0; 588 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0;
588 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0); 589 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0);
589 590
590 GLfloat vertexbuffer_data[] = { 591 GLfloat vertexbuffer_data[] = {
591 minx, miny, 592 minx, miny,
592 maxx, miny, 593 maxx, miny,
@@ -601,14 +602,14 @@ void Texture::fill(Rectangle dstrect, int r, int g, int b)
601 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW); 602 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW);
602 glEnableVertexAttribArray(0); 603 glEnableVertexAttribArray(0);
603 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); 604 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
604 605
605 glViewport(0, 0, width, height); 606 glViewport(0, 0, width, height);
606 glClear(GL_DEPTH_BUFFER_BIT); 607 glClear(GL_DEPTH_BUFFER_BIT);
607 glUseProgram(fillShader); 608 glUseProgram(fillShader);
608 glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0); 609 glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0);
609 610
610 glDrawArrays(GL_TRIANGLES, 0, 6); 611 glDrawArrays(GL_TRIANGLES, 0, 6);
611 612
612 glDisableVertexAttribArray(0); 613 glDisableVertexAttribArray(0);
613 glDeleteBuffers(1, &vertexbuffer); 614 glDeleteBuffers(1, &vertexbuffer);
614} 615}
@@ -620,19 +621,19 @@ void Texture::blit(const Texture& srctex, Rectangle srcrect, Rectangle dstrect,
620 fprintf(stderr, "Renderer not initialized\n"); 621 fprintf(stderr, "Renderer not initialized\n");
621 exit(-1); 622 exit(-1);
622 } 623 }
623 624
624 alpha = glm::clamp(alpha, 0.0, 1.0); 625 alpha = glm::clamp(alpha, 0.0, 1.0);
625 626
626 // Target the framebuffer 627 // Target the framebuffer
627 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); 628 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer);
628 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0); 629 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0);
629 630
630 // Set up the vertex attributes 631 // Set up the vertex attributes
631 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0; 632 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0;
632 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0); 633 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0);
633 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0; 634 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0;
634 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0); 635 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0);
635 636
636 GLfloat vertexbuffer_data[] = { 637 GLfloat vertexbuffer_data[] = {
637 minx, miny, 638 minx, miny,
638 maxx, miny, 639 maxx, miny,
@@ -645,12 +646,12 @@ void Texture::blit(const Texture& srctex, Rectangle srcrect, Rectangle dstrect,
645 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW); 646 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW);
646 glEnableVertexAttribArray(0); 647 glEnableVertexAttribArray(0);
647 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); 648 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
648 649
649 GLfloat minu = (GLfloat) srcrect.x / srctex.width; 650 GLfloat minu = (GLfloat) srcrect.x / srctex.width;
650 GLfloat minv = 1 - ((GLfloat) srcrect.y / srctex.height); 651 GLfloat minv = 1 - ((GLfloat) srcrect.y / srctex.height);
651 GLfloat maxu = (GLfloat) (srcrect.x + srcrect.w) / srctex.width; 652 GLfloat maxu = (GLfloat) (srcrect.x + srcrect.w) / srctex.width;
652 GLfloat maxv = 1 - ((GLfloat) (srcrect.y + srcrect.h) / srctex.height); 653 GLfloat maxv = 1 - ((GLfloat) (srcrect.y + srcrect.h) / srctex.height);
653 654
654 GLfloat texcoordbuffer_data[] = { 655 GLfloat texcoordbuffer_data[] = {
655 minu, minv, 656 minu, minv,
656 maxu, minv, 657 maxu, minv,
@@ -663,20 +664,20 @@ void Texture::blit(const Texture& srctex, Rectangle srcrect, Rectangle dstrect,
663 glBufferData(GL_ARRAY_BUFFER, sizeof(texcoordbuffer_data), texcoordbuffer_data, GL_STATIC_DRAW); 664 glBufferData(GL_ARRAY_BUFFER, sizeof(texcoordbuffer_data), texcoordbuffer_data, GL_STATIC_DRAW);
664 glEnableVertexAttribArray(1); 665 glEnableVertexAttribArray(1);
665 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); 666 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
666 667
667 // Set up the shader 668 // Set up the shader
668 glUseProgram(blitShader); 669 glUseProgram(blitShader);
669 glClear(GL_DEPTH_BUFFER_BIT); 670 glClear(GL_DEPTH_BUFFER_BIT);
670 glViewport(0, 0, width, height); 671 glViewport(0, 0, width, height);
671 672
672 glActiveTexture(GL_TEXTURE0); 673 glActiveTexture(GL_TEXTURE0);
673 glBindTexture(GL_TEXTURE_2D, srctex.texID); 674 glBindTexture(GL_TEXTURE_2D, srctex.texID);
674 glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0); 675 glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0);
675 glUniform1f(glGetUniformLocation(blitShader, "alpha"), alpha); 676 glUniform1f(glGetUniformLocation(blitShader, "alpha"), alpha);
676 677
677 // Blit! 678 // Blit!
678 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 679 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
679 680
680 // Unload everything 681 // Unload everything
681 glDisableVertexAttribArray(1); 682 glDisableVertexAttribArray(1);
682 glDisableVertexAttribArray(0); 683 glDisableVertexAttribArray(0);
@@ -691,11 +692,11 @@ void bloomPass1(GLuint srcTex, GLuint dstTex, bool horizontal, glm::vec2 srcRes,
691 glViewport(0,0,dstRes.x,dstRes.y); 692 glViewport(0,0,dstRes.x,dstRes.y);
692 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 693 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
693 glUseProgram(bloom1Shader); 694 glUseProgram(bloom1Shader);
694 695
695 glActiveTexture(GL_TEXTURE0); 696 glActiveTexture(GL_TEXTURE0);
696 glBindTexture(GL_TEXTURE_2D, srcTex); 697 glBindTexture(GL_TEXTURE_2D, srcTex);
697 glUniform1i(glGetUniformLocation(bloom1Shader, "inTex"), 0); 698 glUniform1i(glGetUniformLocation(bloom1Shader, "inTex"), 0);
698 699
699 glm::vec2 offset = glm::vec2(0.0); 700 glm::vec2 offset = glm::vec2(0.0);
700 if (horizontal) 701 if (horizontal)
701 { 702 {
@@ -703,9 +704,9 @@ void bloomPass1(GLuint srcTex, GLuint dstTex, bool horizontal, glm::vec2 srcRes,
703 } else { 704 } else {
704 offset.y = 1.2/srcRes.y; 705 offset.y = 1.2/srcRes.y;
705 } 706 }
706 707
707 glUniform2f(glGetUniformLocation(bloom1Shader, "offset"), offset.x, offset.y); 708 glUniform2f(glGetUniformLocation(bloom1Shader, "offset"), offset.x, offset.y);
708 709
709 glEnableVertexAttribArray(0); 710 glEnableVertexAttribArray(0);
710 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); 711 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
711 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); 712 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
@@ -720,17 +721,17 @@ void Texture::renderScreen() const
720 fprintf(stderr, "Renderer not initialized\n"); 721 fprintf(stderr, "Renderer not initialized\n");
721 exit(-1); 722 exit(-1);
722 } 723 }
723 724
724 // First we're going to composite our frame with the previous frame 725 // First we're going to composite our frame with the previous frame
725 // We start by setting up the framebuffer 726 // We start by setting up the framebuffer
726 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); 727 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer);
727 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0); 728 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0);
728 729
729 // Set up the shader 730 // Set up the shader
730 glViewport(0,0,GAME_WIDTH,GAME_HEIGHT); 731 glViewport(0,0,GAME_WIDTH,GAME_HEIGHT);
731 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 732 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
732 glUseProgram(ntscShader); 733 glUseProgram(ntscShader);
733 734
734 // Use the current frame texture, nearest neighbor and clamped to edge 735 // Use the current frame texture, nearest neighbor and clamped to edge
735 glActiveTexture(GL_TEXTURE0); 736 glActiveTexture(GL_TEXTURE0);
736 glBindTexture(GL_TEXTURE_2D, texID); 737 glBindTexture(GL_TEXTURE_2D, texID);
@@ -739,7 +740,7 @@ void Texture::renderScreen() const
739 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 740 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
740 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 741 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
741 glUniform1i(glGetUniformLocation(ntscShader, "curFrameSampler"), 0); 742 glUniform1i(glGetUniformLocation(ntscShader, "curFrameSampler"), 0);
742 743
743 // Use the previous frame composite texture, nearest neighbor and clamped to edge 744 // Use the previous frame composite texture, nearest neighbor and clamped to edge
744 glActiveTexture(GL_TEXTURE1); 745 glActiveTexture(GL_TEXTURE1);
745 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[(curBuf + 1) % 2]); 746 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[(curBuf + 1) % 2]);
@@ -748,13 +749,13 @@ void Texture::renderScreen() const
748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 749 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
749 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 750 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
750 glUniform1i(glGetUniformLocation(ntscShader, "prevFrameSampler"), 1); 751 glUniform1i(glGetUniformLocation(ntscShader, "prevFrameSampler"), 1);
751 752
752 // Load the NTSC artifact texture 753 // Load the NTSC artifact texture
753 glActiveTexture(GL_TEXTURE2); 754 glActiveTexture(GL_TEXTURE2);
754 glBindTexture(GL_TEXTURE_2D, artifactsTex); 755 glBindTexture(GL_TEXTURE_2D, artifactsTex);
755 glUniform1i(glGetUniformLocation(ntscShader, "NTSCArtifactSampler"), 2); 756 glUniform1i(glGetUniformLocation(ntscShader, "NTSCArtifactSampler"), 2);
756 glUniform1f(glGetUniformLocation(ntscShader, "NTSCLerp"), curBuf * 1.0); 757 glUniform1f(glGetUniformLocation(ntscShader, "NTSCLerp"), curBuf * 1.0);
757 758
758 if ((rand() % 60) == 0) 759 if ((rand() % 60) == 0)
759 { 760 {
760 // Change the 0.0 to a 1.0 or a 10.0 for a glitchy effect! 761 // Change the 0.0 to a 1.0 or a 10.0 for a glitchy effect!
@@ -762,7 +763,7 @@ void Texture::renderScreen() const
762 } else { 763 } else {
763 glUniform1f(glGetUniformLocation(ntscShader, "Tuning_NTSC"), 0.0); 764 glUniform1f(glGetUniformLocation(ntscShader, "Tuning_NTSC"), 0.0);
764 } 765 }
765 766
766 // Render our composition 767 // Render our composition
767 glEnableVertexAttribArray(0); 768 glEnableVertexAttribArray(0);
768 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); 769 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
@@ -776,7 +777,7 @@ void Texture::renderScreen() const
776 glViewport(0,0,buffer_width,buffer_height); 777 glViewport(0,0,buffer_width,buffer_height);
777 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 778 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
778 glUseProgram(finalShader); 779 glUseProgram(finalShader);
779 780
780 // Use the composited frame texture, linearly filtered and filling in black for the border 781 // Use the composited frame texture, linearly filtered and filling in black for the border
781 glActiveTexture(GL_TEXTURE0); 782 glActiveTexture(GL_TEXTURE0);
782 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[curBuf]); 783 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[curBuf]);
@@ -788,70 +789,70 @@ void Texture::renderScreen() const
788 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); 789 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
789 glGenerateMipmap(GL_TEXTURE_2D); 790 glGenerateMipmap(GL_TEXTURE_2D);
790 glUniform1i(glGetUniformLocation(finalShader, "rendertex"), 0); 791 glUniform1i(glGetUniformLocation(finalShader, "rendertex"), 0);
791 792
792 // Use the scanlines texture 793 // Use the scanlines texture
793 glActiveTexture(GL_TEXTURE1); 794 glActiveTexture(GL_TEXTURE1);
794 glBindTexture(GL_TEXTURE_2D, scanlinesTex); 795 glBindTexture(GL_TEXTURE_2D, scanlinesTex);
795 glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1); 796 glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1);
796 797
797 // Initialize the MVP matrices 798 // Initialize the MVP matrices
798 glm::mat4 p_matrix = glm::perspective(glm::radians(25.0f), (float) buffer_width / (float) buffer_height, 0.1f, 100.0f); 799 glm::mat4 p_matrix = glm::perspective(glm::radians(25.0f), (float) buffer_width / (float) buffer_height, 0.1f, 100.0f);
799 glm::mat4 v_matrix = glm::lookAt(glm::vec3(3.75,0,0), glm::vec3(0,0,0), glm::vec3(0,1,0)); 800 glm::mat4 v_matrix = glm::lookAt(glm::vec3(3.75,0,0), glm::vec3(0,0,0), glm::vec3(0,1,0));
800 glm::mat4 m_matrix = glm::mat4(1.0); 801 glm::mat4 m_matrix = glm::mat4(1.0);
801 glm::mat4 mvp_matrix = p_matrix * v_matrix * m_matrix; 802 glm::mat4 mvp_matrix = p_matrix * v_matrix * m_matrix;
802 803
803 glUniformMatrix4fv(glGetUniformLocation(finalShader, "MVP"), 1, GL_FALSE, &mvp_matrix[0][0]); 804 glUniformMatrix4fv(glGetUniformLocation(finalShader, "MVP"), 1, GL_FALSE, &mvp_matrix[0][0]);
804 glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]); 805 glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]);
805 glUniform2f(glGetUniformLocation(finalShader, "resolution"), buffer_width, buffer_height); 806 glUniform2f(glGetUniformLocation(finalShader, "resolution"), buffer_width, buffer_height);
806 glUniform1f(glGetUniformLocation(finalShader, "iGlobalTime"), glfwGetTime()); 807 glUniform1f(glGetUniformLocation(finalShader, "iGlobalTime"), glfwGetTime());
807 glUniform3f(glGetUniformLocation(finalShader, "frameColor"), 0.76f, 0.78f, 0.81f); 808 glUniform3f(glGetUniformLocation(finalShader, "frameColor"), 0.76f, 0.78f, 0.81f);
808 809
809 glEnableVertexAttribArray(0); 810 glEnableVertexAttribArray(0);
810 glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); 811 glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer);
811 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); 812 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
812 813
813 glEnableVertexAttribArray(1); 814 glEnableVertexAttribArray(1);
814 glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); 815 glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer);
815 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); 816 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
816 817
817 glEnableVertexAttribArray(2); 818 glEnableVertexAttribArray(2);
818 glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); 819 glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer);
819 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); 820 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
820 821
821 glDrawArrays(GL_TRIANGLES, 0, mesh_numvertices); 822 glDrawArrays(GL_TRIANGLES, 0, mesh_numvertices);
822 glDisableVertexAttribArray(2); 823 glDisableVertexAttribArray(2);
823 glDisableVertexAttribArray(1); 824 glDisableVertexAttribArray(1);
824 glDisableVertexAttribArray(0); 825 glDisableVertexAttribArray(0);
825 826
826 // First pass of bloom! 827 // First pass of bloom!
827 glm::vec2 buffer_size = glm::vec2(buffer_width, buffer_height); 828 glm::vec2 buffer_size = glm::vec2(buffer_width, buffer_height);
828 bloomPass1(preBloomTex, bloomPassTex1, true, buffer_size, buffer_size / 4.0f); 829 bloomPass1(preBloomTex, bloomPassTex1, true, buffer_size, buffer_size / 4.0f);
829 bloomPass1(bloomPassTex1, bloomPassTex2, false, buffer_size / 4.0f, buffer_size / 4.0f); 830 bloomPass1(bloomPassTex1, bloomPassTex2, false, buffer_size / 4.0f, buffer_size / 4.0f);
830 831
831 // Do the second pass of bloom and render to screen 832 // Do the second pass of bloom and render to screen
832 glBindFramebuffer(GL_FRAMEBUFFER, 0); 833 glBindFramebuffer(GL_FRAMEBUFFER, 0);
833 glViewport(0, 0, buffer_width, buffer_height); 834 glViewport(0, 0, buffer_width, buffer_height);
834 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 835 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
835 glUseProgram(bloom2Shader); 836 glUseProgram(bloom2Shader);
836 837
837 glActiveTexture(GL_TEXTURE0); 838 glActiveTexture(GL_TEXTURE0);
838 glBindTexture(GL_TEXTURE_2D, preBloomTex); 839 glBindTexture(GL_TEXTURE_2D, preBloomTex);
839 glUniform1i(glGetUniformLocation(bloom2Shader, "clearTex"), 0); 840 glUniform1i(glGetUniformLocation(bloom2Shader, "clearTex"), 0);
840 841
841 glActiveTexture(GL_TEXTURE1); 842 glActiveTexture(GL_TEXTURE1);
842 glBindTexture(GL_TEXTURE_2D, bloomPassTex2); 843 glBindTexture(GL_TEXTURE_2D, bloomPassTex2);
843 glUniform1i(glGetUniformLocation(bloom2Shader, "blurTex"), 1); 844 glUniform1i(glGetUniformLocation(bloom2Shader, "blurTex"), 1);
844 845
845 glUniform1f(glGetUniformLocation(bloom2Shader, "iGlobalTime"), glfwGetTime()); 846 glUniform1f(glGetUniformLocation(bloom2Shader, "iGlobalTime"), glfwGetTime());
846 847
847 glEnableVertexAttribArray(0); 848 glEnableVertexAttribArray(0);
848 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); 849 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
849 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); 850 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
850 glDrawArrays(GL_TRIANGLES, 0, 6); 851 glDrawArrays(GL_TRIANGLES, 0, 6);
851 glDisableVertexAttribArray(0); 852 glDisableVertexAttribArray(0);
852 853
853 glfwSwapBuffers(window); 854 glfwSwapBuffers(window);
854 855
855 curBuf = (curBuf + 1) % 2; 856 curBuf = (curBuf + 1) % 2;
856} 857}
857 858
diff --git a/src/renderer.h b/src/renderer.h index 84ad688..6dccf7a 100644 --- a/src/renderer.h +++ b/src/renderer.h
@@ -24,7 +24,7 @@ class Texture {
24 void blit(const Texture& src, Rectangle srcrect, Rectangle dstrect, double alpha = 1.0); 24 void blit(const Texture& src, Rectangle srcrect, Rectangle dstrect, double alpha = 1.0);
25 void renderScreen() const; 25 void renderScreen() const;
26 Rectangle entirety() const; 26 Rectangle entirety() const;
27 27
28 private: 28 private:
29 GLuint texID; 29 GLuint texID;
30 int width; 30 int width;
diff --git a/src/system.h b/src/system.h new file mode 100644 index 0000000..489afd0 --- /dev/null +++ b/src/system.h
@@ -0,0 +1,20 @@
1#ifndef SYSTEM_H_B61A8CEA
2#define SYSTEM_H_B61A8CEA
3
4class Game;
5
6class System {
7public:
8 System(Game& game)
9 : game(game) {}
10
11 virtual ~System() = default;
12
13 virtual void tick(double dt) = 0;
14
15protected:
16
17 Game& game;
18};
19
20#endif /* end of include guard: SYSTEM_H_B61A8CEA */
diff --git a/src/system_manager.h b/src/system_manager.h new file mode 100644 index 0000000..e2c98cb --- /dev/null +++ b/src/system_manager.h
@@ -0,0 +1,44 @@
1#ifndef SYSTEM_MANAGER_H_544E6056
2#define SYSTEM_MANAGER_H_544E6056
3
4#include <list>
5#include <memory>
6#include <map>
7#include <typeindex>
8#include <stdexcept>
9#include "system.h"
10
11class SystemManager {
12private:
13
14 std::list<std::unique_ptr<System>> loop;
15 std::map<std::type_index, System*> systems;
16
17public:
18
19 template <class T, class... Args>
20 void emplaceSystem(Game& game, Args&&... args)
21 {
22 std::unique_ptr<T> ptr(new T(game, std::forward<Args>(args)...));
23 std::type_index systemType = typeid(T);
24
25 systems[systemType] = ptr.get();
26 loop.push_back(std::move(ptr));
27 }
28
29 template <class T>
30 T& getSystem()
31 {
32 std::type_index systemType = typeid(T);
33
34 if (!systems.count(systemType))
35 {
36 throw std::invalid_argument("Cannot get non-existent system");
37 }
38
39 return *dynamic_cast<T*>(systems[systemType]);
40 }
41
42};
43
44#endif /* end of include guard: SYSTEM_MANAGER_H_544E6056 */
diff --git a/src/systems/controlling.cpp b/src/systems/controlling.cpp new file mode 100644 index 0000000..456da3b --- /dev/null +++ b/src/systems/controlling.cpp
@@ -0,0 +1,168 @@
1#include "controlling.h"
2#include "game.h"
3#include "components/controllable.h"
4#include "components/ponderable.h"
5#include "components/animatable.h"
6#include "components/droppable.h"
7#include "direction.h"
8#include "muxer.h"
9#include "consts.h"
10
11void ControllingSystem::tick(double dt)
12{
13 while (!actions.empty())
14 {
15 int key = actions.front().first;
16 int action = actions.front().second;
17
18 auto entities = game.getEntityManager().getEntitiesWithComponents<ControllableComponent, PonderableComponent, AnimatableComponent, DroppableComponent>();
19 for (auto entity : entities)
20 {
21 auto& controllable = game.getEntityManager().getComponent<ControllableComponent>(entity);
22
23 if (action == GLFW_PRESS)
24 {
25 if (key == controllable.getLeftKey())
26 {
27 controllable.setHoldingLeft(true);
28
29 if (!controllable.isFrozen())
30 {
31 walkLeft(entity);
32 }
33 } else if (key == controllable.getRightKey())
34 {
35 controllable.setHoldingRight(true);
36
37 if (!controllable.isFrozen())
38 {
39 walkRight(entity);
40 }
41 } else if (key == controllable.getJumpKey())
42 {
43 if (!controllable.isFrozen())
44 {
45 jump(entity);
46 }
47 } else if (key == controllable.getDropKey())
48 {
49 if (!controllable.isFrozen())
50 {
51 drop(entity, true);
52 }
53 }
54 } else if (action == GLFW_RELEASE)
55 {
56 if (key == controllable.getLeftKey())
57 {
58 controllable.setHoldingLeft(false);
59
60 if (!controllable.isFrozen())
61 {
62 if (controllable.isHoldingRight())
63 {
64 walkRight(entity);
65 } else {
66 stopWalking(entity);
67 }
68 }
69 } else if (key == controllable.getRightKey())
70 {
71 controllable.setHoldingRight(false);
72
73 if (!controllable.isFrozen())
74 {
75 if (controllable.isHoldingRight())
76 {
77 walkLeft(entity);
78 } else {
79 stopWalking(entity);
80 }
81 }
82 } else if (key == controllable.getDropKey())
83 {
84 if (!controllable.isFrozen())
85 {
86 drop(entity, false);
87 }
88 } else if (key == controllable.getJumpKey())
89 {
90 if (!controllable.isFrozen())
91 {
92 stopJumping(entity);
93 }
94 }
95 }
96 }
97
98 actions.pop();
99 }
100}
101
102void ControllingSystem::input(int key, int action)
103{
104 actions.push(std::make_pair(key, action));
105}
106
107void ControllingSystem::walkLeft(int entity)
108{
109 auto& ponderable = game.getEntityManager().getComponent<PonderableComponent>(entity);
110 auto& animatable = game.getEntityManager().getComponent<AnimatableComponent>(entity);
111
112 ponderable.setVelocityX(-90);
113
114 animatable.setDirection(Direction::Left);
115 animatable.setWalking(true);
116}
117
118void ControllingSystem::walkRight(int entity)
119{
120 auto& ponderable = game.getEntityManager().getComponent<PonderableComponent>(entity);
121 auto& animatable = game.getEntityManager().getComponent<AnimatableComponent>(entity);
122
123 ponderable.setVelocityX(90);
124
125 animatable.setDirection(Direction::Right);
126 animatable.setWalking(true);
127}
128
129void ControllingSystem::stopWalking(int entity)
130{
131 auto& ponderable = game.getEntityManager().getComponent<PonderableComponent>(entity);
132 auto& animatable = game.getEntityManager().getComponent<AnimatableComponent>(entity);
133
134 ponderable.setVelocityX(0);
135
136 animatable.setWalking(false);
137}
138
139void ControllingSystem::jump(int entity)
140{
141 auto& ponderable = game.getEntityManager().getComponent<PonderableComponent>(entity);
142 auto& animatable = game.getEntityManager().getComponent<AnimatableComponent>(entity);
143
144 playSound("res/Randomize87.wav", 0.25);
145
146 ponderable.setVelocityY(JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3));
147 ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3));
148
149 animatable.setJumping(true);
150}
151
152void ControllingSystem::stopJumping(int entity)
153{
154 auto& ponderable = game.getEntityManager().getComponent<PonderableComponent>(entity);
155 auto& animatable = game.getEntityManager().getComponent<AnimatableComponent>(entity);
156
157 ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233));
158 animatable.setJumping(false);
159}
160
161void ControllingSystem::drop(int entity, bool start)
162{
163 auto& animatable = game.getEntityManager().getComponent<AnimatableComponent>(entity);
164 auto& droppable = game.getEntityManager().getComponent<DroppableComponent>(entity);
165
166 droppable.setDroppable(start);
167 animatable.setCrouching(start);
168}
diff --git a/src/systems/controlling.h b/src/systems/controlling.h new file mode 100644 index 0000000..30210b3 --- /dev/null +++ b/src/systems/controlling.h
@@ -0,0 +1,26 @@
1#ifndef CONTROLLING_H_80B1BB8D
2#define CONTROLLING_H_80B1BB8D
3
4#include "system.h"
5#include <queue>
6
7class ControllingSystem : public System {
8 public:
9 ControllingSystem(Game& game)
10 : System(game) {}
11
12 void tick(double dt);
13 void input(int key, int action);
14
15 private:
16 void walkLeft(int entity);
17 void walkRight(int entity);
18 void stopWalking(int entity);
19 void jump(int entity);
20 void stopJumping(int entity);
21 void drop(int entity, bool start);
22
23 std::queue<std::pair<int,int>> actions;
24};
25
26#endif /* end of include guard: CONTROLLING_H_80B1BB8D */
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp new file mode 100644 index 0000000..50a8bc8 --- /dev/null +++ b/src/systems/pondering.cpp
@@ -0,0 +1,23 @@
1#include "pondering.h"
2#include "game.h"
3#include "components/ponderable.h"
4#include "components/transformable.h"
5
6void PonderingSystem::tick(double dt)
7{
8 auto entities = game.getEntityManager().getEntitiesWithComponents<PonderableComponent, TransformableComponent>();
9
10 for (auto entity : entities)
11 {
12 auto& transformable = game.getEntityManager().getComponent<TransformableComponent>(entity);
13 auto& ponderable = game.getEntityManager().getComponent<PonderableComponent>(entity);
14
15 // Accelerate
16 ponderable.setVelocityX(ponderable.getVelocityX() + ponderable.getAccelX() * dt);
17 ponderable.setVelocityY(ponderable.getVelocityY() + ponderable.getAccelY() * dt);
18
19 // Move
20 transformable.setX(transformable.getX() + ponderable.getVelocityX() * dt);
21 transformable.setY(transformable.getY() + ponderable.getVelocityY() * dt);
22 }
23}
diff --git a/src/systems/pondering.h b/src/systems/pondering.h new file mode 100644 index 0000000..3fe5473 --- /dev/null +++ b/src/systems/pondering.h
@@ -0,0 +1,14 @@
1#ifndef PONDERING_H_F2530E0E
2#define PONDERING_H_F2530E0E
3
4#include "system.h"
5
6class PonderingSystem : public System {
7 public:
8 PonderingSystem(Game& game)
9 : System(game) {}
10
11 void tick(double dt);
12};
13
14#endif /* end of include guard: PONDERING_H_F2530E0E */
diff --git a/src/systems/rendering.cpp b/src/systems/rendering.cpp new file mode 100644 index 0000000..251c2bc --- /dev/null +++ b/src/systems/rendering.cpp
@@ -0,0 +1,21 @@
1#include "rendering.h"
2#include "game.h"
3#include "components/animatable.h"
4#include "components/transformable.h"
5
6void RenderingSystem::tick(double dt)
7{
8 texture.fill(texture.entirety(), 0, 0, 0);
9
10 std::set<int> spriteEntities = game.getEntityManager().getEntitiesWithComponents<AnimatableComponent, TransformableComponent>();
11 for (int entity : spriteEntities)
12 {
13 auto& sprite = game.getEntityManager().getComponent<AnimatableComponent>(entity);
14 auto& transform = game.getEntityManager().getComponent<TransformableComponent>(entity);
15 Rectangle dstrect {(int) transform.getX(), (int) transform.getY(), transform.getW(), transform.getH()};
16
17 texture.blit(sprite.getTexture(), sprite.getFrameRect(), dstrect);
18 }
19
20 texture.renderScreen();
21}
diff --git a/src/systems/rendering.h b/src/systems/rendering.h new file mode 100644 index 0000000..cec72e2 --- /dev/null +++ b/src/systems/rendering.h
@@ -0,0 +1,19 @@
1#ifndef RENDERING_H_76ABC02A
2#define RENDERING_H_76ABC02A
3
4#include "system.h"
5#include "renderer.h"
6#include "consts.h"
7
8class RenderingSystem : public System {
9 public:
10 RenderingSystem(Game& game)
11 : System(game) {}
12
13 void tick(double dt);
14
15 private:
16 Texture texture {GAME_WIDTH, GAME_HEIGHT};
17};
18
19#endif /* end of include guard: RENDERING_H_76ABC02A */
diff --git a/src/world.cpp b/src/world.cpp deleted file mode 100644 index 0c61c47..0000000 --- a/src/world.cpp +++ /dev/null
@@ -1,150 +0,0 @@
1#include "world.h"
2#include <libxml/parser.h>
3#include "consts.h"
4
5World::World(const char* filename)
6{
7 xmlDocPtr doc = xmlParseFile(filename);
8 if (doc == nullptr)
9 {
10 exit(2);
11 }
12
13 xmlNodePtr top = xmlDocGetRootElement(doc);
14 if (top == nullptr)
15 {
16 exit(2);
17 }
18
19 if (xmlStrcmp(top->name, (const xmlChar*) "world"))
20 {
21 exit(2);
22 }
23
24 xmlChar* startxKey = xmlGetProp(top, (xmlChar*) "startx");
25 if (startxKey == 0) exit(2);
26 startX = atoi((char*) startxKey);
27 xmlFree(startxKey);
28
29 xmlChar* startyKey = xmlGetProp(top, (xmlChar*) "starty");
30 if (startyKey == 0) exit(2);
31 startY = atoi((char*) startyKey);
32 xmlFree(startyKey);
33
34 xmlChar* startmapKey = xmlGetProp(top, (xmlChar*) "startmap");
35 if (startxKey == 0) exit(2);
36 startMap = atoi((char*) startmapKey);
37 xmlFree(startmapKey);
38
39 for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next)
40 {
41 if (!xmlStrcmp(node->name, (const xmlChar*) "map"))
42 {
43 xmlChar* idKey = xmlGetProp(node, (xmlChar*) "id");
44 if (idKey == 0) exit(2);
45 int theId = atoi((char*) idKey);
46 xmlFree(idKey);
47
48 maps.emplace(theId, theId);
49 Map& map = maps[theId];
50
51 xmlChar* titleKey = xmlGetProp(node, (xmlChar*) "title");
52 if (titleKey == 0) exit(2);
53 map.setTitle((char*) titleKey);
54 xmlFree(titleKey);
55
56 for (xmlNodePtr mapNode = node->xmlChildrenNode; mapNode != NULL; mapNode = mapNode->next)
57 {
58 if (!xmlStrcmp(mapNode->name, (const xmlChar*) "environment"))
59 {
60 xmlChar* key = xmlNodeGetContent(mapNode);
61 int* mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int));
62 mapdata[0] = atoi(strtok((char*) key, ",\n"));
63 for (int i=1; i<(MAP_WIDTH*MAP_HEIGHT); i++)
64 {
65 mapdata[i] = atoi(strtok(NULL, ",\n"));
66 }
67 map.setMapdata(mapdata);
68 xmlFree(key);
69 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "entity"))
70 {
71 Map::EntityData data;
72
73 xmlChar* typeKey = xmlGetProp(mapNode, (const xmlChar*) "type");
74 if (typeKey == 0) exit(2);
75 data.name = (char*) typeKey;
76 xmlFree(typeKey);
77
78 xmlChar* xKey = xmlGetProp(mapNode, (const xmlChar*) "x");
79 if (xKey == 0) exit(2);
80 data.position.first = atoi((char*) xKey);
81 xmlFree(xKey);
82
83 xmlChar* yKey = xmlGetProp(mapNode, (const xmlChar*) "y");
84 if (yKey == 0) exit(2);
85 data.position.second = atoi((char*) yKey);
86 xmlFree(yKey);
87
88 for (xmlNodePtr entityNode = mapNode->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next)
89 {
90 if (!xmlStrcmp(entityNode->name, (xmlChar*) "item"))
91 {
92 xmlChar* itemIdKey = xmlGetProp(entityNode, (const xmlChar*) "id");
93 if (itemIdKey == 0) exit(2);
94 std::string itemId = (char*) itemIdKey;
95 xmlFree(itemIdKey);
96
97 xmlChar* itemIdVal = xmlNodeGetContent(entityNode);
98 if (itemIdVal == 0) exit(2);
99 data.items[itemId] = atoi((char*) itemIdVal);
100 xmlFree(itemIdVal);
101 }
102 }
103
104 map.addEntity(data);
105 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "adjacent"))
106 {
107 Map::MoveDir direction;
108 Map::MoveType moveType;
109 int mapId = 0;
110
111 xmlChar* dirKey = xmlGetProp(mapNode, (const xmlChar*) "dir");
112 if (dirKey == 0) exit(2);
113 direction = Map::moveDirForShort((char*) dirKey);
114 xmlFree(dirKey);
115
116 xmlChar* typeKey = xmlGetProp(mapNode, (const xmlChar*) "type");
117 if (typeKey == 0) exit(2);
118 moveType = Map::moveTypeForShort((char*) typeKey);
119 xmlFree(typeKey);
120
121 xmlChar* mapIdKey = xmlGetProp(mapNode, (const xmlChar*) "map");
122 if (mapIdKey != 0)
123 {
124 mapId = atoi((char*) mapIdKey);
125 }
126 xmlFree(mapIdKey);
127
128 map.setAdjacent(direction, moveType, mapId);
129 }
130 }
131 }
132 }
133
134 xmlFreeDoc(doc);
135}
136
137const Map& World::getMap(int id) const
138{
139 return maps.at(id);
140}
141
142const Map& World::getStartingMap() const
143{
144 return maps.at(startMap);
145}
146
147std::pair<int, int> World::getStartingPosition() const
148{
149 return std::make_pair(startX, startY);
150}
diff --git a/src/world.h b/src/world.h deleted file mode 100644 index f566487..0000000 --- a/src/world.h +++ /dev/null
@@ -1,21 +0,0 @@
1#ifndef WORLD_H
2#define WORLD_H
3
4#include <map>
5#include "map.h"
6
7class World {
8 public:
9 World(const char* filename);
10 const Map& getMap(int id) const;
11 const Map& getStartingMap() const;
12 std::pair<int, int> getStartingPosition() const;
13
14 private:
15 std::map<int, Map> maps;
16 int startMap;
17 int startX;
18 int startY;
19};
20
21#endif /* end of include guard: WORLD_H */