summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--res/childoflight.txt26
-rw-r--r--res/read_instruction.pngbin0 -> 10146 bytes
-rw-r--r--src/animation.h2
-rw-r--r--src/direction.h12
-rw-r--r--src/game.cpp70
-rw-r--r--src/game.h14
-rw-r--r--src/map.h5
-rw-r--r--src/renderer.cpp22
-rw-r--r--src/renderer.h1
9 files changed, 142 insertions, 10 deletions
diff --git a/res/childoflight.txt b/res/childoflight.txt new file mode 100644 index 0000000..d65796d --- /dev/null +++ b/res/childoflight.txt
@@ -0,0 +1,26 @@
1"Your life, and the lives of those who believe in you. Are you willing to put it all on the line?"
2Those words echoed in the child's head more than any other as he put his hands on the lamp. Through it, he could feel the sun's enormous presence far below him. Its power was palpable; a gentle thrumming that tickled his fingers. It was strong -- stronger and nearer than it had been with the other temples. Up close, it felt like all there was.
3The lamp was light in his hands. Without a word he pulled, and light poured out. He closed his eyes and all he saw was light.
4The child was nowhere when he awoke. Bright, white emptiness stretched out in all directions. He gulped as he looked around -- felt that emptiness resonate in his chest.
5"Hello?" he called out. No one answered.
6Trembling, he pushed himself to his feet. He'd been through countless battles, been spat on by people he used to trust, and even took down the immortal ruler of the world. He told himself he could handle whatever this was.
7He hadn't had to do those things by himself, though.
8The child took a step. His bare foot thudded against an invisible ground. When nothing further happened, he kept going. Choose a direction and just walk, he thought. There was nothing else to do.
9"Is anyone out there?"
10His steps turned inside out. The ground flipped over and curved in on itself. He saw figures in the distance but when he approached he realized it was himself he was seeing. He felt a headache start to come on, and it only grew when something finally did appear.
11A black spiral, twisting out from beneath him. He climbed and climbed, and his feet hurt and his chest ached and his arms twisted but it wasn't enough to take him down. Somehow he felt like nothing would ever be able to stop him again. One foot after another he climbed and watched the matter splay out before him. This thing he'd found, it was immense. It was infinite.
12It was the Sun.
13"Pure hearted one," it said without saying, not a roaring voice but a subtle understanding planted in the child's mind. "We meet at last."
14The child gulped. Throughout all that time searching for and sanctifying the lamps, he hadn't considered what would actually happen if he won. But now here he was, facing infinity itself, and it dawned on him the Sun had probably been sealed away for a good reason.
15Would saving the world be worth the consequences?
16"H-hello?" he stammered. It came out as nothing more than a squeak, but a shift in the Sun's surface -- starry as the night sky -- told him that it heard.
17"For thousands of years I have slept here, ever since the world grew past the need for my power."
18An eye -- incomprehensibly large -- regarded the boy who'd raised it from its slumber. An eye which had seen countless things: births, deaths, loves, wars. A being who'd caused so many of them, and had to be shut away to contain its limitless power. A power that was once again free.
19The child took a deep breath. "I'm sorry I woke you up," he said, voice wobbling like a teeter totter. "I had to light the lamps to stop someone else from doing it. He wanted to end the world. But I want to save it."
20"I've seen visions in my dreams of your world crumbling. I've felt your despair. I've heard your cries for help. I've seen your strength, clear as day, in the pieces of your heart that you shared."
21The child saw himself reflected in that eye. Saw his feet lift off the ground, pulled by some invisible force. Saw the sparks of magic flying around his hands, felt his being churning out of control as something dark, something horrible, something unfathomably ancient poured into his mind, squeezing and pulling it like taffy, tearing it apart and putting it back together.
22"Now my power is needed once again. As you have shared with me, I will share it in return."
23"Wh-" he tried to ask, but his throat squeezed tight and choked the words to death. Sweat poured from his brow as the worst fever he'd ever felt took hold. His head was being thrust beneath the surface of the water, his torso was being struck by lightning from a machine.
24The Sun watched him float there, writhing and sweating and sparking with violent electricity. It closed its eye.
25"I promise you that I will not miss it."
26The thrumming from before was inside of him now. The Sun's heartbeat was gone -- it was his own. The child opened his mouth to scream, and what came out was light. \ No newline at end of file
diff --git a/res/read_instruction.png b/res/read_instruction.png new file mode 100644 index 0000000..6e924e6 --- /dev/null +++ b/res/read_instruction.png
Binary files differ
diff --git a/src/animation.h b/src/animation.h index 0108c12..f1eddb6 100644 --- a/src/animation.h +++ b/src/animation.h
@@ -20,6 +20,8 @@ public:
20 return frames_.at(animations_.at(animationId_).at(animationFrame_)); 20 return frames_.at(animations_.at(animationId_).at(animationFrame_));
21 } 21 }
22 22
23 Direction getDirection() const { return dir_; }
24
23 void update(int dt); 25 void update(int dt);
24 26
25private: 27private:
diff --git a/src/direction.h b/src/direction.h index 0fe3e5a..14ea0a5 100644 --- a/src/direction.h +++ b/src/direction.h
@@ -3,6 +3,9 @@
3 3
4#include <string_view> 4#include <string_view>
5#include <stdexcept> 5#include <stdexcept>
6#include <tuple>
7
8using coord = std::tuple<int, int>;
6 9
7enum class Direction { 10enum class Direction {
8 up, 11 up,
@@ -19,4 +22,13 @@ inline Direction directionFromString(std::string_view str) {
19 throw std::invalid_argument("Invalid direction: " + std::string(str)); 22 throw std::invalid_argument("Invalid direction: " + std::string(str));
20} 23}
21 24
25inline coord coordInDirection(int x, int y, Direction dir) {
26 switch (dir) {
27 case Direction::up: return {x, y-1};
28 case Direction::down: return {x, y+1};
29 case Direction::left: return {x-1, y};
30 case Direction::right: return {x+1, y};
31 }
32}
33
22#endif /* end of include guard: DIRECTION_H_42BDAFB9 */ 34#endif /* end of include guard: DIRECTION_H_42BDAFB9 */
diff --git a/src/game.cpp b/src/game.cpp index 170f584..301447f 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -2,6 +2,7 @@
2#include <vector> 2#include <vector>
3#include <fov.h> 3#include <fov.h>
4#include <iostream> 4#include <iostream>
5#include <fstream>
5#include "util.h" 6#include "util.h"
6#include "renderer.h" 7#include "renderer.h"
7#include "consts.h" 8#include "consts.h"
@@ -23,6 +24,12 @@ Game::Game(std::mt19937& rng, Muxer& muxer) :
23 } 24 }
24 25
25 tick(); 26 tick();
27
28 std::ifstream textFile("../res/childoflight.txt");
29 std::string line;
30 while (std::getline(textFile, line)) {
31 signTexts.push_back(line);
32 }
26} 33}
27 34
28inline bool isTileSetOrNotLit(const Map& map, int x, int y) 35inline bool isTileSetOrNotLit(const Map& map, int x, int y)
@@ -119,7 +126,7 @@ void Game::tick(bool onlyDark)
119 126
120bool Game::movePlayer(int x, int y) 127bool Game::movePlayer(int x, int y)
121{ 128{
122 if (map.at(x,y).tile == Tile::Floor) 129 if (map.at(x,y).tile == Tile::Floor && !map.at(x,y).sign)
123 { 130 {
124 if (map.at(player_x, player_y).tile == Tile::Floor) 131 if (map.at(player_x, player_y).tile == Tile::Floor)
125 { 132 {
@@ -258,16 +265,36 @@ void Game::recalculateRender() {
258 map.at(x,y).dirtyRender = false; 265 map.at(x,y).dirtyRender = false;
259 266
260 if (map.at(x,y).tile == Tile::Floor) { 267 if (map.at(x,y).tile == Tile::Floor) {
261 if (std::bernoulli_distribution(0.05)(rng)) { 268 int renderDesc = 0;
269 if (isTileSetOrNotLit(map, x-1, y-1)) renderDesc |= (1 << 7);
270 if (isTileSetOrNotLit(map, x , y-1)) renderDesc |= (1 << 6);
271 if (isTileSetOrNotLit(map, x+1, y-1)) renderDesc |= (1 << 5);
272 if (isTileSetOrNotLit(map, x+1, y )) renderDesc |= (1 << 4);
273 if (isTileSetOrNotLit(map, x+1, y+1)) renderDesc |= (1 << 3);
274 if (isTileSetOrNotLit(map, x , y+1)) renderDesc |= (1 << 2);
275 if (isTileSetOrNotLit(map, x-1, y+1)) renderDesc |= (1 << 1);
276 if (isTileSetOrNotLit(map, x-1, y )) renderDesc |= (1 << 0);
277
278 if (renderDesc == 0 && map.at(x,y).sign) {
279 map.at(x,y).renderId = TilesetIndex(24, 13);
280 } else if (std::bernoulli_distribution(0.05)(rng)) {
262 static const std::vector<int> furnishings { 281 static const std::vector<int> furnishings {
263 TilesetIndex(20, 16), 282 TilesetIndex(20, 16),
264 TilesetIndex(21, 2), 283 TilesetIndex(21, 2),
265 TilesetIndex(22, 2), 284 TilesetIndex(22, 2),
266 TilesetIndex(21, 3), 285 TilesetIndex(21, 3),
267 TilesetIndex(22, 3)}; 286 TilesetIndex(22, 3)};
268 map.at(x,y).renderId = furnishings.at(std::uniform_int_distribution<int>(0, furnishings.size()-1)(rng)); 287
288 if (renderDesc == 0 && !(x == player_x && y == player_y) && std::bernoulli_distribution(0.2)(rng)) {
289 map.at(x,y).renderId = TilesetIndex(24, 13);
290 map.at(x,y).sign = true;
291 } else {
292 map.at(x,y).renderId = furnishings.at(std::uniform_int_distribution<int>(0, furnishings.size()-1)(rng));
293 map.at(x,y).sign = false;
294 }
269 } else { 295 } else {
270 map.at(x,y).renderId = -1; 296 map.at(x,y).renderId = -1;
297 map.at(x,y).sign = false;
271 } 298 }
272 } else if (map.at(x,y).tile == Tile::Wall) { 299 } else if (map.at(x,y).tile == Tile::Wall) {
273 static bool initWalls = false; 300 static bool initWalls = false;
@@ -785,6 +812,43 @@ void Game::update(size_t frameTime) {
785 } 812 }
786 } 813 }
787 814
815 switch (signInstructionState) {
816 case SignInstructionState::Hidden: {
817 auto [lookX, lookY] = coordInDirection(player_x, player_y, playerAnim.getDirection());
818 if (map.at(lookX, lookY).sign) {
819 signInstructionState = SignInstructionState::FadingIn;
820 signFade.start(1000);
821 }
822
823 break;
824 }
825 case SignInstructionState::FadingIn: {
826 signFade.tick(frameTime);
827 if (signFade.isComplete()) {
828 signInstructionState = SignInstructionState::Visible;
829 }
830
831 break;
832 }
833 case SignInstructionState::Visible: {
834 auto [lookX, lookY] = coordInDirection(player_x, player_y, playerAnim.getDirection());
835 if (!map.at(lookX, lookY).sign || losing != LoseState::None) {
836 signInstructionState = SignInstructionState::FadingOut;
837 signFade.start(1000);
838 }
839
840 break;
841 }
842 case SignInstructionState::FadingOut: {
843 signFade.tick(frameTime);
844 if (signFade.isComplete()) {
845 signInstructionState = SignInstructionState::Hidden;
846 }
847
848 break;
849 }
850 }
851
788 if (dirtyLighting) 852 if (dirtyLighting)
789 { 853 {
790 recalculateLighting(); 854 recalculateLighting();
diff --git a/src/game.h b/src/game.h index f307156..71685e6 100644 --- a/src/game.h +++ b/src/game.h
@@ -13,7 +13,7 @@
13#include "consts.h" 13#include "consts.h"
14 14
15constexpr int TilesetIndex(int x, int y) { 15constexpr int TilesetIndex(int x, int y) {
16 return x + y * 24; 16 return x + y * 25;
17} 17}
18 18
19enum class LoseState { 19enum class LoseState {
@@ -23,6 +23,13 @@ enum class LoseState {
23 Outro 23 Outro
24}; 24};
25 25
26enum class SignInstructionState {
27 Hidden,
28 FadingIn,
29 Visible,
30 FadingOut
31};
32
26struct Input { 33struct Input {
27 bool left = false; 34 bool left = false;
28 bool right = false; 35 bool right = false;
@@ -100,6 +107,11 @@ public:
100 Timer losePopPlayerTimer = {3000}; 107 Timer losePopPlayerTimer = {3000};
101 //Timer zoomTimer = {62}; 108 //Timer zoomTimer = {62};
102 109
110 std::vector<std::string> signTexts;
111 int nextSignIndex = 0;
112 SignInstructionState signInstructionState = SignInstructionState::Hidden;
113 Interpolation signFade;
114
103private: 115private:
104 116
105 void tick( 117 void tick(
diff --git a/src/map.h b/src/map.h index 2faac85..de74b14 100644 --- a/src/map.h +++ b/src/map.h
@@ -8,8 +8,7 @@
8#include <map> 8#include <map>
9#include <random> 9#include <random>
10#include "consts.h" 10#include "consts.h"
11 11#include "direction.h"
12using coord = std::tuple<int, int>;
13 12
14enum class Tile { 13enum class Tile {
15 Floor, 14 Floor,
@@ -35,6 +34,8 @@ struct MapData {
35 std::set<coord> litTiles; 34 std::set<coord> litTiles;
36 int renderId = -1; 35 int renderId = -1;
37 bool dirtyRender = true; 36 bool dirtyRender = true;
37 bool sign = false;
38 std::string text;
38}; 39};
39 40
40struct Chunk { 41struct Chunk {
diff --git a/src/renderer.cpp b/src/renderer.cpp index befad8a..2be36ae 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp
@@ -109,6 +109,7 @@ Renderer::Renderer()
109 loadTextureFromFile("../res/player.png", playerSheet_); 109 loadTextureFromFile("../res/player.png", playerSheet_);
110 loadTextureFromFile("../res/runninbloods.png", tileset_); 110 loadTextureFromFile("../res/runninbloods.png", tileset_);
111 loadTextureFromFile("../res/lamp.png", lamp_); 111 loadTextureFromFile("../res/lamp.png", lamp_);
112 loadTextureFromFile("../res/read_instruction.png", readInstruction_);
112 113
113 loadTextureFromFile("../res/title0.png", titles_[0]); 114 loadTextureFromFile("../res/title0.png", titles_[0]);
114 SDL_QueryTexture(titles_[0].get(), nullptr, nullptr, &titleWidths_[0], &titleHeights_[0]); 115 SDL_QueryTexture(titles_[0].get(), nullptr, nullptr, &titleWidths_[0], &titleHeights_[0]);
@@ -171,14 +172,14 @@ void Renderer::renderGame(
171 SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect); 172 SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect);
172 173
173 if (game.map.at(x,y).renderId != -1) { 174 if (game.map.at(x,y).renderId != -1) {
174 tileRect.x = game.map.at(x,y).renderId % 24 * 16; 175 tileRect.x = game.map.at(x,y).renderId % 25 * 16;
175 tileRect.y = game.map.at(x,y).renderId / 24 * 16; 176 tileRect.y = game.map.at(x,y).renderId / 25 * 16;
176 SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect); 177 SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect);
177 } 178 }
178 } else { 179 } else {
179 SDL_Rect tileRect { 180 SDL_Rect tileRect {
180 game.map.at(x,y).renderId % 24 * 16, 181 game.map.at(x,y).renderId % 25 * 16,
181 game.map.at(x,y).renderId / 24 * 16, 182 game.map.at(x,y).renderId / 25 * 16,
182 16, 183 16,
183 16}; 184 16};
184 185
@@ -375,6 +376,19 @@ void Renderer::renderGame(
375 } 376 }
376 377
377 SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr); 378 SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr);
379
380 if (game.signInstructionState != SignInstructionState::Hidden) {
381 int instOpacity = 255;
382 if (game.signInstructionState == SignInstructionState::FadingIn) {
383 instOpacity = game.signFade.getProgress(0, 255);
384 } else if (game.signInstructionState == SignInstructionState::FadingOut) {
385 instOpacity = game.signFade.getProgress(255, 0);
386 }
387
388 SDL_SetTextureAlphaMod(readInstruction_.get(), instOpacity);
389 SDL_RenderCopy(ren_.get(), readInstruction_.get(), nullptr, nullptr);
390 }
391
378 SDL_RenderPresent(ren_.get()); 392 SDL_RenderPresent(ren_.get());
379} 393}
380 394
diff --git a/src/renderer.h b/src/renderer.h index 1364550..de1e125 100644 --- a/src/renderer.h +++ b/src/renderer.h
@@ -137,6 +137,7 @@ private:
137 texture_ptr playerSheet_; 137 texture_ptr playerSheet_;
138 texture_ptr tileset_; 138 texture_ptr tileset_;
139 texture_ptr lamp_; 139 texture_ptr lamp_;
140 texture_ptr readInstruction_;
140 141
141 std::array<texture_ptr, NUM_TITLES> titles_; 142 std::array<texture_ptr, NUM_TITLES> titles_;
142 std::array<int, NUM_TITLES> titleWidths_; 143 std::array<int, NUM_TITLES> titleWidths_;