aboutsummaryrefslogtreecommitdiff
path: root/game.c
blob: 07b0264769bba7525a55a4e6d70afd424f3ce7cd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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);
	}
}