Import from neverball-1.1.3.tar.gz
[neverball-archive.git] / state.c
blob8aac42c10b8954812b2dad5333bb642525d7fc1b
1 /*
2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
15 #include <SDL.h>
16 #include <SDL_ttf.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <math.h>
21 #include "glext.h"
22 #include "hud.h"
23 #include "game.h"
24 #include "back.h"
25 #include "menu.h"
26 #include "text.h"
27 #include "solid.h"
28 #include "state.h"
29 #include "level.h"
30 #include "set.h"
31 #include "image.h"
32 #include "audio.h"
33 #include "config.h"
35 FILE *record_fp;
36 FILE *replay_fp;
38 static double global_time;
39 static double replay_time;
41 /*---------------------------------------------------------------------------*/
43 static double state_time = 0.0;
44 static struct state *state = NULL;
46 void init_state(void)
48 state = &st_title;
50 if (state->enter)
51 state->enter();
54 double time_state(void)
56 return state_time;
59 int goto_state(struct state *st)
61 if (state && state->leave)
62 state->leave();
64 state = st;
65 state_time = 0;
67 if (state && state->enter)
68 state->enter();
70 return 1;
73 /*---------------------------------------------------------------------------*/
75 void st_paint(void)
77 if (state && state->paint)
79 if (config_stereo())
81 glDrawBuffer(GL_BACK_LEFT);
82 state->paint(+config_stereo());
84 glDrawBuffer(GL_BACK_RIGHT);
85 state->paint(-config_stereo());
87 else
88 state->paint(0);
92 int st_timer(double t)
94 state_time += t;
95 return (state && state->timer) ? state->timer(t) : 1;
98 int st_point(int x, int y, int dx, int dy)
100 return (state && state->point) ? state->point(x, y, dx, dy) : 1;
103 int st_click(int b, int d)
105 return (state && state->click) ? state->click(b, d) : 1;
108 int st_keybd(int c)
110 return (state && state->keybd) ? state->keybd(c) : 1;
113 int st_stick(int a, int k)
115 return (state && state->stick) ? state->stick(a, k) : 1;
118 int st_buttn(int b, int d)
120 return (state && state->buttn) ? state->buttn(b, d) : 1;
123 /*---------------------------------------------------------------------------*/
125 #define TITLE_PLAY 1
126 #define TITLE_HELP 2
127 #define TITLE_DEMO 3
128 #define TITLE_CONF 4
129 #define TITLE_EXIT 5
131 #define STR_TITLE " Neverball "
132 #define STR_PLAY " Play "
133 #define STR_HELP " Help "
134 #define STR_DEMO " Demo "
135 #define STR_CONF " Options "
136 #define STR_EXIT " Exit "
138 static int title_action(int i)
140 switch (i)
142 case TITLE_PLAY: audio_play(AUD_MENU, 1.f); goto_state(&st_set); break;
143 case TITLE_HELP: audio_play(AUD_MENU, 1.f); goto_state(&st_help); break;
144 case TITLE_DEMO: audio_play(AUD_MENU, 1.f); goto_state(&st_demo); break;
145 case TITLE_CONF: audio_play(AUD_MENU, 1.f); goto_state(&st_conf); break;
146 case TITLE_EXIT: return 0;
148 return 1;
151 static void title_enter(void)
153 int lw, lh, lm;
154 int mw, mh;
156 text_size(STR_TITLE, TXT_LRG, &lw, &lh);
157 text_size(STR_CONF, TXT_MED, &mw, &mh);
159 lm = lh / 2;
161 menu_init(6, 6, TITLE_PLAY);
163 menu_text(0, 0, lm + 2 * mh, c_yellow, c_red, STR_TITLE, TXT_LRG);
164 menu_text(TITLE_PLAY, 0, +1 * mh, c_white, c_white, STR_PLAY, TXT_MED);
165 menu_text(TITLE_HELP, 0, 0 * mh, c_white, c_white, STR_HELP, TXT_MED);
166 menu_text(TITLE_DEMO, 0, -1 * mh, c_white, c_white, STR_DEMO, TXT_MED);
167 menu_text(TITLE_CONF, 0, -2 * mh, c_white, c_white, STR_CONF, TXT_MED);
168 menu_text(TITLE_EXIT, 0, -3 * mh, c_white, c_white, STR_EXIT, TXT_MED);
170 menu_item(0, 0, lm + 2 * mh, lw, lh);
171 menu_item(TITLE_PLAY, 0, +1 * mh, mw, mh);
172 menu_item(TITLE_HELP, 0, 0 * mh, mw, mh);
173 menu_item(TITLE_DEMO, 0, -1 * mh, mw, mh);
174 menu_item(TITLE_CONF, 0, -2 * mh, mw, mh);
175 menu_item(TITLE_EXIT, 0, -3 * mh, mw, mh);
177 menu_link(TITLE_PLAY, -1, TITLE_HELP, -1, -1);
178 menu_link(TITLE_HELP, TITLE_PLAY, TITLE_DEMO, -1, -1);
179 menu_link(TITLE_DEMO, TITLE_HELP, TITLE_CONF, -1, -1);
180 menu_link(TITLE_CONF, TITLE_DEMO, TITLE_EXIT, -1, -1);
181 menu_link(TITLE_EXIT, TITLE_CONF, -1, -1, -1);
183 menu_stat(0, -1);
184 menu_stat(TITLE_PLAY, +1);
185 menu_stat(TITLE_HELP, 0);
186 menu_stat(TITLE_DEMO, config_demo() ? 0 : -1);
187 menu_stat(TITLE_CONF, 0);
188 menu_stat(TITLE_EXIT, 0);
190 set_init();
191 set_goto(0);
192 level_goto(0, 0, 0, 0);
194 audio_music_play("bgm/title.ogg");
196 SDL_ShowCursor(SDL_ENABLE);
199 static void title_leave(void)
201 SDL_ShowCursor(SDL_DISABLE);
203 set_free();
204 menu_free();
205 audio_music_play("bgm/inter.ogg");
208 static void title_paint(double dy)
210 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
211 game_draw(0, dy);
212 menu_paint();
215 static int title_timer(double dt)
217 game_set_fly(cos(time_state() / 10.0));
218 return 1;
221 static int title_point(int x, int y, int dx, int dy)
223 menu_point(x, y);
224 return 1;
227 static int title_click(int b, int d)
229 return (b < 0 && d == 1) ? title_action(menu_click()) : 1;
232 static int title_keybd(int c)
234 return (c == SDLK_ESCAPE) ? 0 : 1;
237 static int title_stick(int a, int v)
239 menu_stick(a, v);
240 return 1;
243 static int title_buttn(int b, int d)
245 if (config_button_a(b) && d == 1) return title_action(menu_buttn());
246 if (config_button_X(b) && d == 1) return 0;
247 return 1;
250 /*---------------------------------------------------------------------------*/
252 static void help_enter(void)
254 const GLfloat *c0 = c_white;
255 const GLfloat *c1 = c_yellow;
256 int w, h;
258 text_size("X", TXT_SML, &w, &h);
259 w = config_w();
261 menu_init(15, 1, -1);
262 back_init("png/blues.png", config_geom());
264 menu_item(0, 0, 0, 7 * w / 8, h * 14);
266 menu_text(0, 0, +6 * h, c0, c0,
267 "Move the mouse or joystick to tilt the floor,", TXT_SML);
268 menu_text(1, 0, +5 * h, c0, c0,
269 "causing the ball to roll. Guide it to the goal", TXT_SML);
270 menu_text(2, 0, +4 * h, c0, c0,
271 "to finish the level. Collect 100 coins to earn", TXT_SML);
272 menu_text(3, 0, +3 * h, c0, c0,
273 "an extra ball and save your progress.", TXT_SML);
275 menu_text(4, -w / 4, +1 * h, c1, c1, "Spacebar", TXT_SML);
276 menu_text(5, -w / 4, 0 * h, c1, c1, "Escape", TXT_SML);
277 menu_text(6, -w / 4, -2 * h, c1, c1, "F1", TXT_SML);
278 menu_text(7, -w / 4, -3 * h, c1, c1, "F2", TXT_SML);
279 menu_text(8, -w / 4, -4 * h, c1, c1, "F3", TXT_SML);
281 menu_text(9, w / 8, +1 * h, c0, c0, "Pause / Release Pointer", TXT_SML);
282 menu_text(10, w / 8, 0 * h, c0, c0, "Exit / Cancel Menu", TXT_SML);
283 menu_text(11, w / 8, -2 * h, c0, c0, "Chase View", TXT_SML);
284 menu_text(12, w / 8, -3 * h, c0, c0, "Lazy View", TXT_SML);
285 menu_text(13, w / 8, -4 * h, c0, c0, "Manual View", TXT_SML);
287 menu_text(14, 0, -6 * h, c0, c0,
288 "Left and right mouse buttons rotate the view.", TXT_SML);
290 SDL_ShowCursor(SDL_ENABLE);
293 static void help_leave(void)
295 SDL_ShowCursor(SDL_DISABLE);
296 menu_free();
297 back_free();
300 static void help_paint(double dy)
302 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
304 config_push_persp(FOV, 0.1, 300.0);
306 back_draw(time_state());
308 config_pop_matrix();
310 menu_paint();
313 static int help_click(int b, int d)
315 return d ? goto_state(&st_title) : 1;
318 static int help_keybd(int c)
320 return goto_state(&st_title);
323 static int help_buttn(int b, int d)
325 return goto_state(&st_title);
328 /*---------------------------------------------------------------------------*/
330 #define CONF_FULL 0
331 #define CONF_WIN 1
332 #define CONF_16x12 2
333 #define CONF_12x10 3
334 #define CONF_10x7 4
335 #define CONF_8x6 5
336 #define CONF_6x4 6
337 #define CONF_TEXHI 7
338 #define CONF_TEXLO 8
339 #define CONF_GEOHI 9
340 #define CONF_GEOLO 10
341 #define CONF_AUDHI 11
342 #define CONF_AUDLO 12
343 #define CONF_SNDDN 13
344 #define CONF_SNDUP 14
345 #define CONF_MUSDN 15
346 #define CONF_MUSUP 16
347 #define CONF_BACK 17
349 static int conf_action(int i)
351 int w, h, w2, s = 1;
352 char str[8];
354 text_size("MMMMMMMMM", TXT_SML, &w, &h);
355 w2 = w / 2;
357 switch (i)
359 case CONF_FULL:
360 goto_state(&st_null);
361 s = config_set_mode(config_w(), config_h(), SDL_OPENGL|SDL_FULLSCREEN);
362 goto_state(&st_conf);
363 break;
365 case CONF_WIN:
366 goto_state(&st_null);
367 s = config_set_mode(config_w(), config_h(), SDL_OPENGL);
368 goto_state(&st_conf);
369 break;
371 case CONF_16x12:
372 goto_state(&st_null);
373 s = config_set_mode(1600, 1200, config_mode());
374 goto_state(&st_conf);
375 break;
377 case CONF_12x10:
378 goto_state(&st_null);
379 s = config_set_mode(1280, 1024, config_mode());
380 goto_state(&st_conf);
381 break;
383 case CONF_10x7:
384 goto_state(&st_null);
385 s = config_set_mode(1024, 768, config_mode());
386 goto_state(&st_conf);
387 break;
389 case CONF_8x6:
390 goto_state(&st_null);
391 s = config_set_mode(800, 600, config_mode());
392 goto_state(&st_conf);
393 break;
395 case CONF_6x4:
396 goto_state(&st_null);
397 s = config_set_mode(640, 480, config_mode());
398 goto_state(&st_conf);
399 break;
401 case CONF_TEXHI:
402 goto_state(&st_null);
403 config_set_text(1);
404 goto_state(&st_conf);
405 break;
407 case CONF_TEXLO:
408 goto_state(&st_null);
409 config_set_text(2);
410 goto_state(&st_conf);
411 break;
413 case CONF_GEOHI:
414 goto_state(&st_null);
415 config_set_geom(1);
416 goto_state(&st_conf);
417 break;
419 case CONF_GEOLO:
420 goto_state(&st_null);
421 config_set_geom(0);
422 goto_state(&st_conf);
423 break;
425 case CONF_AUDHI:
426 s = config_set_audio(44100, AUD_BUFF_HI);
427 goto_state(&st_conf);
428 break;
430 case CONF_AUDLO:
431 s = config_set_audio(22050, AUD_BUFF_LO);
432 goto_state(&st_conf);
433 break;
435 case CONF_SNDDN:
436 config_set_sound(config_sound() - 1);
437 sprintf(str, "%02d", config_sound());
439 menu_text(33, +w2, -3 * h, c_yellow, c_red, str, TXT_SML);
440 audio_play(AUD_BUMP, 1.f);
441 break;
443 case CONF_SNDUP:
444 config_set_sound(config_sound() + 1);
445 sprintf(str, "%02d", config_sound());
447 menu_text(33, +w2, -3 * h, c_yellow, c_red, str, TXT_SML);
448 audio_play(AUD_BUMP, 1.f);
449 break;
451 case CONF_MUSDN:
452 config_set_music(config_music() - 1);
453 sprintf(str, "%02d", config_music());
455 menu_text(34, +w2, -4 * h, c_yellow, c_red, str, TXT_SML);
456 break;
458 case CONF_MUSUP:
459 config_set_music(config_music() + 1);
460 sprintf(str, "%02d", config_music());
462 menu_text(34, +w2, -4 * h, c_yellow, c_red, str, TXT_SML);
463 break;
465 case CONF_BACK:
466 goto_state(&st_title);
467 break;
469 return s;
472 static void conf_enter(void)
474 static int value = CONF_FULL;
475 char snds[16];
476 char muss[16];
478 int w, w2, w4;
479 int h, h2;
481 /* Compute menu sizes from font sizes */
483 text_size("MMMMMMMMM", TXT_SML, &w, &h);
484 w2 = w / 2;
485 w4 = w / 4;
486 h2 = h / 2;
488 sprintf(snds, "%02d", config_sound());
489 sprintf(muss, "%02d", config_music());
491 menu_init(36, 25, value);
492 back_init("png/blues.png", config_geom());
494 /* Text elements */
496 menu_text(0, -w2, +h2 + 4 * h, c_yellow, c_red, "Options", TXT_MED);
497 menu_text(1, -w2, +3 * h, c_white, c_white, "Fullscreen", TXT_SML);
498 menu_text(2, -w2, +2 * h, c_white, c_white, "Window", TXT_SML);
499 menu_text(3, +w2 - w4, +5 * h, c_white, c_white, "1600", TXT_SML);
500 menu_text(4, +w2 - w4, +4 * h, c_white, c_white, "1280", TXT_SML);
501 menu_text(5, +w2 - w4, +3 * h, c_white, c_white, "1024", TXT_SML);
502 menu_text(6, +w2 - w4, +2 * h, c_white, c_white, "800", TXT_SML);
503 menu_text(7, +w2 - w4, 1 * h, c_white, c_white, "640", TXT_SML);
504 menu_text(8, +w2, +5 * h, c_white, c_white, "x", TXT_SML);
505 menu_text(9, +w2, +4 * h, c_white, c_white, "x", TXT_SML);
506 menu_text(10, +w2, +3 * h, c_white, c_white, "x", TXT_SML);
507 menu_text(11, +w2, +2 * h, c_white, c_white, "x", TXT_SML);
508 menu_text(12, +w2, 1 * h, c_white, c_white, "x", TXT_SML);
509 menu_text(13, +w2 + w4, +5 * h, c_white, c_white, "1200", TXT_SML);
510 menu_text(14, +w2 + w4, +4 * h, c_white, c_white, "1024", TXT_SML);
511 menu_text(15, +w2 + w4, +3 * h, c_white, c_white, "768", TXT_SML);
512 menu_text(16, +w2 + w4, +2 * h, c_white, c_white, "600", TXT_SML);
513 menu_text(17, +w2 + w4, 1 * h, c_white, c_white, "480", TXT_SML);
514 menu_text(18, -w2, 0 * h, c_yellow, c_red, "Textures", TXT_SML);
515 menu_text(19, -w2, -1 * h, c_yellow, c_red, "Geometry", TXT_SML);
516 menu_text(20, -w2, -2 * h, c_yellow, c_red, "Audio", TXT_SML);
517 menu_text(21, -w2, -3 * h, c_yellow, c_red, "Sound Vol", TXT_SML);
518 menu_text(22, -w2, -4 * h, c_yellow, c_red, "Music Vol", TXT_SML);
519 menu_text(23, +w2 - w4, 0 * h, c_white, c_white, "High", TXT_SML);
520 menu_text(24, +w2 - w4, -1 * h, c_white, c_white, "High", TXT_SML);
521 menu_text(25, +w2 - w4, -2 * h, c_white, c_white, "High", TXT_SML);
522 menu_text(26, +w2 - w4, -3 * h, c_white, c_white, "<", TXT_SML);
523 menu_text(27, +w2 - w4, -4 * h, c_white, c_white, "<", TXT_SML);
524 menu_text(28, +w2 + w4, 0 * h, c_white, c_white, "Low", TXT_SML);
525 menu_text(29, +w2 + w4, -1 * h, c_white, c_white, "Low", TXT_SML);
526 menu_text(30, +w2 + w4, -2 * h, c_white, c_white, "Low", TXT_SML);
527 menu_text(31, +w2 + w4, -3 * h, c_white, c_white, ">", TXT_SML);
528 menu_text(32, +w2 + w4, -4 * h, c_white, c_white, ">", TXT_SML);
529 menu_text(33, +w2, -3 * h, c_yellow, c_red, snds, TXT_SML);
530 menu_text(34, +w2, -4 * h, c_yellow, c_red, muss, TXT_SML);
531 menu_text(35, +w2, -5 * h, c_white, c_white, "Back", TXT_SML);
533 /* Active items */
535 menu_item(CONF_FULL, -w2, +3 * h, w, h);
536 menu_item(CONF_WIN, -w2, +2 * h, w, h);
537 menu_item(CONF_16x12, +w2, +5 * h, w, h);
538 menu_item(CONF_12x10, +w2, +4 * h, w, h);
539 menu_item(CONF_10x7, +w2, +3 * h, w, h);
540 menu_item(CONF_8x6, +w2, +2 * h, w, h);
541 menu_item(CONF_6x4, +w2, +1 * h, w, h);
542 menu_item(CONF_TEXHI, +w2 - w4, 0 * h, w2, h);
543 menu_item(CONF_TEXLO, +w2 + w4, 0 * h, w2, h);
544 menu_item(CONF_GEOHI, +w2 - w4, -1 * h, w2, h);
545 menu_item(CONF_GEOLO, +w2 + w4, -1 * h, w2, h);
546 menu_item(CONF_AUDHI, +w2 - w4, -2 * h, w2, h);
547 menu_item(CONF_AUDLO, +w2 + w4, -2 * h, w2, h);
548 menu_item(CONF_SNDDN, +w2 - w4, -3 * h, w2, h);
549 menu_item(CONF_SNDUP, +w2 + w4, -3 * h, w2, h);
550 menu_item(CONF_MUSDN, +w2 - w4, -4 * h, w2, h);
551 menu_item(CONF_MUSUP, +w2 + w4, -4 * h, w2, h);
552 menu_item(CONF_BACK, +w2, -5 * h, w, h);
554 /* Inactive label padding */
556 menu_item(18, -w2, +5 * h, w, h);
557 menu_item(19, -w2, +4 * h, w, h);
558 menu_item(20, -w2, 0 * h, w, h);
559 menu_item(21, -w2, -1 * h, w, h);
560 menu_item(22, -w2, -2 * h, w, h);
561 menu_item(23, -w2, -3 * h, w, h);
562 menu_item(24, -w2, -4 * h, w, h);
564 /* Item state */
566 menu_stat(CONF_FULL, (config_mode() & SDL_FULLSCREEN) ? 1 : 0);
567 menu_stat(CONF_WIN, (config_mode() & SDL_FULLSCREEN) ? 0 : 1);
568 menu_stat(CONF_16x12, (config_w() == 1600) ? 1 : 0);
569 menu_stat(CONF_12x10, (config_w() == 1280) ? 1 : 0);
570 menu_stat(CONF_10x7, (config_w() == 1024) ? 1 : 0);
571 menu_stat(CONF_8x6, (config_w() == 800) ? 1 : 0);
572 menu_stat(CONF_6x4, (config_w() == 640) ? 1 : 0);
573 menu_stat(CONF_TEXHI, (config_text() == 1) ? 1 : 0);
574 menu_stat(CONF_TEXLO, (config_text() == 2) ? 1 : 0);
575 menu_stat(CONF_GEOHI, (config_geom() == 1) ? 1 : 0);
576 menu_stat(CONF_GEOLO, (config_geom() == 0) ? 1 : 0);
577 menu_stat(CONF_AUDHI, (config_rate() == 44100) ? 1 : 0);
578 menu_stat(CONF_AUDLO, (config_rate() == 22050) ? 1 : 0);
579 menu_stat(CONF_SNDDN, 0);
580 menu_stat(CONF_SNDUP, 0);
581 menu_stat(CONF_MUSDN, 0);
582 menu_stat(CONF_MUSUP, 0);
583 menu_stat(CONF_BACK, 0);
585 /* Item linkings for menu traversal */
587 menu_link(CONF_FULL, CONF_FULL, CONF_WIN, CONF_FULL, CONF_10x7);
588 menu_link(CONF_WIN, CONF_FULL, CONF_WIN, CONF_WIN, CONF_8x6);
589 menu_link(CONF_16x12, CONF_16x12, CONF_12x10, CONF_16x12, CONF_16x12);
590 menu_link(CONF_12x10, CONF_16x12, CONF_10x7, CONF_12x10, CONF_12x10);
591 menu_link(CONF_10x7, CONF_12x10, CONF_8x6, CONF_FULL, CONF_10x7);
592 menu_link(CONF_8x6, CONF_10x7, CONF_6x4, CONF_WIN, CONF_8x6);
593 menu_link(CONF_6x4, CONF_8x6, CONF_TEXHI, CONF_6x4, CONF_6x4);
594 menu_link(CONF_TEXHI, CONF_6x4, CONF_GEOHI, CONF_TEXHI, CONF_TEXLO);
595 menu_link(CONF_TEXLO, CONF_6x4, CONF_GEOLO, CONF_TEXHI, CONF_TEXLO);
596 menu_link(CONF_GEOHI, CONF_TEXHI, CONF_AUDHI, CONF_GEOHI, CONF_GEOLO);
597 menu_link(CONF_GEOLO, CONF_TEXLO, CONF_AUDLO, CONF_GEOHI, CONF_GEOLO);
598 menu_link(CONF_AUDHI, CONF_GEOHI, CONF_SNDDN, CONF_AUDHI, CONF_AUDLO);
599 menu_link(CONF_AUDLO, CONF_GEOLO, CONF_SNDUP, CONF_AUDHI, CONF_AUDLO);
600 menu_link(CONF_SNDDN, CONF_AUDHI, CONF_MUSDN, CONF_SNDDN, CONF_SNDUP);
601 menu_link(CONF_SNDUP, CONF_AUDLO, CONF_MUSUP, CONF_SNDDN, CONF_SNDUP);
602 menu_link(CONF_MUSDN, CONF_SNDDN, CONF_BACK, CONF_MUSDN, CONF_MUSUP);
603 menu_link(CONF_MUSUP, CONF_SNDUP, CONF_BACK, CONF_MUSDN, CONF_MUSUP);
604 menu_link(CONF_BACK, CONF_MUSDN, CONF_BACK, CONF_BACK, CONF_BACK);
606 value = -1;
608 SDL_ShowCursor(SDL_ENABLE);
611 static void conf_leave(void)
613 SDL_ShowCursor(SDL_DISABLE);
615 config_store();
616 menu_free();
617 back_free();
620 static void conf_paint(double dy)
622 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
624 config_push_persp(FOV, 0.1, 300.0);
626 back_draw(time_state());
628 config_pop_matrix();
630 menu_paint();
633 static int conf_point(int x, int y, int dx, int dy)
635 menu_point(x, y);
636 return 1;
639 static int conf_click(int b, int d)
641 return (b < 0 && d == 1) ? conf_action(menu_click()) : 1;
644 static int conf_keybd(int c)
646 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
649 static int conf_stick(int a, int v)
651 menu_stick(a, v);
652 return 1;
655 static int conf_buttn(int b, int d)
657 if (config_button_a(b) && d == 1) return conf_action(menu_buttn());
658 if (config_button_b(b) && d == 1) return goto_state(&st_title);
659 if (config_button_X(b) && d == 1) return goto_state(&st_title);
660 return 1;
663 /*---------------------------------------------------------------------------*/
665 static GLuint shot_rect = 0;
666 static int shot_set = 0;
668 static int set_action(int i)
670 if (i >= 0)
672 if (i == 0)
674 back_free();
675 return goto_state(&st_title);
677 if (2 <= i && i <= 6)
679 back_free();
680 set_goto(i - 2);
681 return goto_state(&st_start);
684 return 1;
687 static void set_describe(int i)
689 int w, h, j, y, m = 7;
691 char buf[STRMAX];
692 const char *p = set_desc(i);
694 text_size("0", TXT_SML, &w, &h);
695 y = -2 * h;
696 h = 3 * h / 2;
698 while (p && m < 12)
700 memset(buf, 0, 256);
701 j = 0;
703 while (p && *p && *p != '\\')
704 buf[j++] = *p++;
706 if (j > 0) menu_text(m, 0, y, c_yellow, c_white, buf, TXT_SML);
708 menu_item(m, 0, y, h * 15, h);
709 menu_stat(m, -1);
711 y -= h;
712 m++;
714 if (*p) p++;
718 static void set_enter(void)
720 int w;
721 int h;
722 int j;
724 audio_play(AUD_START, 1.f);
726 shot_set = 0;
728 text_size("0", TXT_SML, &w, &h);
729 j = h / 2;
731 set_init();
732 menu_init(12, 12, 0);
733 back_init("png/blues.png", config_geom());
735 /* Text elements */
737 menu_text(0, -8 * h, 16 * j, c_white, c_white, "Back", TXT_SML);
738 menu_text(1, +7 * h, 16 * j, c_yellow, c_red, "Level Set", TXT_SML);
739 menu_text(2, -5 * h, 13 * j, c_white, c_white, set_name(0), TXT_SML);
740 menu_text(3, -5 * h, 10 * j, c_white, c_white, set_name(1), TXT_SML);
741 menu_text(4, -5 * h, 7 * j, c_white, c_white, set_name(2), TXT_SML);
742 menu_text(5, -5 * h, 4 * j, c_white, c_white, set_name(3), TXT_SML);
743 menu_text(6, -5 * h, j, c_white, c_white, set_name(4), TXT_SML);
745 /* Active items */
747 menu_item(0, -8 * h, 16 * j, 4 * h, 3 * j);
748 menu_item(1, +7 * h, 16 * j, 6 * h, 3 * j);
749 menu_item(2, -5 * h, 13 * j, 10 * h, 3 * j);
750 menu_item(3, -5 * h, 10 * j, 10 * h, 3 * j);
751 menu_item(4, -5 * h, 7 * j, 10 * h, 3 * j);
752 menu_item(5, -5 * h, 4 * j, 10 * h, 3 * j);
753 menu_item(6, -5 * h, j, 10 * h, 3 * j);
755 /* Item state */
757 menu_stat(0, 0);
758 menu_stat(1, 0);
759 menu_stat(2, set_exists(0) ? 0 : -1);
760 menu_stat(3, set_exists(1) ? 0 : -1);
761 menu_stat(4, set_exists(2) ? 0 : -1);
762 menu_stat(5, set_exists(3) ? 0 : -1);
763 menu_stat(6, set_exists(4) ? 0 : -1);
765 /* Item linkings */
767 menu_link(0, -1, set_exists(0) ? 2 : -1, -1, -1);
768 menu_link(2, 0, set_exists(1) ? 3 : -1, -1, -1);
769 menu_link(3, set_exists(0) ? 2 : -1, set_exists(2) ? 4 : -1, -1, -1);
770 menu_link(4, set_exists(1) ? 3 : -1, set_exists(3) ? 5 : -1, -1, -1);
771 menu_link(5, set_exists(2) ? 4 : -1, set_exists(4) ? 6 : -1, -1, -1);
772 menu_link(6, set_exists(3) ? 5 : -1, -1, -1, -1);
774 set_describe(0);
776 /* Position the set shot. */
778 shot_rect = make_rect(config_w() / 2,
779 config_h() / 2 - j / 2,
780 config_w() / 2 + 10 * h,
781 config_h() / 2 + 29 * j / 2);
783 SDL_ShowCursor(SDL_ENABLE);
786 static void set_leave(void)
788 if (glIsList(shot_rect))
789 glDeleteLists(shot_rect, 1);
791 SDL_ShowCursor(SDL_DISABLE);
792 menu_free();
795 static void set_paint(double dy)
797 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
799 config_push_persp(FOV, 0.1, 300.0);
801 back_draw(time_state());
803 config_pop_matrix();
805 glPushAttrib(GL_LIGHTING_BIT);
806 glPushAttrib(GL_DEPTH_BUFFER_BIT);
807 config_push_ortho();
809 glEnable(GL_COLOR_MATERIAL);
810 glDisable(GL_LIGHTING);
811 glDisable(GL_DEPTH_TEST);
813 set_shot(shot_set);
814 glCallList(shot_rect);
816 config_pop_matrix();
817 glPopAttrib();
818 glPopAttrib();
820 menu_paint();
823 static int set_point(int x, int y, int dx, int dy)
825 int i;
827 if ((i = menu_point(x, y)) >= 0 && shot_set != i - 2)
829 shot_set = i - 2;
830 set_describe(shot_set);
833 return 1;
836 static int set_click(int b, int d)
838 return (b < 0 && d == 1) ? set_action(menu_click()) : 1;
841 static int set_keybd(int c)
843 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
846 static int set_stick(int a, int v)
848 menu_stick(a, v);
849 return 1;
852 static int set_buttn(int b, int d)
854 if (config_button_a(b) && d == 1) return set_action(menu_buttn());
855 if (config_button_b(b) && d == 1) return goto_state(&st_title);
856 if (config_button_X(b) && d == 1) return goto_state(&st_title);
857 return 1;
860 /*---------------------------------------------------------------------------*/
862 static void score_menu(int i, int j, int k)
864 const GLfloat *c0 = c_yellow;
865 const GLfloat *c1 = c_white;
866 int w, h;
868 text_size("0", TXT_SML, &w, &h);
870 menu_text(j, -7 * h, 0, c1, c1, "Time:", TXT_SML);
871 menu_text(j + 1, +7 * h, 0, c1, c1, "Coins:", TXT_SML);
873 menu_text(j + 2, -2 * h, 0, c0, c1, level_time_s(i, -1), TXT_SML);
874 menu_text(j + 3, +11 * h, 0, c0, c1, level_coin_c(i, -1), TXT_SML);
876 menu_item(k, -6 * h, 0, 12 * h - 4, 3 * h / 2);
877 menu_item(k + 1, +6 * h, 0, 12 * h - 4, 3 * h / 2);
880 static void highs_menu(int i, int j, int k)
882 const GLfloat *c0 = c_yellow;
883 const GLfloat *c1 = c_white;
884 const GLfloat *c2 = c_red;
885 int w, h;
887 text_size("0", TXT_SML, &w, &h);
889 menu_text(j, -6*h, -9*h/4, c0, c2, "Best Times", TXT_SML);
890 menu_text(j + 1, +6*h, -9*h/4, c0, c2, "Most Coins", TXT_SML);
892 menu_text(j + 2, -21*h/2, -15*h/4, c0, c1, level_time_c(i,0), TXT_SML);
893 menu_text(j + 3, -14*h/2, -15*h/4, c0, c1, level_time_n(i,0), TXT_SML);
894 menu_text(j + 4, -5*h/2, -15*h/4, c0, c1, level_time_s(i,0), TXT_SML);
896 menu_text(j + 5, -21*h/2, -21*h/4, c0, c1, level_time_c(i,1), TXT_SML);
897 menu_text(j + 6, -14*h/2, -21*h/4, c0, c1, level_time_n(i,1), TXT_SML);
898 menu_text(j + 7, -5*h/2, -21*h/4, c0, c1, level_time_s(i,1), TXT_SML);
900 menu_text(j + 8, -21*h/2, -27*h/4, c0, c1, level_time_c(i,2), TXT_SML);
901 menu_text(j + 9, -14*h/2, -27*h/4, c0, c1, level_time_n(i,2), TXT_SML);
902 menu_text(j + 10, -5*h/2, -27*h/4, c0, c1, level_time_s(i,2), TXT_SML);
905 menu_text(j + 11, +5*h/2, -15*h/4, c0, c1, level_coin_s(i,0), TXT_SML);
906 menu_text(j + 12, +14*h/2, -15*h/4, c0, c1, level_coin_n(i,0), TXT_SML);
907 menu_text(j + 13, +21*h/2, -15*h/4, c0, c1, level_coin_c(i,0), TXT_SML);
909 menu_text(j + 14, +5*h/2, -21*h/4, c0, c1, level_coin_s(i,1), TXT_SML);
910 menu_text(j + 15, +14*h/2, -21*h/4, c0, c1, level_coin_n(i,1), TXT_SML);
911 menu_text(j + 16, +21*h/2, -21*h/4, c0, c1, level_coin_c(i,1), TXT_SML);
913 menu_text(j + 17, +5*h/2, -27*h/4, c0, c1, level_coin_s(i,2), TXT_SML);
914 menu_text(j + 18, +14*h/2, -27*h/4, c0, c1, level_coin_n(i,2), TXT_SML);
915 menu_text(j + 19, +21*h/2, -27*h/4, c0, c1, level_coin_c(i,2), TXT_SML);
917 menu_item(k, -6*h, -18*h/4, 12 * h - 4, 12 * h / 2);
918 menu_item(k + 1, +6*h, -18*h/4, 12 * h - 4, 12 * h / 2);
921 /*---------------------------------------------------------------------------*/
923 #define START_BACK 0
925 static int shot_level = -1;
927 static int start_action(int i)
929 if (i >= 0)
931 if (i == START_BACK)
933 back_free();
934 return goto_state(&st_set);
936 else
938 back_free();
939 level_goto(0, 0, 2, i);
940 return goto_state(&st_level);
943 return 1;
946 #define COL0(i) (level_exists(i) \
947 ? ((level_opened(i) ? c_white : c_yellow)) : c_black)
948 #define COL1(i) (level_exists(i) \
949 ? ((level_opened(i) ? c_white : c_red)) : c_black)
950 #define OPN(i) (level_opened(i) ? i : -1)
952 static void start_enter(void)
954 int i;
955 int w;
956 int h;
957 int j;
959 shot_level = 0;
961 text_size("0", TXT_SML, &w, &h);
962 j = h / 2;
964 menu_init(47, 29, 0);
965 back_init("png/blues.png", config_geom());
967 /* Text elements */
969 menu_text(0, -8 * h, 16 * j, c_white, c_white, "Set", TXT_SML);
970 menu_text(1, -9 * h, 13 * j, COL0( 1), COL1( 1), "01", TXT_SML);
971 menu_text(2, -7 * h, 13 * j, COL0( 2), COL1( 2), "02", TXT_SML);
972 menu_text(3, -5 * h, 13 * j, COL0( 3), COL1( 3), "03", TXT_SML);
973 menu_text(4, -3 * h, 13 * j, COL0( 4), COL1( 4), "04", TXT_SML);
974 menu_text(5, -1 * h, 13 * j, COL0( 5), COL1( 5), "05", TXT_SML);
975 menu_text(6, -9 * h, 10 * j, COL0( 6), COL1( 6), "06", TXT_SML);
976 menu_text(7, -7 * h, 10 * j, COL0( 7), COL1( 7), "07", TXT_SML);
977 menu_text(8, -5 * h, 10 * j, COL0( 8), COL1( 8), "08", TXT_SML);
978 menu_text(9, -3 * h, 10 * j, COL0( 9), COL1( 9), "09", TXT_SML);
979 menu_text(10, -1 * h, 10 * j, COL0(10), COL1(10), "10", TXT_SML);
980 menu_text(11, -9 * h, 7 * j, COL0(11), COL1(11), "11", TXT_SML);
981 menu_text(12, -7 * h, 7 * j, COL0(12), COL1(12), "12", TXT_SML);
982 menu_text(13, -5 * h, 7 * j, COL0(13), COL1(13), "13", TXT_SML);
983 menu_text(14, -3 * h, 7 * j, COL0(14), COL1(14), "14", TXT_SML);
984 menu_text(15, -1 * h, 7 * j, COL0(15), COL1(15), "15", TXT_SML);
985 menu_text(16, -9 * h, 4 * j, COL0(16), COL1(16), "16", TXT_SML);
986 menu_text(17, -7 * h, 4 * j, COL0(17), COL1(17), "17", TXT_SML);
987 menu_text(18, -5 * h, 4 * j, COL0(18), COL1(18), "18", TXT_SML);
988 menu_text(19, -3 * h, 4 * j, COL0(19), COL1(19), "19", TXT_SML);
989 menu_text(20, -1 * h, 4 * j, COL0(20), COL1(20), "20", TXT_SML);
990 menu_text(21, -9 * h, j, COL0(21), COL1(21), "21", TXT_SML);
991 menu_text(22, -7 * h, j, COL0(22), COL1(22), "22", TXT_SML);
992 menu_text(23, -5 * h, j, COL0(23), COL1(23), "23", TXT_SML);
993 menu_text(24, -3 * h, j, COL0(24), COL1(24), "24", TXT_SML);
994 menu_text(25, -1 * h, j, COL0(25), COL1(25), "25", TXT_SML);
995 menu_text(26, 8 * h, 16 * j, c_yellow, c_red, "Level", TXT_SML);
997 highs_menu(0, 27, 27);
999 /* Active items */
1001 menu_item(0, -8 * h, 16 * j, 4 * h, 3 * j);
1002 menu_item(1, -9 * h, 13 * j, 2 * h, 3 * j);
1003 menu_item(2, -7 * h, 13 * j, 2 * h, 3 * j);
1004 menu_item(3, -5 * h, 13 * j, 2 * h, 3 * j);
1005 menu_item(4, -3 * h, 13 * j, 2 * h, 3 * j);
1006 menu_item(5, -1 * h, 13 * j, 2 * h, 3 * j);
1007 menu_item(6, -9 * h, 10 * j, 2 * h, 3 * j);
1008 menu_item(7, -7 * h, 10 * j, 2 * h, 3 * j);
1009 menu_item(8, -5 * h, 10 * j, 2 * h, 3 * j);
1010 menu_item(9, -3 * h, 10 * j, 2 * h, 3 * j);
1011 menu_item(10, -1 * h, 10 * j, 2 * h, 3 * j);
1012 menu_item(11, -9 * h, 7 * j, 2 * h, 3 * j);
1013 menu_item(12, -7 * h, 7 * j, 2 * h, 3 * j);
1014 menu_item(13, -5 * h, 7 * j, 2 * h, 3 * j);
1015 menu_item(14, -3 * h, 7 * j, 2 * h, 3 * j);
1016 menu_item(15, -1 * h, 7 * j, 2 * h, 3 * j);
1017 menu_item(16, -9 * h, 4 * j, 2 * h, 3 * j);
1018 menu_item(17, -7 * h, 4 * j, 2 * h, 3 * j);
1019 menu_item(18, -5 * h, 4 * j, 2 * h, 3 * j);
1020 menu_item(19, -3 * h, 4 * j, 2 * h, 3 * j);
1021 menu_item(20, -1 * h, 4 * j, 2 * h, 3 * j);
1022 menu_item(21, -9 * h, j, 2 * h, 3 * j);
1023 menu_item(22, -7 * h, j, 2 * h, 3 * j);
1024 menu_item(23, -5 * h, j, 2 * h, 3 * j);
1025 menu_item(24, -3 * h, j, 2 * h, 3 * j);
1026 menu_item(25, -1 * h, j, 2 * h, 3 * j);
1027 menu_item(26, +8 * h, 16 * j, 4 * h - 4, 3 * j);
1029 menu_stat(0, 0);
1031 for (i = 1; i < 26; i++)
1032 if (level_opened(i))
1033 menu_stat(i, 0);
1035 /* Item linkings for menu traversal */
1037 menu_link(0, -1, OPN(1), -1, -1);
1038 menu_link(1, 0, OPN(6), -1, OPN(2));
1039 menu_link(2, 0, OPN(7), OPN(1), OPN(3));
1040 menu_link(3, 0, OPN(8), OPN(2), OPN(4));
1041 menu_link(4, 0, OPN(9), OPN(3), OPN(5));
1042 menu_link(5, 0, OPN(10), OPN(4), OPN(6));
1043 menu_link(6, OPN(1), OPN(11), OPN(5), OPN(7));
1044 menu_link(7, OPN(2), OPN(12), OPN(6), OPN(8));
1045 menu_link(8, OPN(3), OPN(13), OPN(7), OPN(9));
1046 menu_link(9, OPN(4), OPN(14), OPN(8), OPN(10));
1047 menu_link(10, OPN(5), OPN(15), OPN(9), OPN(11));
1048 menu_link(11, OPN(6), OPN(16), OPN(10), OPN(12));
1049 menu_link(12, OPN(7), OPN(17), OPN(11), OPN(13));
1050 menu_link(13, OPN(8), OPN(18), OPN(12), OPN(14));
1051 menu_link(14, OPN(9), OPN(19), OPN(13), OPN(15));
1052 menu_link(15, OPN(10), OPN(20), OPN(14), OPN(16));
1053 menu_link(16, OPN(11), OPN(21), OPN(15), OPN(17));
1054 menu_link(17, OPN(12), OPN(22), OPN(16), OPN(18));
1055 menu_link(18, OPN(13), OPN(23), OPN(17), OPN(19));
1056 menu_link(19, OPN(14), OPN(24), OPN(18), OPN(20));
1057 menu_link(20, OPN(15), OPN(25), OPN(19), OPN(21));
1058 menu_link(21, OPN(16), -1, OPN(20), OPN(22));
1059 menu_link(22, OPN(17), -1, OPN(21), OPN(23));
1060 menu_link(23, OPN(18), -1, OPN(22), OPN(24));
1061 menu_link(24, OPN(19), -1, OPN(23), OPN(25));
1062 menu_link(25, OPN(20), -1, OPN(24), -1);
1064 /* Position the level shot. */
1066 shot_rect = make_rect(config_w() / 2,
1067 config_h() / 2 - j / 2,
1068 config_w() / 2 + 10 * h,
1069 config_h() / 2 + 29 * j / 2);
1071 SDL_ShowCursor(SDL_ENABLE);
1074 static void start_leave(void)
1076 if (glIsList(shot_rect))
1077 glDeleteLists(shot_rect, 1);
1079 SDL_ShowCursor(SDL_DISABLE);
1080 menu_free();
1083 static void start_paint(double dy)
1085 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1087 config_push_persp(FOV, 0.1, 300.0);
1089 back_draw(time_state());
1091 config_pop_matrix();
1093 glPushAttrib(GL_LIGHTING_BIT);
1094 glPushAttrib(GL_DEPTH_BUFFER_BIT);
1095 config_push_ortho();
1097 glEnable(GL_COLOR_MATERIAL);
1098 glDisable(GL_LIGHTING);
1099 glDisable(GL_DEPTH_TEST);
1101 level_shot(shot_level);
1102 glCallList(shot_rect);
1104 config_pop_matrix();
1105 glPopAttrib();
1106 glPopAttrib();
1108 menu_paint();
1111 static int start_point(int x, int y, int dx, int dy)
1113 int i;
1115 if ((i = menu_point(x, y)) >= 0 && shot_level != i)
1117 highs_menu(i, 27, 27);
1118 shot_level = i;
1121 return 1;
1124 static int start_click(int b, int d)
1126 return (b < 0 && d == 1) ? start_action(menu_click()) : 1;
1129 static int start_keybd(int c)
1131 if (c == SDLK_ESCAPE)
1132 return goto_state(&st_title);
1134 if (c == SDLK_F12)
1136 int i, n = curr_count();
1138 back_free();
1140 for (i = 1; i < n; i++)
1141 if (level_exists(i))
1142 level_snap(i);
1144 back_init("png/blues.png", config_geom());
1147 return 1;
1150 static int start_stick(int a, int v)
1152 int i;
1154 if ((i = menu_stick(a, v)) >= 0 && i != shot_level)
1156 highs_menu(i, 27, 27);
1157 shot_level = i;
1160 return 1;
1163 static int start_buttn(int b, int d)
1165 if (config_button_a(b) && d == 1) return start_action(menu_buttn());
1166 if (config_button_b(b) && d == 1) return goto_state(&st_title);
1167 if (config_button_X(b) && d == 1) return goto_state(&st_title);
1168 return 1;
1171 /*---------------------------------------------------------------------------*/
1173 static void level_enter(void)
1175 int y = 1 * config_h() / 6;
1176 int h = 1 * config_w() / 6;
1177 int w = 7 * config_w() / 8;
1178 int i, j, l = curr_level();
1180 char buf[STRMAX], *p = curr_intro();
1182 sprintf(buf, "Level %02d", l);
1184 menu_init(7, 7, 10);
1185 menu_text(0, 0, y, c_yellow, c_red, buf, TXT_LRG);
1186 menu_item(0, 0, y, w, h);
1188 /* Position the level intro message text. */
1190 text_size("M", TXT_SML, NULL, &l);
1191 y = 0;
1192 i = 1;
1194 while (p && i < 7)
1196 memset(buf, 0, STRMAX);
1197 j = 0;
1199 while (p && *p && *p != '\\')
1200 buf[j++] = *p++;
1202 if (strlen(buf) > 0)
1203 menu_text(i, 0, y, c_white, c_white, buf, TXT_SML);
1205 menu_item(i, 0, y, w, l);
1206 menu_stat(i, -1);
1208 y -= l;
1209 i++;
1211 if (*p) p++;
1214 game_set_fly(1.0);
1217 static void level_leave(void)
1219 menu_free();
1222 static void level_paint(double dy)
1224 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1225 game_draw(0, dy);
1226 hud_draw();
1227 menu_paint();
1230 static int level_click(int b, int d)
1232 return (b < 0 && d == 1) ? goto_state(&st_two) : 1;
1235 static int level_keybd(int c)
1237 if (c == SDLK_ESCAPE)
1238 goto_state(&st_over);
1239 if (c == SDLK_F12)
1240 goto_state(&st_poser);
1241 return 1;
1244 static int level_buttn(int b, int d)
1246 if (config_button_a(b) && d == 1) return goto_state(&st_two);
1247 if (config_button_X(b) && d == 1) return goto_state(&st_over);
1248 return 1;
1251 /*---------------------------------------------------------------------------*/
1253 static void poser_paint(double dy)
1255 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1256 game_draw(1, dy);
1259 static int poser_keybd(int c)
1261 return (c == SDLK_ESCAPE) ? goto_state(&st_level) : 1;
1264 /*---------------------------------------------------------------------------*/
1266 static void two_enter(void)
1268 int y = 1 * config_h() / 6;
1269 int h = 1 * config_w() / 6;
1270 int w = 2 * config_w() / 3;
1272 menu_init(1, 1, 1);
1273 menu_text(0, 0, y, c_yellow, c_red, "Ready?", TXT_LRG);
1274 menu_item(0, 0, y, w, h);
1276 audio_music_fade(2.f);
1277 audio_play(AUD_READY, 1.f);
1280 static void two_leave(void)
1282 menu_free();
1285 static void two_paint(double dy)
1287 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1288 game_draw(0, dy);
1289 hud_draw();
1290 menu_paint();
1293 static int two_timer(double dt)
1295 double t = time_state();
1297 game_set_fly(1.0 - 0.5 * t);
1299 if (dt > 0.0 && t > 1.0)
1300 return goto_state(&st_one);
1302 return 1;
1305 static int two_click(int b, int d)
1307 return (b < 0 && d == 1) ? goto_state(&st_play) : 1;
1310 static int two_keybd(int c)
1312 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
1315 static int two_buttn(int b, int d)
1317 if (config_button_a(b) && d == 1) return goto_state(&st_play);
1318 if (config_button_X(b) && d == 1) return goto_state(&st_over);
1319 return 1;
1322 /*---------------------------------------------------------------------------*/
1324 static void one_enter(void)
1326 int y = 1 * config_h() / 6;
1327 int h = 1 * config_w() / 6;
1328 int w = 2 * config_w() / 3;
1330 menu_init(1, 1, 1);
1331 menu_text(0, 0, y, c_yellow, c_red, "Set?", TXT_LRG);
1332 menu_item(0, 0, y, w, h);
1334 audio_play(AUD_SET, 1.f);
1337 static void one_leave(void)
1339 menu_free();
1342 static void one_paint(double dy)
1344 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1345 game_draw(0, dy);
1346 hud_draw();
1347 menu_paint();
1350 static int one_timer(double dt)
1352 double t = time_state();
1354 game_set_fly(0.5 - 0.5 * t);
1356 if (dt > 0.0 && t > 1.0)
1357 return goto_state(&st_play);
1359 return 1;
1362 static int one_click(int b, int d)
1364 if (b < 0 && d == 1)
1366 game_set_fly(0.0);
1367 return goto_state(&st_play);
1369 return 1;
1372 static int one_keybd(int c)
1374 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
1377 static int one_buttn(int b, int d)
1379 if (config_button_a(b) && d == 1) return goto_state(&st_play);
1380 if (config_button_X(b) && d == 1) return goto_state(&st_over);
1381 return 1;
1384 /*---------------------------------------------------------------------------*/
1386 static int view_rotate = 0;
1388 static void play_enter(void)
1390 char filename[STRMAX];
1392 int y = 1 * config_h() / 6;
1393 int h = 1 * config_w() / 6;
1394 int w = 2 * config_w() / 3;
1396 menu_init(1, 1, 1);
1397 menu_text(0, 0, y, c_blue, c_green, "GO!", TXT_LRG);
1398 menu_item(0, 0, y, w, h);
1400 level_song();
1401 audio_play(AUD_GO, 1.f);
1403 game_set_fly(0.0);
1404 view_rotate = 0;
1406 if (config_home(filename, USER_REPLAY_FILE, STRMAX))
1407 if ((record_fp = fopen(filename, FMODE_WB)))
1409 fputc(set_curr(), record_fp);
1410 fputc(curr_score(), record_fp);
1411 fputc(curr_coins(), record_fp);
1412 fputc(curr_balls(), record_fp);
1413 fputc(curr_level(), record_fp);
1417 static void play_leave(void)
1419 menu_free();
1422 static void play_paint(double dy)
1424 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1426 game_draw(0, dy);
1427 hud_draw();
1429 if (time_state() < 1.0)
1430 menu_paint();
1433 static int play_timer(double dt)
1435 static double at = 0;
1437 double g[3] = { 0.0, -9.8, 0.0 };
1439 at = (7 * at + dt) / 8;
1441 hud_step(at);
1442 game_set_rot(view_rotate);
1444 switch (game_step(g, at, 1))
1446 case GAME_TIME: goto_state(&st_time); break;
1447 case GAME_GOAL: goto_state(&st_goal); break;
1448 case GAME_FALL: goto_state(&st_fall); break;
1451 if (record_fp)
1453 double_put(record_fp, &at);
1454 game_put(record_fp);
1457 return 1;
1460 static int play_point(int x, int y, int dx, int dy)
1462 game_set_pos(dx, dy);
1463 return 1;
1466 static int play_click(int b, int d)
1468 view_rotate = d ? b : 0;
1469 return 1;
1472 static int play_keybd(int c)
1474 if (c == SDLK_ESCAPE)
1475 goto_state(&st_over);
1476 return 1;
1479 static int play_stick(int a, int k)
1481 if (config_axis_x(a)) game_set_z(k);
1482 if (config_axis_y(a)) game_set_x(k);
1483 return 1;
1486 static int play_buttn(int b, int d)
1488 if (config_button_r(b))
1490 if (d == 1)
1491 view_rotate += 1;
1492 else
1493 view_rotate -= 1;
1495 if (config_button_l(b))
1497 if (d == 1)
1498 view_rotate -= 1;
1499 else
1500 view_rotate += 1;
1502 if (config_button_X(b) && d == 1)
1503 return goto_state(&st_over);
1505 return 1;
1508 /*---------------------------------------------------------------------------*/
1510 static void demo_enter(void)
1512 char filename[STRMAX];
1514 int y = 1 * config_h() / 6;
1515 int h = 1 * config_w() / 6;
1516 int w = 2 * config_w() / 3;
1518 menu_init(1, 1, 1);
1519 menu_text(0, 0, y, c_blue, c_green, "Demo", TXT_LRG);
1520 menu_item(0, 0, y, w, h);
1522 global_time = -1.0;
1523 replay_time = 0.0;
1525 if (config_home(filename, USER_REPLAY_FILE, STRMAX))
1526 if ((replay_fp = fopen(filename, FMODE_RB)))
1528 int l, b, c, s, n = fgetc(replay_fp);
1530 if (set_exists(n))
1532 set_goto(n);
1534 s = fgetc(replay_fp);
1535 c = fgetc(replay_fp);
1536 b = fgetc(replay_fp);
1537 l = fgetc(replay_fp);
1539 if (level_exists(l))
1541 level_goto(s, c, b, l);
1542 level_song();
1547 game_set_fly(0.0);
1550 static void demo_leave(void)
1552 if (replay_fp)
1554 fclose(replay_fp);
1555 replay_fp = NULL;
1557 menu_free();
1560 static void demo_paint(double dy)
1562 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1564 game_draw(0, dy);
1565 hud_draw();
1567 if (time_state() < 1.0)
1568 menu_paint();
1571 static int demo_timer(double dt)
1573 double g[3] = { 0.0, -9.8, 0.0 };
1574 double t;
1575 int b = 1;
1577 global_time += dt;
1579 if (replay_fp)
1581 /* Spin or skip depending on how fast the demo wants to run. */
1583 while (replay_time < global_time && (b = double_get(replay_fp, &t)))
1585 /* Play out current game state for particles, clock, etc. */
1587 hud_step(t);
1588 game_step(g, t, 1);
1590 replay_time += t;
1592 /* Load demo game state from file. */
1594 if (!game_get(replay_fp))
1595 goto_state(&st_omed);
1597 if (!b) goto_state(&st_omed);
1599 else goto_state(&st_omed);
1601 return 1;
1604 static int demo_keybd(int c)
1606 if (c == SDLK_ESCAPE)
1607 goto_state(&st_omed);
1608 return 1;
1611 static int demo_buttn(int b, int d)
1613 if (config_button_X(b) && d == 1)
1614 return goto_state(&st_omed);
1616 return 1;
1619 /*---------------------------------------------------------------------------*/
1621 static void goal_enter(void)
1623 int y = 1 * config_h() / 6;
1624 int h = 1 * config_w() / 6;
1625 int w = 2 * config_w() / 3;
1627 menu_init(25, 5, 99);
1628 menu_text(0, 0, y, c_blue, c_green, "GOAL!", TXT_LRG);
1629 menu_item(0, 0, y, w, h);
1631 score_menu(curr_level(), 1, 1);
1632 highs_menu(curr_level(), 5, 3);
1634 audio_music_fade(3.f);
1635 audio_play(AUD_GOAL, 1.f);
1638 static void goal_leave(void)
1640 if (record_fp)
1642 fclose(record_fp);
1643 record_fp = NULL;
1645 menu_free();
1646 audio_music_play("bgm/inter.ogg");
1649 static void goal_paint(double dy)
1651 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1652 game_draw(0, dy);
1653 menu_paint();
1656 static int goal_click(int b, int d)
1658 if (b <= 0 && d == 1)
1660 if (level_goal())
1661 goto_state(&st_score);
1662 else
1664 if (level_pass())
1665 goto_state(&st_level);
1666 else
1667 goto_state(&st_done);
1670 return 1;
1673 static int goal_keybd(int c)
1675 if (c == SDLK_ESCAPE)
1676 goto_state(&st_over);
1677 return 1;
1680 static int goal_timer(double dt)
1682 double g[3] = { 0.0, 9.8, 0.0 };
1683 double t = dt;
1685 if (time_state() < 1.0)
1687 game_step(g, dt, 0);
1689 if (record_fp)
1691 double_put(record_fp, &t);
1692 game_put(record_fp);
1695 return 1;
1698 static int goal_buttn(int b, int d)
1700 if (config_button_a(b) && d == 1) return goal_click(0, 1);
1701 if (config_button_X(b) && d == 1) return goto_state(&st_over);
1702 return 1;
1705 /*---------------------------------------------------------------------------*/
1707 static int score_action(int i)
1709 int w, h, l = (int) strlen(player);
1711 if (i == 28)
1713 /* Ok selected */
1715 if (level_pass())
1716 goto_state(&st_level);
1717 else
1718 goto_state(&st_done);
1720 return 1;
1722 if (i == 27)
1724 /* Backspace selected */
1726 if (l > 0)
1727 player[l - 1] = 0;
1729 else
1731 /* Letter selected */
1733 if (l < MAXNAM - 1)
1735 player[l + 0] = i + 'A' - 1;
1736 player[l + 1] = 0;
1740 text_size("M", TXT_MED, &w, &h);
1741 menu_text(0, 0, h & (~3), c_yellow, c_white, player, TXT_MED);
1743 return 1;
1746 static void score_enter(void)
1748 int i;
1749 int sw, mw, lw;
1750 int sh, mh, lh;
1752 text_size("M", TXT_SML, &sw, &sh);
1753 text_size("M", TXT_MED, &mw, &mh);
1754 text_size("M", TXT_LRG, &lw, &lh);
1755 sw *= 2;
1756 sh *= 2;
1758 menu_init(34, 32, 28);
1760 /* Text elements */
1762 menu_text(0, 0, mh, c_yellow, c_white, player, TXT_MED);
1763 menu_text(29, 0, 3 * mh, c_yellow, c_red, "New Record!", TXT_LRG);
1765 menu_text(1, -3 * sw, -1 * sh, c_white, c_white, "A", TXT_SML);
1766 menu_text(2, -2 * sw, -1 * sh, c_white, c_white, "B", TXT_SML);
1767 menu_text(3, -1 * sw, -1 * sh, c_white, c_white, "C", TXT_SML);
1768 menu_text(4, 0 * sw, -1 * sh, c_white, c_white, "D", TXT_SML);
1769 menu_text(5, +1 * sw, -1 * sh, c_white, c_white, "E", TXT_SML);
1770 menu_text(6, +2 * sw, -1 * sh, c_white, c_white, "F", TXT_SML);
1771 menu_text(7, +3 * sw, -1 * sh, c_white, c_white, "G", TXT_SML);
1772 menu_text(8, -3 * sw, -2 * sh, c_white, c_white, "H", TXT_SML);
1773 menu_text(9, -2 * sw, -2 * sh, c_white, c_white, "I", TXT_SML);
1774 menu_text(10, -1 * sw, -2 * sh, c_white, c_white, "J", TXT_SML);
1775 menu_text(11, 0 * sw, -2 * sh, c_white, c_white, "K", TXT_SML);
1776 menu_text(12, +1 * sw, -2 * sh, c_white, c_white, "L", TXT_SML);
1777 menu_text(13, +2 * sw, -2 * sh, c_white, c_white, "M", TXT_SML);
1778 menu_text(14, +3 * sw, -2 * sh, c_white, c_white, "N", TXT_SML);
1779 menu_text(15, -3 * sw, -3 * sh, c_white, c_white, "O", TXT_SML);
1780 menu_text(16, -2 * sw, -3 * sh, c_white, c_white, "P", TXT_SML);
1781 menu_text(17, -1 * sw, -3 * sh, c_white, c_white, "Q", TXT_SML);
1782 menu_text(18, 0 * sw, -3 * sh, c_white, c_white, "R", TXT_SML);
1783 menu_text(19, +1 * sw, -3 * sh, c_white, c_white, "S", TXT_SML);
1784 menu_text(20, +2 * sw, -3 * sh, c_white, c_white, "T", TXT_SML);
1785 menu_text(21, +3 * sw, -3 * sh, c_white, c_white, "U", TXT_SML);
1786 menu_text(22, -3 * sw, -4 * sh, c_white, c_white, "V", TXT_SML);
1787 menu_text(23, -2 * sw, -4 * sh, c_white, c_white, "W", TXT_SML);
1788 menu_text(24, -1 * sw, -4 * sh, c_white, c_white, "X", TXT_SML);
1789 menu_text(25, 0 * sw, -4 * sh, c_white, c_white, "Y", TXT_SML);
1790 menu_text(26, +1 * sw, -4 * sh, c_white, c_white, "Z", TXT_SML);
1791 menu_text(27, +2 * sw, -4 * sh, c_green, c_white, "<", TXT_SML);
1792 menu_text(28, +3 * sw, -4 * sh, c_green, c_white, "Ok", TXT_SML);
1794 score_menu(curr_level(), 30, 30);
1796 /* Active elements. */
1798 menu_item(0, 0, mh, mw * MAXNAM, mh);
1799 menu_item(29, 0, 3 * mh, 8 * config_w() / 9, lh);
1801 menu_item(1, -3 * sw, -1 * sh, sw, sh);
1802 menu_item(2, -2 * sw, -1 * sh, sw, sh);
1803 menu_item(3, -1 * sw, -1 * sh, sw, sh);
1804 menu_item(4, 0 * sw, -1 * sh, sw, sh);
1805 menu_item(5, +1 * sw, -1 * sh, sw, sh);
1806 menu_item(6, +2 * sw, -1 * sh, sw, sh);
1807 menu_item(7, +3 * sw, -1 * sh, sw, sh);
1808 menu_item(8, -3 * sw, -2 * sh, sw, sh);
1809 menu_item(9, -2 * sw, -2 * sh, sw, sh);
1810 menu_item(10, -1 * sw, -2 * sh, sw, sh);
1811 menu_item(11, 0 * sw, -2 * sh, sw, sh);
1812 menu_item(12, +1 * sw, -2 * sh, sw, sh);
1813 menu_item(13, +2 * sw, -2 * sh, sw, sh);
1814 menu_item(14, +3 * sw, -2 * sh, sw, sh);
1815 menu_item(15, -3 * sw, -3 * sh, sw, sh);
1816 menu_item(16, -2 * sw, -3 * sh, sw, sh);
1817 menu_item(17, -1 * sw, -3 * sh, sw, sh);
1818 menu_item(18, 0 * sw, -3 * sh, sw, sh);
1819 menu_item(19, +1 * sw, -3 * sh, sw, sh);
1820 menu_item(20, +2 * sw, -3 * sh, sw, sh);
1821 menu_item(21, +3 * sw, -3 * sh, sw, sh);
1822 menu_item(22, -3 * sw, -4 * sh, sw, sh);
1823 menu_item(23, -2 * sw, -4 * sh, sw, sh);
1824 menu_item(24, -1 * sw, -4 * sh, sw, sh);
1825 menu_item(25, 0 * sw, -4 * sh, sw, sh);
1826 menu_item(26, +1 * sw, -4 * sh, sw, sh);
1827 menu_item(27, +2 * sw, -4 * sh, sw, sh);
1828 menu_item(28, +3 * sw, -4 * sh, sw, sh);
1830 for (i = 1; i < 29; i++)
1831 menu_stat(i, 0);
1833 /* Menu traversal linkages. */
1835 menu_link(1, -1, 8, -1, 2);
1836 menu_link(2, -1, 9, 1, 3);
1837 menu_link(3, -1, 10, 2, 4);
1838 menu_link(4, -1, 11, 3, 5);
1839 menu_link(5, -1, 12, 4, 6);
1840 menu_link(6, -1, 13, 5, 7);
1841 menu_link(7, -1, 14, 6, 8);
1842 menu_link(8, 1, 15, 7, 9);
1843 menu_link(9, 2, 16, 8, 10);
1844 menu_link(10, 3, 17, 9, 11);
1845 menu_link(11, 4, 18, 10, 12);
1846 menu_link(12, 5, 19, 11, 13);
1847 menu_link(13, 6, 20, 12, 14);
1848 menu_link(14, 7, 21, 13, 15);
1849 menu_link(15, 8, 22, 14, 16);
1850 menu_link(16, 9, 23, 15, 17);
1851 menu_link(17, 10, 24, 16, 18);
1852 menu_link(18, 11, 25, 17, 19);
1853 menu_link(19, 12, 26, 18, 20);
1854 menu_link(20, 13, 27, 19, 21);
1855 menu_link(21, 14, 28, 20, 22);
1856 menu_link(22, 15, -1, 21, 23);
1857 menu_link(23, 16, -1, 22, 24);
1858 menu_link(24, 17, -1, 23, 25);
1859 menu_link(25, 18, -1, 24, 26);
1860 menu_link(26, 19, -1, 25, 27);
1861 menu_link(27, 20, -1, 26, 28);
1862 menu_link(28, 20, -1, 27, -1);
1864 audio_play(AUD_SCORE, 1.f);
1866 SDL_ShowCursor(SDL_ENABLE);
1869 static void score_leave(void)
1871 SDL_ShowCursor(SDL_DISABLE);
1873 menu_free();
1876 static void score_paint(double dy)
1878 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1879 game_draw(0, dy);
1880 menu_paint();
1883 static int score_point(int x, int y, int dx, int dy)
1885 menu_point(x, y);
1886 return 1;
1889 static int score_click(int b, int d)
1891 return (b < 0 && d == 1) ? score_action(menu_click()) : 1;
1894 static int score_keybd(int c)
1896 if (c == SDLK_ESCAPE)
1897 goto_state(&st_over);
1898 return 1;
1901 static int score_stick(int a, int v)
1903 menu_stick(a, v);
1904 return 1;
1907 static int score_buttn(int b, int d)
1909 if (config_button_a(b) && d == 1) return score_action(menu_buttn());
1910 if (config_button_X(b) && d == 1) return goto_state(&st_over);
1911 return 1;
1914 /*---------------------------------------------------------------------------*/
1916 static void fall_enter(void)
1918 int y = 1 * config_h() / 6;
1919 int h = 1 * config_w() / 6;
1920 int w = 7 * config_w() / 8;
1922 menu_init(1, 1, 1);
1923 menu_text(0, 0, y, c_black, c_red, "Fall-out!", TXT_LRG);
1924 menu_item(0, 0, y, w, h);
1926 audio_music_fade(1.f);
1927 audio_play(AUD_FALL, 1.f);
1930 static void fall_leave(void)
1932 if (record_fp)
1934 fclose(record_fp);
1935 record_fp = NULL;
1937 menu_free();
1938 audio_music_play("bgm/inter.ogg");
1941 static void fall_paint(double dy)
1943 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1944 game_draw(0, dy);
1945 hud_draw();
1946 menu_paint();
1949 static int fall_click(int b, int d)
1951 if (b <= 0 && d == 1)
1953 if (level_fail())
1954 goto_state(&st_level);
1955 else
1956 goto_state(&st_over);
1958 return 1;
1961 static int fall_keybd(int c)
1963 if (c == SDLK_ESCAPE)
1964 goto_state(&st_over);
1965 return 1;
1968 static int fall_timer(double dt)
1970 double g[3] = { 0.0, -9.8, 0.0 };
1971 double t = dt;
1973 if (time_state() < 2.0)
1975 game_step(g, dt, 0);
1977 if (record_fp)
1979 double_put(record_fp, &t);
1980 game_put(record_fp);
1983 else
1984 return fall_click(0, 1);
1986 return 1;
1989 static int fall_buttn(int b, int d)
1991 if (config_button_a(b) && d == 1) return fall_click(0, 1);
1992 if (config_button_X(b) && d == 1) return goto_state(&st_over);
1993 return 1;
1996 /*---------------------------------------------------------------------------*/
1998 static void time_enter(void)
2000 int y = 1 * config_h() / 6;
2001 int h = 1 * config_w() / 6;
2002 int w = 7 * config_w() / 8;
2004 menu_init(1, 1, 1);
2005 menu_text(0, 0, y, c_black, c_red, "Time's up!", TXT_LRG);
2006 menu_item(0, 0, y, w, h);
2008 audio_music_fade(1.f);
2009 audio_play(AUD_TIME, 1.f);
2012 static void time_leave(void)
2014 if (record_fp)
2016 fclose(record_fp);
2017 record_fp = NULL;
2019 menu_free();
2020 audio_music_play("bgm/inter.ogg");
2023 static void time_paint(double dy)
2025 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2026 game_draw(0, dy);
2027 hud_draw();
2028 menu_paint();
2031 static int time_click(int b, int d)
2033 if (b <= 0 && d == 1)
2035 if (level_fail())
2036 goto_state(&st_level);
2037 else
2038 goto_state(&st_over);
2040 return 1;
2043 static int time_timer(double dt)
2045 double g[3] = { 0.0, -9.8, 0.0 };
2046 double t = dt;
2048 if (time_state() < 2.0)
2050 game_step(g, dt, 0);
2052 if (record_fp)
2054 double_put(record_fp, &t);
2055 game_put(record_fp);
2058 else
2059 return time_click(0, 1);
2061 return 1;
2064 static int time_buttn(int b, int d)
2066 if (config_button_a(b) && d == 1) return time_click(0, 1);
2067 if (config_button_X(b) && d == 1) return goto_state(&st_over);
2068 return 1;
2071 /*---------------------------------------------------------------------------*/
2073 static void omed_enter(void)
2075 int y = 1 * config_h() / 6;
2076 int h = 1 * config_w() / 6;
2077 int w = 7 * config_w() / 8;
2079 menu_init(1, 1, 1);
2080 menu_text(0, 0, y, c_black, c_red, "Demo Ends", TXT_LRG);
2081 menu_item(0, 0, y, w, h);
2083 audio_music_fade(3.f);
2086 static void omed_leave(void)
2088 audio_music_stop();
2089 menu_free();
2090 set_free();
2093 static void omed_paint(double dy)
2095 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2096 game_draw(0, dy);
2097 menu_paint();
2100 static int omed_timer(double dt)
2102 return (dt > 0.0 && time_state() > 3.0) ? goto_state(&st_title) : 1;
2105 static int omed_keybd(int c)
2107 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
2110 static int omed_click(int b, int d)
2112 return (b < 0 && d == 1) ? goto_state(&st_title) : 1;
2115 static int omed_buttn(int b, int d)
2117 if (config_button_a(b) && d == 1) goto_state(&st_title);
2118 if (config_button_b(b) && d == 1) goto_state(&st_title);
2119 return 1;
2122 /*---------------------------------------------------------------------------*/
2124 static void over_enter(void)
2126 int y = 1 * config_h() / 6;
2127 int h = 1 * config_w() / 6;
2128 int w = 7 * config_w() / 8;
2130 menu_init(1, 1, 1);
2131 menu_text(0, 0, y, c_black, c_red, "GAME OVER", TXT_LRG);
2132 menu_item(0, 0, y, w, h);
2134 audio_music_stop();
2135 audio_play(AUD_OVER, 1.f);
2138 static void over_leave(void)
2140 if (record_fp)
2142 fclose(record_fp);
2143 record_fp = NULL;
2145 menu_free();
2146 set_free();
2149 static void over_paint(double dy)
2151 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2152 game_draw(0, dy);
2153 menu_paint();
2156 static int over_timer(double dt)
2158 return (dt > 0.0 && time_state() > 3.0) ? goto_state(&st_title) : 1;
2161 static int over_keybd(int c)
2163 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
2166 static int over_click(int b, int d)
2168 return (b < 0 && d == 1) ? goto_state(&st_title) : 1;
2171 static int over_buttn(int b, int d)
2173 if (config_button_a(b) && d == 1) goto_state(&st_title);
2174 if (config_button_b(b) && d == 1) goto_state(&st_title);
2175 return 1;
2178 /*---------------------------------------------------------------------------*/
2180 #define STR_DONE " Congrats! "
2181 #define STR_THNX " That's it for this set. "
2182 #define STR_MORE " Move on to the next one. "
2184 static void done_enter(void)
2186 int lw, lh, lm;
2187 int sw, sh;
2189 text_size(STR_DONE, TXT_LRG, &lw, &lh);
2190 text_size(STR_MORE, TXT_SML, &sw, &sh);
2192 lm = lh / 2;
2194 menu_init(3, 3, 10);
2195 menu_text(0, 0, sh + lm, c_green, c_yellow, STR_DONE, TXT_LRG);
2196 menu_text(1, 0, -0 * sh, c_white, c_white, STR_THNX, TXT_SML);
2197 menu_text(2, 0, -1 * sh, c_white, c_white, STR_MORE, TXT_SML);
2199 menu_item(0, 0, sh + lm, lw, lh);
2200 menu_item(1, 0, -0 * sh, sw, sh);
2201 menu_item(2, 0, -1 * sh, sw, sh);
2203 audio_play(AUD_OVER, 1.f);
2206 static void done_leave(void)
2208 menu_free();
2209 set_free();
2212 static void done_paint(double dy)
2214 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2215 game_draw(0, dy);
2216 menu_paint();
2219 static int done_timer(double dt)
2221 return (dt > 0.0 && time_state() > 10.0) ? goto_state(&st_title) : 1;
2224 static int done_keybd(int c)
2226 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
2229 static int done_click(int b, int d)
2231 return (b < 0 && d == 1) ? goto_state(&st_title) : 1;
2234 static int done_buttn(int b, int d)
2236 if (config_button_a(b) && d == 1) goto_state(&st_title);
2237 if (config_button_b(b) && d == 1) goto_state(&st_title);
2238 return 1;
2241 /*---------------------------------------------------------------------------*/
2243 struct state st_null = {
2244 NULL,
2245 NULL,
2246 NULL,
2247 NULL,
2248 NULL,
2249 NULL,
2250 NULL,
2251 NULL,
2252 NULL,
2255 struct state st_title = {
2256 title_enter,
2257 title_leave,
2258 title_paint,
2259 title_timer,
2260 title_point,
2261 title_click,
2262 title_keybd,
2263 title_stick,
2264 title_buttn,
2267 struct state st_help = {
2268 help_enter,
2269 help_leave,
2270 help_paint,
2271 NULL,
2272 NULL,
2273 help_click,
2274 help_keybd,
2275 NULL,
2276 help_buttn,
2279 struct state st_set = {
2280 set_enter,
2281 set_leave,
2282 set_paint,
2283 NULL,
2284 set_point,
2285 set_click,
2286 set_keybd,
2287 set_stick,
2288 set_buttn,
2291 struct state st_start = {
2292 start_enter,
2293 start_leave,
2294 start_paint,
2295 NULL,
2296 start_point,
2297 start_click,
2298 start_keybd,
2299 start_stick,
2300 start_buttn,
2303 struct state st_conf = {
2304 conf_enter,
2305 conf_leave,
2306 conf_paint,
2307 NULL,
2308 conf_point,
2309 conf_click,
2310 conf_keybd,
2311 conf_stick,
2312 conf_buttn,
2315 struct state st_level = {
2316 level_enter,
2317 level_leave,
2318 level_paint,
2319 NULL,
2320 NULL,
2321 level_click,
2322 level_keybd,
2323 NULL,
2324 level_buttn,
2327 struct state st_poser = {
2328 NULL,
2329 NULL,
2330 poser_paint,
2331 NULL,
2332 NULL,
2333 NULL,
2334 poser_keybd,
2335 NULL,
2336 NULL,
2339 struct state st_two = {
2340 two_enter,
2341 two_leave,
2342 two_paint,
2343 two_timer,
2344 NULL,
2345 two_click,
2346 two_keybd,
2347 NULL,
2348 two_buttn,
2351 struct state st_one = {
2352 one_enter,
2353 one_leave,
2354 one_paint,
2355 one_timer,
2356 NULL,
2357 one_click,
2358 one_keybd,
2359 NULL,
2360 one_buttn,
2363 struct state st_play = {
2364 play_enter,
2365 play_leave,
2366 play_paint,
2367 play_timer,
2368 play_point,
2369 play_click,
2370 play_keybd,
2371 play_stick,
2372 play_buttn,
2375 struct state st_demo = {
2376 demo_enter,
2377 demo_leave,
2378 demo_paint,
2379 demo_timer,
2380 NULL,
2381 NULL,
2382 demo_keybd,
2383 NULL,
2384 demo_buttn,
2387 struct state st_goal = {
2388 goal_enter,
2389 goal_leave,
2390 goal_paint,
2391 goal_timer,
2392 NULL,
2393 goal_click,
2394 goal_keybd,
2395 NULL,
2396 goal_buttn,
2399 struct state st_score = {
2400 score_enter,
2401 score_leave,
2402 score_paint,
2403 NULL,
2404 score_point,
2405 score_click,
2406 score_keybd,
2407 score_stick,
2408 score_buttn,
2411 struct state st_fall = {
2412 fall_enter,
2413 fall_leave,
2414 fall_paint,
2415 fall_timer,
2416 NULL,
2417 fall_click,
2418 fall_keybd,
2419 NULL,
2420 fall_buttn,
2423 struct state st_time = {
2424 time_enter,
2425 time_leave,
2426 time_paint,
2427 time_timer,
2428 NULL,
2429 time_click,
2430 NULL,
2431 NULL,
2432 time_buttn,
2435 struct state st_omed = {
2436 omed_enter,
2437 omed_leave,
2438 omed_paint,
2439 omed_timer,
2440 NULL,
2441 omed_click,
2442 omed_keybd,
2443 NULL,
2444 omed_buttn,
2447 struct state st_over = {
2448 over_enter,
2449 over_leave,
2450 over_paint,
2451 over_timer,
2452 NULL,
2453 over_click,
2454 over_keybd,
2455 NULL,
2456 over_buttn,
2459 struct state st_done = {
2460 done_enter,
2461 done_leave,
2462 done_paint,
2463 done_timer,
2464 NULL,
2465 done_click,
2466 done_keybd,
2467 NULL,
2468 done_buttn,