aboutsummaryrefslogtreecommitdiff
path: root/game.c
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-10-05 12:13:47 +1000
committerquou <quou@disroot.org>2024-10-05 12:13:47 +1000
commit0e75a2949678cb8a68fb0819355864aa6db2cb43 (patch)
treeabeb4ecb53649e520e4fcc1652ad870e3d7175fa /game.c
parent6cab1d56ad2b29a2556090f1f0ce7e2b72d5460a (diff)
Level transitions and main menu
Diffstat (limited to 'game.c')
-rw-r--r--game.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/game.c b/game.c
new file mode 100644
index 0000000..07b0264
--- /dev/null
+++ b/game.c
@@ -0,0 +1,172 @@
+#include "animation.h"
+#include "asset.h"
+#include "game.h"
+#include "plat.h"
+#include "render.h"
+
+const Rect logo_rect = { 47, 0, 54, 16 };
+
+void init_game(Game* g, Game_State s) {
+ World* w = &g->w;
+ g->st = s;
+ g->frame = 0;
+ g->want_next = 0;
+ init_world(w);
+}
+
+void update_menu(Game* g, App* a) {
+ int i;
+ for (i = 0; i < btn_count; i++)
+ if (a->btn_states[i] & btn_state_pressed) {
+ queue_gs(g, game_state_fade_out);
+ queue_gs(g, game_state_generate);
+ queue_gs(g, game_state_fade_in);
+ queue_gs(g, game_state_play);
+ g->want_next = 1;
+ return;
+ }
+}
+
+void queue_gs(Game* g, Game_State s) {
+ assert(g->qt < game_max_state_queue);
+ g->sq[g->qt++] = s;
+}
+
+void on_transition(Game* g) {
+ g->ff = 0;
+}
+
+void next_gs(Game* g) {
+ int i, e = --g->qt;
+ g->ps = g->st;
+ g->st = g->sq[0];
+ for (i = 0; i < e; i++)
+ g->sq[i] = g->sq[i + 1];
+ on_transition(g);
+}
+
+void detect_next(Game* g, const World* w) {
+ const Player* p = &w->player;
+ if (p->y < 0) /* next level */ {
+ queue_gs(g, game_state_fade_out);
+ queue_gs(g, game_state_generate);
+ queue_gs(g, game_state_fade_in);
+ queue_gs(g, game_state_play);
+ g->want_next = 1;
+ }
+}
+
+void update_game(Game* g, App* a) {
+ const Animation* fa;
+ if (g->want_next) {
+ next_gs(g);
+ g->want_next = 0;
+ }
+ switch (g->st) {
+ case game_state_menu:
+ update_menu(g, a);
+ break;
+ case game_state_over:
+ break;
+ case game_state_fade_in:
+ fa = get_animation(asset_id_fade_in_anm);
+ if (g->ff < fa->fc * fa->s - 1)
+ update_anim(fa, &g->ff, &g->fr);
+ else
+ g->want_next = 1;
+ break;
+ case game_state_fade_out:
+ fa = get_animation(asset_id_fade_out_anm);
+ if (g->ff < fa->fc * fa->s - 1)
+ update_anim(fa, &g->ff, &g->fr);
+ else
+ g->want_next = 1;
+ break;
+ case game_state_generate:
+ generate_floor(&g->w.map, &g->w);
+ g->want_next = 1;
+ break;
+ case game_state_play:
+ update_world(&g->w, a);
+ detect_next(g, &g->w);
+ break;
+ }
+ g->frame++;
+}
+
+void ren_menu(const Game* g, Renderer* r) {
+ const Bitmap* bm = get_bitmap(asset_id_hud_img);
+ const int hv = viewport_w >> 1;
+ ren_map(
+ r,
+ hv - (logo_rect.w >> 1),
+ 100,
+ &logo_rect,
+ bm
+ );
+ if (g->frame & 3)
+ ren_text(
+ r,
+ hv - 38,
+ 155,
+ "ANY BUTTON TO START"
+ );
+ ren_text(
+ r,
+ hv - 24,
+ 200,
+ "made by quou"
+ );
+ ren_text(
+ r,
+ hv - 44,
+ 205,
+ "public domain software"
+ );
+ ren_text(
+ r,
+ hv - 16,
+ 210,
+ "quou.xyz"
+ );
+}
+
+void ren_state(const Game* g, Game_State s, Renderer* r) {
+ switch (s) {
+ case game_state_menu:
+ ren_menu(g, r);
+ break;
+ case game_state_over:
+ break;
+ case game_state_generate:
+ break;
+ case game_state_play:
+ ren_world(&g->w, r);
+ break;
+ default: break;
+ }
+}
+
+void ren_fade(const Game* g, Renderer* r) {
+ const Bitmap* bm = get_bitmap(asset_id_hud_img);
+ const Rect* re = &g->fr;
+ int x, y;
+ for (y = 0; y < viewport_h; y += re->h)
+ for (x = 0; x < viewport_w; x += re->w)
+ ren_cmap(r, x, y, re, bm);
+}
+
+void ren_game(const Game* g, Renderer* r) {
+ switch (g->st) {
+ case game_state_fade_in:
+ ren_state(g, g->sq[1], r);
+ ren_fade(g, r);
+ break;
+ case game_state_fade_out:
+ ren_state(g, g->ps, r);
+ ren_fade(g, r);
+ break;
+ default:
+ ren_state(g, g->st, r);
+ }
+}