Skip to content

Commit 0c3be19

Browse files
committed
add tons
Signed-off-by: Slendi <[email protected]>
1 parent f9c23be commit 0c3be19

File tree

15 files changed

+822
-120
lines changed

15 files changed

+822
-120
lines changed

editor.py

Lines changed: 381 additions & 0 deletions
Large diffs are not rendered by default.

src/Color.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@
33
#include <tuple>
44

55
static float get_random_hue(void) {
6-
//int hue = GetRandomValue(0, 360);
7-
//// Avoid the orange, yellow, and green ranges
8-
//while ((hue >= 15 && hue <= 70) || (hue >= 85 && hue <= 150)) {
9-
// hue = GetRandomValue(0, 360);
10-
//}
11-
//return static_cast<float>(hue);
126
return static_cast<float>(GetRandomValue(188, 235));
137
}
148

@@ -39,6 +33,11 @@ ColorPalette ColorPalette::generate(void)
3933
std::tie(p.wall, p.game_background) = get_colors(bg_hue);
4034

4135
float primary_hue = fmod(bg_hue + 180.0f, 360.0f);
36+
37+
if (primary_hue >= 270.0f && primary_hue <= 300.0f) {
38+
primary_hue = fmod(primary_hue + 60.0f, 360.0f);
39+
}
40+
4241
p.primary = ColorFromHSV(primary_hue, fixed_saturation, 0.75f);
4342
p.primary.a = 0xff;
4443

@@ -54,7 +53,7 @@ ColorPalette ColorPalette::generate(void)
5453

5554
p.one_way_zone_background = ColorBrightness(p.game_background, -0.25f);
5655

57-
p.danger_zone_background = ColorFromHSV(0.0f, fixed_saturation, 0.5f);
56+
p.danger_zone_background = ColorLerp(ColorFromHSV(0.0f, fixed_saturation, 0.5f), p.game_background, 0.2);
5857

5958
return p;
6059
}

src/GameState.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ struct GameState {
2626
usize current_dialog_idx, current_dialog_dialog_idx;
2727
f32 dialog_box_y;
2828

29-
int collected_files, total_files;
30-
3129
int total_collected_files = 0;
3230

3331
ColorPalette palette;
3432

3533
std::optional<usize> current_level;
3634

35+
// Audio
36+
Sound explosion;
37+
std::vector<Music> music;
38+
usize current_song;
39+
3740
// Rendering
3841
i32 width;
3942
i32 height;

src/Level.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ Level Level::deserialize(nlohmann::json &data)
8383
level.start_position.x = data["start_position"][0];
8484
level.start_position.y = data["start_position"][1];
8585
level.start_angle = data["start_angle"];
86+
if (!data["on_unlock_dialog"].is_null())
87+
level.on_unlock_dialog = data["on_unlock_dialog"];
8688

8789
for (auto &wallj : data["walls"]) {
8890
Wall wall;
@@ -266,7 +268,7 @@ void Level::render_hud(f64 t)
266268
}
267269
if (t > 1) {
268270
DrawTextEx(g_gs.font,
269-
TextFormat("Files collected: %d/%d", g_gs.collected_files, g_gs.total_files),
271+
TextFormat("Files collected: %d/%d", this->collected_files, this->total_files),
270272
{ x + PADDING, off }, FONT_SIZE, FONT_SPACING, g_gs.palette.primary);
271273
off += FONT_SIZE * .75 + PADDING / 2;
272274
}

src/Level.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,13 @@ struct Level {
9393
f64 author_time;
9494
Vector2 start_position;
9595
f32 start_angle;
96-
u32 on_unlock_dialog;
96+
u32 on_unlock_dialog = -1;
9797

9898
std::vector<Wall> walls;
9999
std::vector<Zone> zones;
100100
std::vector<Pickup> pickups;
101101

102102
// Non-serialized
103103
bool did_initial_dialog = false;
104+
int collected_files = 0, total_files = 0;
104105
};

src/main.cpp

Lines changed: 92 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <cmath>
2+
#include <algorithm>
23
#include <filesystem>
34
#include <iostream>
45
#include <string>
@@ -31,8 +32,35 @@ void set_level(usize i, bool reset_dialog = false);
3132
static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint);
3233
static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint);
3334

