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.
38 static double global_time
;
39 static double replay_time
;
41 /*---------------------------------------------------------------------------*/
43 static double state_time
= 0.0;
44 static struct state
*state
= NULL
;
54 double time_state(void)
59 int goto_state(struct state
*st
)
61 if (state
&& state
->leave
)
67 if (state
&& state
->enter
)
73 /*---------------------------------------------------------------------------*/
77 if (state
&& state
->paint
)
81 glDrawBuffer(GL_BACK_LEFT
);
82 state
->paint(+config_stereo());
84 glDrawBuffer(GL_BACK_RIGHT
);
85 state
->paint(-config_stereo());
92 int st_timer(double 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;
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 /*---------------------------------------------------------------------------*/
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
)
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;
151 static void title_enter(void)
156 text_size(STR_TITLE
, TXT_LRG
, &lw
, &lh
);
157 text_size(STR_CONF
, TXT_MED
, &mw
, &mh
);
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);
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);
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
);
205 audio_music_play("bgm/inter.ogg");
208 static void title_paint(double dy
)
210 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
215 static int title_timer(double dt
)
217 game_set_fly(cos(time_state() / 10.0));
221 static int title_point(int x
, int y
, int dx
, int dy
)
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
)
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;
250 /*---------------------------------------------------------------------------*/
252 static void help_enter(void)
254 const GLfloat
*c0
= c_white
;
255 const GLfloat
*c1
= c_yellow
;
258 text_size("X", TXT_SML
, &w
, &h
);
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
);
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());
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 /*---------------------------------------------------------------------------*/
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
349 static int conf_action(int i
)
354 text_size("MMMMMMMMM", TXT_SML
, &w
, &h
);
360 goto_state(&st_null
);
361 s
= config_set_mode(config_w(), config_h(), SDL_OPENGL
|SDL_FULLSCREEN
);
362 goto_state(&st_conf
);
366 goto_state(&st_null
);
367 s
= config_set_mode(config_w(), config_h(), SDL_OPENGL
);
368 goto_state(&st_conf
);
372 goto_state(&st_null
);
373 s
= config_set_mode(1600, 1200, config_mode());
374 goto_state(&st_conf
);
378 goto_state(&st_null
);
379 s
= config_set_mode(1280, 1024, config_mode());
380 goto_state(&st_conf
);
384 goto_state(&st_null
);
385 s
= config_set_mode(1024, 768, config_mode());
386 goto_state(&st_conf
);
390 goto_state(&st_null
);
391 s
= config_set_mode(800, 600, config_mode());
392 goto_state(&st_conf
);
396 goto_state(&st_null
);
397 s
= config_set_mode(640, 480, config_mode());
398 goto_state(&st_conf
);
402 goto_state(&st_null
);
404 goto_state(&st_conf
);
408 goto_state(&st_null
);
410 goto_state(&st_conf
);
414 goto_state(&st_null
);
416 goto_state(&st_conf
);
420 goto_state(&st_null
);
422 goto_state(&st_conf
);
426 s
= config_set_audio(44100, AUD_BUFF_HI
);
427 goto_state(&st_conf
);
431 s
= config_set_audio(22050, AUD_BUFF_LO
);
432 goto_state(&st_conf
);
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
);
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
);
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
);
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
);
466 goto_state(&st_title
);
472 static void conf_enter(void)
474 static int value
= CONF_FULL
;
481 /* Compute menu sizes from font sizes */
483 text_size("MMMMMMMMM", TXT_SML
, &w
, &h
);
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());
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
);
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
);
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
);
608 SDL_ShowCursor(SDL_ENABLE
);
611 static void conf_leave(void)
613 SDL_ShowCursor(SDL_DISABLE
);
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());
633 static int conf_point(int x
, int y
, int dx
, int dy
)
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
)
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
);
663 /*---------------------------------------------------------------------------*/
665 static GLuint shot_rect
= 0;
666 static int shot_set
= 0;
668 static int set_action(int i
)
675 return goto_state(&st_title
);
677 if (2 <= i
&& i
<= 6)
681 return goto_state(&st_start
);
687 static void set_describe(int i
)
689 int w
, h
, j
, y
, m
= 7;
692 const char *p
= set_desc(i
);
694 text_size("0", TXT_SML
, &w
, &h
);
703 while (p
&& *p
&& *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
);
718 static void set_enter(void)
724 audio_play(AUD_START
, 1.f
);
728 text_size("0", TXT_SML
, &w
, &h
);
732 menu_init(12, 12, 0);
733 back_init("png/blues.png", config_geom());
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
);
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
);
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);
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);
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
);
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());
805 glPushAttrib(GL_LIGHTING_BIT
);
806 glPushAttrib(GL_DEPTH_BUFFER_BIT
);
809 glEnable(GL_COLOR_MATERIAL
);
810 glDisable(GL_LIGHTING
);
811 glDisable(GL_DEPTH_TEST
);
814 glCallList(shot_rect
);
823 static int set_point(int x
, int y
, int dx
, int dy
)
827 if ((i
= menu_point(x
, y
)) >= 0 && shot_set
!= i
- 2)
830 set_describe(shot_set
);
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
)
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
);
860 /*---------------------------------------------------------------------------*/
862 static void score_menu(int i
, int j
, int k
)
864 const GLfloat
*c0
= c_yellow
;
865 const GLfloat
*c1
= c_white
;
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
;
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 /*---------------------------------------------------------------------------*/
925 static int shot_level
= -1;
927 static int start_action(int i
)
934 return goto_state(&st_set
);
939 level_goto(0, 0, 2, i
);
940 return goto_state(&st_level
);
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)
961 text_size("0", TXT_SML
, &w
, &h
);
964 menu_init(47, 29, 0);
965 back_init("png/blues.png", config_geom());
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);
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
);
1031 for (i
= 1; i
< 26; i
++)
1032 if (level_opened(i
))
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
);
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();
1111 static int start_point(int x
, int y
, int dx
, int dy
)
1115 if ((i
= menu_point(x
, y
)) >= 0 && shot_level
!= i
)
1117 highs_menu(i
, 27, 27);
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
);
1136 int i
, n
= curr_count();
1140 for (i
= 1; i
< n
; i
++)
1141 if (level_exists(i
))
1144 back_init("png/blues.png", config_geom());
1150 static int start_stick(int a
, int v
)
1154 if ((i
= menu_stick(a
, v
)) >= 0 && i
!= shot_level
)
1156 highs_menu(i
, 27, 27);
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
);
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
);
1196 memset(buf
, 0, STRMAX
);
1199 while (p
&& *p
&& *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
);
1217 static void level_leave(void)
1222 static void level_paint(double dy
)
1224 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
);
1240 goto_state(&st_poser
);
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
);
1251 /*---------------------------------------------------------------------------*/
1253 static void poser_paint(double dy
)
1255 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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;
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)
1285 static void two_paint(double dy
)
1287 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
);
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
);
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;
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)
1342 static void one_paint(double dy
)
1344 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
);
1362 static int one_click(int b
, int d
)
1364 if (b
< 0 && d
== 1)
1367 return goto_state(&st_play
);
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
);
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;
1397 menu_text(0, 0, y
, c_blue
, c_green
, "GO!", TXT_LRG
);
1398 menu_item(0, 0, y
, w
, h
);
1401 audio_play(AUD_GO
, 1.f
);
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)
1422 static void play_paint(double dy
)
1424 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1429 if (time_state() < 1.0)
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;
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;
1453 double_put(record_fp
, &at
);
1454 game_put(record_fp
);
1460 static int play_point(int x
, int y
, int dx
, int dy
)
1462 game_set_pos(dx
, dy
);
1466 static int play_click(int b
, int d
)
1468 view_rotate
= d
? b
: 0;
1472 static int play_keybd(int c
)
1474 if (c
== SDLK_ESCAPE
)
1475 goto_state(&st_over
);
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
);
1486 static int play_buttn(int b
, int d
)
1488 if (config_button_r(b
))
1495 if (config_button_l(b
))
1502 if (config_button_X(b
) && d
== 1)
1503 return goto_state(&st_over
);
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;
1519 menu_text(0, 0, y
, c_blue
, c_green
, "Demo", TXT_LRG
);
1520 menu_item(0, 0, y
, w
, h
);
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
);
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
);
1550 static void demo_leave(void)
1560 static void demo_paint(double dy
)
1562 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1567 if (time_state() < 1.0)
1571 static int demo_timer(double dt
)
1573 double g
[3] = { 0.0, -9.8, 0.0 };
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. */
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
);
1604 static int demo_keybd(int c
)
1606 if (c
== SDLK_ESCAPE
)
1607 goto_state(&st_omed
);
1611 static int demo_buttn(int b
, int d
)
1613 if (config_button_X(b
) && d
== 1)
1614 return goto_state(&st_omed
);
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)
1646 audio_music_play("bgm/inter.ogg");
1649 static void goal_paint(double dy
)
1651 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1656 static int goal_click(int b
, int d
)
1658 if (b
<= 0 && d
== 1)
1661 goto_state(&st_score
);
1665 goto_state(&st_level
);
1667 goto_state(&st_done
);
1673 static int goal_keybd(int c
)
1675 if (c
== SDLK_ESCAPE
)
1676 goto_state(&st_over
);
1680 static int goal_timer(double dt
)
1682 double g
[3] = { 0.0, 9.8, 0.0 };
1685 if (time_state() < 1.0)
1687 game_step(g
, dt
, 0);
1691 double_put(record_fp
, &t
);
1692 game_put(record_fp
);
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
);
1705 /*---------------------------------------------------------------------------*/
1707 static int score_action(int i
)
1709 int w
, h
, l
= (int) strlen(player
);
1716 goto_state(&st_level
);
1718 goto_state(&st_done
);
1724 /* Backspace selected */
1731 /* Letter selected */
1735 player
[l
+ 0] = i
+ 'A' - 1;
1740 text_size("M", TXT_MED
, &w
, &h
);
1741 menu_text(0, 0, h
& (~3), c_yellow
, c_white
, player
, TXT_MED
);
1746 static void score_enter(void)
1752 text_size("M", TXT_SML
, &sw
, &sh
);
1753 text_size("M", TXT_MED
, &mw
, &mh
);
1754 text_size("M", TXT_LRG
, &lw
, &lh
);
1758 menu_init(34, 32, 28);
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
++)
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
);
1876 static void score_paint(double dy
)
1878 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1883 static int score_point(int x
, int y
, int dx
, int dy
)
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
);
1901 static int score_stick(int a
, int v
)
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
);
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;
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)
1938 audio_music_play("bgm/inter.ogg");
1941 static void fall_paint(double dy
)
1943 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1949 static int fall_click(int b
, int d
)
1951 if (b
<= 0 && d
== 1)
1954 goto_state(&st_level
);
1956 goto_state(&st_over
);
1961 static int fall_keybd(int c
)
1963 if (c
== SDLK_ESCAPE
)
1964 goto_state(&st_over
);
1968 static int fall_timer(double dt
)
1970 double g
[3] = { 0.0, -9.8, 0.0 };
1973 if (time_state() < 2.0)
1975 game_step(g
, dt
, 0);
1979 double_put(record_fp
, &t
);
1980 game_put(record_fp
);
1984 return fall_click(0, 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
);
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;
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)
2020 audio_music_play("bgm/inter.ogg");
2023 static void time_paint(double dy
)
2025 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
2031 static int time_click(int b
, int d
)
2033 if (b
<= 0 && d
== 1)
2036 goto_state(&st_level
);
2038 goto_state(&st_over
);
2043 static int time_timer(double dt
)
2045 double g
[3] = { 0.0, -9.8, 0.0 };
2048 if (time_state() < 2.0)
2050 game_step(g
, dt
, 0);
2054 double_put(record_fp
, &t
);
2055 game_put(record_fp
);
2059 return time_click(0, 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
);
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;
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)
2093 static void omed_paint(double dy
)
2095 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
);
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;
2131 menu_text(0, 0, y
, c_black
, c_red
, "GAME OVER", TXT_LRG
);
2132 menu_item(0, 0, y
, w
, h
);
2135 audio_play(AUD_OVER
, 1.f
);
2138 static void over_leave(void)
2149 static void over_paint(double dy
)
2151 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
);
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)
2189 text_size(STR_DONE
, TXT_LRG
, &lw
, &lh
);
2190 text_size(STR_MORE
, TXT_SML
, &sw
, &sh
);
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)
2212 static void done_paint(double dy
)
2214 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
);
2241 /*---------------------------------------------------------------------------*/
2243 struct state st_null
= {
2255 struct state st_title
= {
2267 struct state st_help
= {
2279 struct state st_set
= {
2291 struct state st_start
= {
2303 struct state st_conf
= {
2315 struct state st_level
= {
2327 struct state st_poser
= {
2339 struct state st_two
= {
2351 struct state st_one
= {
2363 struct state st_play
= {
2375 struct state st_demo
= {
2387 struct state st_goal
= {
2399 struct state st_score
= {
2411 struct state st_fall
= {
2423 struct state st_time
= {
2435 struct state st_omed
= {
2447 struct state st_over
= {
2459 struct state st_done
= {