35+
void low_pass_filter_cb(void *buffer, unsigned int frames) {
36+
if (!g_gs.current_dialog) return;
37+
float *samples = (float *)buffer;
38+
static float prevSampleLeft = 0.0f;
39+
static float prevSampleRight = 0.0f;
40+
float alpha = 0.05f;
41+
42+
for (unsigned int i = 0; i < frames * 2; i += 2) {
43+
samples[i] = prevSampleLeft + alpha * (samples[i] - prevSampleLeft);
44+
prevSampleLeft = samples[i];
45+
samples[i + 1] = prevSampleRight + alpha * (samples[i + 1] - prevSampleRight);
46+
prevSampleRight = samples[i + 1];
47+
}
48+
}
49+
50+
float angle_from_center(const Vector2& center, const Vector2& point) {
51+
return atan2(point.y - center.y, point.x - center.x);
52+
}
53+
54+
usize number_of_files_in_directory(std::filesystem::path path)
55+
{
56+
using std::filesystem::directory_iterator;
57+
return std::distance(directory_iterator(path), directory_iterator{});
58+
}
59+
3460
int main(void)
3561
{
62+
SetRandomSeed(time(nullptr));
63+
3664
for (usize i = 0; i < 800; i++) {
3765
g_gs.menu_particles.push_back({
3866
static_cast<float>(GetRandomValue(0, INITIAL_SCREEN_WIDTH)),
@@ -48,11 +76,26 @@ int main(void)
4876
ChangeDirectory(parentPath.string().c_str());
4977
}
5078

51-
SetRandomSeed(time(nullptr));
52-
5379
g_gs.palette = ColorPalette::generate();
54-
for (int i = 0; i < 1; i++) {
55-
g_gs.levels.push_back(Level::read_from_file(TextFormat(RESOURCES_PATH "Level%d.json", i)));
80+
auto const dir_files
81+
= number_of_files_in_directory(RESOURCES_PATH "levels");
82+
for (int i = 0; i < dir_files; i++) {
83+
g_gs.levels.push_back(Level::read_from_file(TextFormat(RESOURCES_PATH "levels/Level%d.json", i)));
84+
85+
for (auto& zone : g_gs.levels[i].zones) {
86+
Vector2 center = { 0, 0 };
87+
for (const auto& point : zone.points) {
88+
center.x += point.x;
89+
center.y += point.y;
90+
}
91+
center.x /= zone.points.size();
92+
center.y /= zone.points.size();
93+
94+
std::sort(zone.points.begin(), zone.points.end(),
95+
[&center](const Vector2& a, const Vector2& b) {
96+
return angle_from_center(center, a) > angle_from_center(center, b);
97+
});
98+
}
5699
}
57100
} catch (std::exception &e) {
58101
std::cout << e.what() << std::endl;
@@ -67,6 +110,17 @@ int main(void)
67110
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_MSAA_4X_HINT);
68111
#endif
69112
InitWindow(INITIAL_SCREEN_WIDTH, INITIAL_SCREEN_HEIGHT, "ByteRacer");
113+
InitAudioDevice();
114+
115+
constexpr auto SONGS = 3;
116+
for (usize i = 0; i < SONGS; i++) {
117+
auto song = LoadMusicStream(TextFormat(RESOURCES_PATH "music_%d.mp3", i));
118+
AttachAudioStreamProcessor(song.stream, low_pass_filter_cb);
119+
g_gs.music.push_back(song);
120+
}
121+
g_gs.current_song = GetRandomValue(0, SONGS-1);
122+
g_gs.explosion = LoadSound(RESOURCES_PATH "explosion.mp3");
123+
PlayMusicStream(g_gs.music[g_gs.current_song]);
70124

71125
g_gs.spritesheet = LoadTexture("resources/spritesheet.png");
72126
g_gs.read_dialogs_from_file("resources/Dialog.json");
@@ -118,6 +172,15 @@ void set_level(usize i, bool reset_dialog)
118172

119173
void produce_frame(void)
120174
{
175+
//if (!IsMusicStreamPlaying(g_gs.music[g_gs.current_song])) {
176+
// StopMusicStream(g_gs.music[g_gs.current_song]);
177+
// g_gs.current_song++;
178+
// g_gs.current_song %= g_gs.music.size();
179+
// SeekMusicStream(g_gs.music[g_gs.current_song], 0);
180+
// PlayMusicStream(g_gs.music[g_gs.current_song]);
181+
//}
182+
UpdateMusicStream(g_gs.music[g_gs.current_song]);
183+
121184
double dt = GetFrameTime();
122185

123186
if (IsKeyPressed(KEY_R)) {
@@ -160,13 +223,13 @@ void produce_frame(void)
160223
} else if (zone.kind == Level::Zone::Kind::End) {
161224
if (!g_gs.completion_time) {
162225
g_gs.completion_time = g_gs.time_spent;
163-
g_gs.collected_files = 0;
164-
g_gs.total_files = 0;
226+
g_gs.level()->collected_files = 0;
227+
g_gs.level()->total_files = 0;
165228
for (auto &pickup : g_gs.level()->pickups) {
166229
if (pickup.kind != Level::Pickup::Kind::File)
167230
continue;
168-
g_gs.total_files++;
169-
g_gs.collected_files += pickup.time_since_pickup != -1;
231+
g_gs.level()->total_files++;
232+
g_gs.level()->collected_files += pickup.time_since_pickup != -1;
170233
}
171234
}
172235
} else if (zone.kind == Level::Zone::Kind::DialogTrigger) {
@@ -191,8 +254,10 @@ void produce_frame(void)
191254

192255
if (g_gs.player.health > PLAYER_MAX_HP)
193256
g_gs.player.health = PLAYER_MAX_HP;
194-
else if (g_gs.player.health < 0)
257+
else if (g_gs.player.health < 0) {
195258
set_level(*g_gs.current_level, false);
259+
PlaySound(g_gs.explosion);
260+
}
196261

197262
g_gs.camera.offset.x = g_gs.widthf / 2.;
198263
g_gs.camera.offset.y = g_gs.heightf / 2.;
@@ -211,8 +276,10 @@ void produce_frame(void)
211276
continue;
212277

213278
if (!level.did_initial_dialog) {
214-
g_gs.show_dialog(level.name, 0);
215-
level.did_initial_dialog = true;
279+
if (level.on_unlock_dialog != -1) {
280+
g_gs.show_dialog(level.name, level.on_unlock_dialog);
281+
level.did_initial_dialog = true;
282+
}
216283
}
217284
}
218285
}
@@ -250,6 +317,11 @@ void produce_frame(void)
250317
float t = 0;
251318
int i = 1;
252319

320+
g_gs.total_collected_files = 0;
321+
for (auto const &level : g_gs.levels) {
322+
g_gs.total_collected_files += level.collected_files;
323+
}
324+
253325
constexpr auto HEIGHT = 60;
254326
constexpr auto BUTTON_SIZE = 50;
255327
constexpr auto PADDING = 20;
@@ -271,7 +343,7 @@ void produce_frame(void)
271343
Vector2 prev;
272344
for (auto const &level : g_gs.levels) {
273345
auto offy = std::sin(t) * HEIGHT;
274-
auto x = PADDING + g_gs.menu_scroll + i * BUTTON_SIZE * 3;
346+
auto x = PADDING + g_gs.menu_scroll + i * BUTTON_SIZE * 5;
275347
auto y = g_gs.heightf / 2 + offy;
276348
Vector2 pos { x, y };
277349

@@ -285,9 +357,10 @@ void produce_frame(void)
285357

286358
bool in = CheckCollisionPointCircle(GetMousePosition(), pos, BUTTON_SIZE);
287359

288-
if (level.files_required) {
360+
bool has_files = g_gs.total_collected_files >= level.files_required;
361+
if (level.files_required && !has_files) {
289362
constexpr auto FILE_ICON_SIZE = 15;
290-
auto txt = TextFormat("%d/%d", 0, level.files_required);
363+
auto txt = TextFormat("%d/%d", g_gs.total_collected_files, level.files_required);
291364
auto sz = MeasureTextEx(g_gs.font, txt, FILE_ICON_SIZE * 2.5, 2);
292365
auto file_pos = pos;
293366
file_pos.y -= BUTTON_SIZE + FILE_ICON_SIZE * 2;
@@ -298,7 +371,7 @@ void produce_frame(void)
298371
DrawTextEx(g_gs.font, txt, file_pos, FILE_ICON_SIZE * 2.5, 2, g_gs.palette.file);
299372
}
300373

301-
if (!level.name.empty()) {
374+
if (!level.name.empty() && has_files) {
302375
constexpr auto TEXT_SIZE = 10;
303376
auto txt = level.name.c_str();
304377
auto sz = MeasureTextEx(g_gs.font, txt, TEXT_SIZE * 2.5, 2);
@@ -310,15 +383,15 @@ void produce_frame(void)
310383

311384
DrawCircleV(pos, BUTTON_SIZE, g_gs.palette.primary);
312385
DrawCircleV(pos, BUTTON_SIZE - BORDER_WIDTH,
313-
in ? g_gs.palette.game_background : g_gs.palette.menu_background);
386+
in && has_files ? g_gs.palette.game_background : g_gs.palette.menu_background);
314387

315388
auto txt = TextFormat("%d", i);
316389
auto w = MeasureTextEx(g_gs.font, txt, FONT_SIZE, 2).x;
317390

318391
DrawTextEx(g_gs.font, txt, { x - w / 2, static_cast<float>(y - FONT_SIZE / 2) },
319392
FONT_SIZE, 2, g_gs.palette.primary);
320393

321-
if (IsMouseButtonPressed(0) && in) {
394+
if (IsMouseButtonPressed(0) && in && has_files) {
322395
set_level(i - 1, true);
323396
}
324397

@@ -374,6 +447,8 @@ void produce_frame(void)
374447
EndDrawing();
375448
}
376449

450+
// Shamelessly stolen from Raylib examples :^)
451+
377452
static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
378453
{
379454
DrawTextBoxedSelectable(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE);

src/resources/Dialog.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,21 @@
3232
"msg": "Grab it. You may need it."
3333
}
3434
]
35+
],
36+
"gateway0.omnitek.co": [
37+
[
38+
{
39+
"name": "Byte",
40+
"msg": "Wait!"
41+
},
42+
{
43+
"name": "Byte",
44+
"msg": "Be careful, once you go in that zone, you will slowly lose power."
45+
},
46+
{
47+
"name": "Byte",
48+
"msg": "If you no longer have any power, you will terminate."
49+
}
50+
]
3551
]
3652
}

0 commit comments

Comments
 (0)