Import from neverball-1.3.1.tar.gz
[neverball-archive.git] / putt / state.c
blob78b9be4d48abbf0648aac7085eab29f7f3086f9d
1 /*
2 * Copyright (C) 2003 Robert Kooima
4 * NEVERPUTT 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 "vec3.h"
24 #include "geom.h"
25 #include "game.h"
26 #include "menu.h"
27 #include "text.h"
28 #include "solid.h"
29 #include "state.h"
30 #include "back.h"
31 #include "hole.h"
32 #include "image.h"
33 #include "audio.h"
34 #include "config.h"
36 /*---------------------------------------------------------------------------*/
38 static float state_time = 0.f;
39 static struct state *state = &st_null;
41 float time_state(void)
43 return state_time;
46 int goto_state(struct state *st)
48 if (state && state->leave)
49 state->leave();
51 state = st;
52 state_time = 0;
54 if (state && state->enter)
55 state->enter();
57 return 1;
60 /*---------------------------------------------------------------------------*/
62 void st_paint(void)
64 glClearColor(0.0f, 0.8f, 1.0f, 1.0f);
65 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
66 if (state && state->paint) state->paint();
69 int st_timer(float t)
71 state_time += t;
72 return (state && state->timer) ? state->timer(t) : 1;
75 int st_point(int x, int y, int dx, int dy)
77 return (state && state->point) ? state->point(x, y, dx, dy) : 1;
80 int st_click(int b, int d)
82 return (state && state->click) ? state->click(b, d) : 1;
85 int st_keybd(int c)
87 return (state && state->keybd) ? state->keybd(c) : 1;
90 /*---------------------------------------------------------------------------*/
92 static void score_card(const char *title,
93 const GLfloat *t0,
94 const GLfloat *t1)
96 const GLfloat *c0 = c_yellow;
97 const GLfloat *c1 = c_white;
98 const GLfloat *c2 = c_red;
99 const GLfloat *c3 = c_white;
101 int w, h, i, k = 0;
103 text_size("0", TXT_SML, &w, &h);
104 w = 3 * h / 2;
106 menu_item(0, 0, +(14 * h) / 2, 12 * w - 4, 2 * h);
107 menu_item(1, 0, +(5 * h) / 2, 12 * w - 4, 6 * h + 8);
108 menu_item(2, 0, -(9 * h) / 2, 12 * w - 4, 6 * h + 8);
109 menu_item(3, +7 * w, -(9 * h) / 2, 2 * w - 4, 6 * h + 8);
111 menu_text(k++, 0, +7*h, t0, t1, title, TXT_MED);
113 menu_text(k++, -4*w, +5*h, c0, c2, "01", TXT_SML);
114 menu_text(k++, -3*w, +5*h, c0, c2, "02", TXT_SML);
115 menu_text(k++, -2*w, +5*h, c0, c2, "03", TXT_SML);
116 menu_text(k++, -1*w, +5*h, c0, c2, "04", TXT_SML);
117 menu_text(k++, 0*w, +5*h, c0, c2, "05", TXT_SML);
118 menu_text(k++, +1*w, +5*h, c0, c2, "06", TXT_SML);
119 menu_text(k++, +2*w, +5*h, c0, c2, "07", TXT_SML);
120 menu_text(k++, +3*w, +5*h, c0, c2, "08", TXT_SML);
121 menu_text(k++, +4*w, +5*h, c0, c2, "09", TXT_SML);
122 menu_text(k++, +5*w, +5*h, c0, c2, "Out", TXT_SML);
124 for (i = 0; i <= 4; i++)
126 c3 = c_play[i];
128 menu_text(k++, -5*w, (+4-i)*h, c3, c1, hole_player(i), TXT_SML);
129 menu_text(k++, -4*w, (+4-i)*h, c3, c1, hole_score(1, i), TXT_SML);
130 menu_text(k++, -3*w, (+4-i)*h, c3, c1, hole_score(2, i), TXT_SML);
131 menu_text(k++, -2*w, (+4-i)*h, c3, c1, hole_score(3, i), TXT_SML);
132 menu_text(k++, -1*w, (+4-i)*h, c3, c1, hole_score(4, i), TXT_SML);
133 menu_text(k++, 0*w, (+4-i)*h, c3, c1, hole_score(5, i), TXT_SML);
134 menu_text(k++, +1*w, (+4-i)*h, c3, c1, hole_score(6, i), TXT_SML);
135 menu_text(k++, +2*w, (+4-i)*h, c3, c1, hole_score(7, i), TXT_SML);
136 menu_text(k++, +3*w, (+4-i)*h, c3, c1, hole_score(8, i), TXT_SML);
137 menu_text(k++, +4*w, (+4-i)*h, c3, c1, hole_score(9, i), TXT_SML);
138 menu_text(k++, +5*w, (+4-i)*h, c3, c1, hole_out(i), TXT_SML);
141 menu_text(k++, -4*w, -2*h, c0, c2, "10", TXT_SML);
142 menu_text(k++, -3*w, -2*h, c0, c2, "11", TXT_SML);
143 menu_text(k++, -2*w, -2*h, c0, c2, "12", TXT_SML);
144 menu_text(k++, -1*w, -2*h, c0, c2, "13", TXT_SML);
145 menu_text(k++, 0*w, -2*h, c0, c2, "14", TXT_SML);
146 menu_text(k++, +1*w, -2*h, c0, c2, "15", TXT_SML);
147 menu_text(k++, +2*w, -2*h, c0, c2, "16", TXT_SML);
148 menu_text(k++, +3*w, -2*h, c0, c2, "17", TXT_SML);
149 menu_text(k++, +4*w, -2*h, c0, c2, "18", TXT_SML);
150 menu_text(k++, +5*w, -2*h, c0, c2, "In", TXT_SML);
151 menu_text(k++, +7*w, -2*h, c0, c2, "Tot", TXT_SML);
153 for (i = 0; i <= 4; i++)
155 c3 = c_play[i];
157 menu_text(k++, -5*w, (-3-i)*h, c3, c1, hole_player(i), TXT_SML);
158 menu_text(k++, -4*w, (-3-i)*h, c3, c1, hole_score(10, i), TXT_SML);
159 menu_text(k++, -3*w, (-3-i)*h, c3, c1, hole_score(11, i), TXT_SML);
160 menu_text(k++, -2*w, (-3-i)*h, c3, c1, hole_score(12, i), TXT_SML);
161 menu_text(k++, -1*w, (-3-i)*h, c3, c1, hole_score(13, i), TXT_SML);
162 menu_text(k++, 0*w, (-3-i)*h, c3, c1, hole_score(14, i), TXT_SML);
163 menu_text(k++, +1*w, (-3-i)*h, c3, c1, hole_score(15, i), TXT_SML);
164 menu_text(k++, +2*w, (-3-i)*h, c3, c1, hole_score(16, i), TXT_SML);
165 menu_text(k++, +3*w, (-3-i)*h, c3, c1, hole_score(17, i), TXT_SML);
166 menu_text(k++, +4*w, (-3-i)*h, c3, c1, hole_score(18, i), TXT_SML);
167 menu_text(k++, +5*w, (-3-i)*h, c3, c1, hole_in(i), TXT_SML);
168 menu_text(k++, +7*w, (-3-i)*h, c3, c1, hole_tot(i), TXT_SML);
173 /*---------------------------------------------------------------------------*/
175 static void null_enter(void)
177 hud_free();
178 swch_free();
179 jump_free();
180 flag_free();
181 mark_free();
182 ball_free();
183 text_free();
184 shad_free();
187 static void null_leave(void)
189 glext_init();
190 shad_init();
191 text_init(config_get_d(CONFIG_HEIGHT));
192 ball_init(config_get_d(CONFIG_GEOMETRY));
193 mark_init(config_get_d(CONFIG_GEOMETRY));
194 flag_init(config_get_d(CONFIG_GEOMETRY));
195 jump_init(config_get_d(CONFIG_GEOMETRY));
196 swch_init(config_get_d(CONFIG_GEOMETRY));
197 hud_init();
200 /*---------------------------------------------------------------------------*/
202 #define TITLE_PLAY 1
203 #define TITLE_CONF 2
204 #define TITLE_EXIT 3
206 #define STR_TITLE " Neverputt "
207 #define STR_PLAY " Play "
208 #define STR_CONF " Options "
209 #define STR_EXIT " Exit "
211 static int title_action(int i)
213 switch (i)
215 case TITLE_PLAY: audio_play(AUD_MENU, 1.f); goto_state(&st_party); break;
216 case TITLE_CONF: audio_play(AUD_MENU, 1.f); goto_state(&st_conf); break;
217 case TITLE_EXIT: return 0;
219 return 1;
222 static void title_enter(void)
224 int lw, lh, lm;
225 int mw, mh;
227 text_size(STR_TITLE, TXT_LRG, &lw, &lh);
228 text_size(STR_CONF, TXT_MED, &mw, &mh);
230 lm = lh / 2;
232 menu_init(4, 4, TITLE_PLAY);
234 menu_text(0, 0, mh + lm, c_yellow, c_red, STR_TITLE, TXT_LRG);
235 menu_text(TITLE_PLAY, 0, -0 * mh, c_white, c_white, STR_PLAY, TXT_MED);
236 menu_text(TITLE_CONF, 0, -1 * mh, c_white, c_white, STR_CONF, TXT_MED);
237 menu_text(TITLE_EXIT, 0, -2 * mh, c_white, c_white, STR_EXIT, TXT_MED);
239 menu_item(0, 0, mh + lm, lw, lh);
240 menu_item(TITLE_PLAY, 0, -0 * mh, mw, mh);
241 menu_item(TITLE_CONF, 0, -1 * mh, mw, mh);
242 menu_item(TITLE_EXIT, 0, -2 * mh, mw, mh);
244 menu_stat(0, -1);
245 menu_stat(TITLE_PLAY, +1);
246 menu_stat(TITLE_CONF, 0);
247 menu_stat(TITLE_EXIT, 0);
249 hole_init();
250 hole_goto(rand() % curr_count(), 1);
253 static void title_leave(void)
255 hole_free();
256 menu_free();
259 static void title_paint(void)
261 game_draw(0);
262 menu_paint();
265 static int title_timer(float dt)
267 float g[3] = { 0.f, 0.f, 0.f };
269 game_step(g, dt);
270 game_set_fly(fcosf(time_state() / 10.f));
272 return 1;
275 static int title_point(int x, int y, int dx, int dy)
277 menu_point(x, y);
278 return 1;
281 static int title_click(int b, int d)
283 return (b < 0 && d == 1) ? title_action(menu_click()) : 1;
286 static int title_keybd(int c)
288 return (c == SDLK_ESCAPE) ? 0 : 1;
291 /*---------------------------------------------------------------------------*/
293 #define CONF_FULL 0
294 #define CONF_WIN 1
295 #define CONF_16x12 2
296 #define CONF_12x10 3
297 #define CONF_10x7 4
298 #define CONF_8x6 5
299 #define CONF_6x4 6
300 #define CONF_TEXHI 7
301 #define CONF_TEXLO 8
302 #define CONF_GEOHI 9
303 #define CONF_GEOLO 10
304 #define CONF_AUDHI 11
305 #define CONF_AUDLO 12
306 #define CONF_SNDDN 13
307 #define CONF_SNDUP 14
308 #define CONF_MUSDN 15
309 #define CONF_MUSUP 16
310 #define CONF_BACK 17
312 static int conf_action(int i)
314 int f = config_get_d(CONFIG_FULLSCREEN);
315 int w = config_get_d(CONFIG_WIDTH);
316 int h = config_get_d(CONFIG_HEIGHT);
317 int s = config_get_d(CONFIG_SOUND_VOLUME);
318 int m = config_get_d(CONFIG_MUSIC_VOLUME);
319 int r = 1;
320 int w2;
321 char str[8];
323 text_size("MMMMMMMMM", TXT_SML, &w, &h);
324 w2 = w / 2;
326 switch (i)
328 case CONF_FULL:
329 goto_state(&st_null);
330 r = config_mode(1, w, h);
331 goto_state(&st_conf);
332 break;
334 case CONF_WIN:
335 goto_state(&st_null);
336 r = config_mode(0, w, h);
337 goto_state(&st_conf);
338 break;
340 case CONF_16x12:
341 goto_state(&st_null);
342 r = config_mode(f, 1600, 1200);
343 goto_state(&st_conf);
344 break;
346 case CONF_12x10:
347 goto_state(&st_null);
348 r = config_mode(f, 1280, 1024);
349 goto_state(&st_conf);
350 break;
352 case CONF_10x7:
353 goto_state(&st_null);
354 r = config_mode(f, 1024, 768);
355 goto_state(&st_conf);
356 break;
358 case CONF_8x6:
359 goto_state(&st_null);
360 r = config_mode(f, 800, 600);
361 goto_state(&st_conf);
362 break;
364 case CONF_6x4:
365 goto_state(&st_null);
366 r = config_mode(f, 640, 480);
367 goto_state(&st_conf);
368 break;
370 case CONF_TEXHI:
371 goto_state(&st_null);
372 config_set_d(CONFIG_TEXTURES, 1);
373 goto_state(&st_conf);
374 break;
376 case CONF_TEXLO:
377 goto_state(&st_null);
378 config_set_d(CONFIG_TEXTURES, 2);
379 goto_state(&st_conf);
380 break;
382 case CONF_GEOHI:
383 goto_state(&st_null);
384 config_set_d(CONFIG_GEOMETRY, 1);
385 goto_state(&st_conf);
386 break;
388 case CONF_GEOLO:
389 goto_state(&st_null);
390 config_set_d(CONFIG_GEOMETRY, 0);
391 goto_state(&st_conf);
392 break;
394 case CONF_AUDHI:
395 audio_free();
396 config_set_d(CONFIG_AUDIO_RATE, 44100);
397 config_set_d(CONFIG_AUDIO_BUFF, AUDIO_BUFF_HI);
398 audio_init();
399 goto_state(&st_conf);
400 break;
402 case CONF_AUDLO:
403 audio_free();
404 config_set_d(CONFIG_AUDIO_RATE, 22050);
405 config_set_d(CONFIG_AUDIO_BUFF, AUDIO_BUFF_LO);
406 audio_init();
407 goto_state(&st_conf);
408 break;
410 case CONF_SNDDN:
411 config_set_d(CONFIG_SOUND_VOLUME, s - 1);
412 sprintf(str, "%02d", s - 1);
413 audio_volume(s - 1, m);
414 menu_text(33, +w2, -3 * h, c_yellow, c_red, str, TXT_SML);
415 audio_play(AUD_BUMP, 1.f);
416 break;
418 case CONF_SNDUP:
419 config_set_d(CONFIG_SOUND_VOLUME, s + 1);
420 sprintf(str, "%02d", s + 1);
421 audio_volume(s + 1, m);
422 menu_text(33, +w2, -3 * h, c_yellow, c_red, str, TXT_SML);
423 audio_play(AUD_BUMP, 1.f);
424 break;
426 case CONF_MUSDN:
427 config_set_d(CONFIG_MUSIC_VOLUME, m - 1);
428 sprintf(str, "%02d", m - 1);
429 audio_volume(s, m - 1);
430 menu_text(34, +w2, -4 * h, c_yellow, c_red, str, TXT_SML);
431 break;
433 case CONF_MUSUP:
434 config_set_d(CONFIG_MUSIC_VOLUME, m + 1);
435 sprintf(str, "%02d", m + 1);
436 audio_volume(s, m + 1);
437 menu_text(34, +w2, -4 * h, c_yellow, c_red, str, TXT_SML);
438 break;
440 case CONF_BACK:
441 goto_state(&st_title);
442 break;
444 return r;
447 static void conf_enter(void)
449 static int value = CONF_FULL;
450 char snds[16];
451 char muss[16];
453 int w, w2, w4;
454 int h, h2;
456 /* Compute menu sizes from font sizes */
458 text_size("MMMMMMMMM", TXT_SML, &w, &h);
459 w2 = w / 2;
460 w4 = w / 4;
461 h2 = h / 2;
463 sprintf(snds, "%02d", config_get_d(CONFIG_SOUND_VOLUME));
464 sprintf(muss, "%02d", config_get_d(CONFIG_MUSIC_VOLUME));
466 menu_init(36, 25, value);
468 /* Text elements */
470 menu_text(0, -w2, +h2 + 4 * h, c_yellow, c_red, "Options", TXT_MED);
471 menu_text(1, -w2, +3 * h, c_white, c_white, "Fullscreen", TXT_SML);
472 menu_text(2, -w2, +2 * h, c_white, c_white, "Window", TXT_SML);
473 menu_text(3, +w2 - w4, +5 * h, c_white, c_white, "1600", TXT_SML);
474 menu_text(4, +w2 - w4, +4 * h, c_white, c_white, "1280", TXT_SML);
475 menu_text(5, +w2 - w4, +3 * h, c_white, c_white, "1024", TXT_SML);
476 menu_text(6, +w2 - w4, +2 * h, c_white, c_white, "800", TXT_SML);
477 menu_text(7, +w2 - w4, 1 * h, c_white, c_white, "640", TXT_SML);
478 menu_text(8, +w2, +5 * h, c_white, c_white, "x", TXT_SML);
479 menu_text(9, +w2, +4 * h, c_white, c_white, "x", TXT_SML);
480 menu_text(10, +w2, +3 * h, c_white, c_white, "x", TXT_SML);
481 menu_text(11, +w2, +2 * h, c_white, c_white, "x", TXT_SML);
482 menu_text(12, +w2, 1 * h, c_white, c_white, "x", TXT_SML);
483 menu_text(13, +w2 + w4, +5 * h, c_white, c_white, "1200", TXT_SML);
484 menu_text(14, +w2 + w4, +4 * h, c_white, c_white, "1024", TXT_SML);
485 menu_text(15, +w2 + w4, +3 * h, c_white, c_white, "768", TXT_SML);
486 menu_text(16, +w2 + w4, +2 * h, c_white, c_white, "600", TXT_SML);
487 menu_text(17, +w2 + w4, 1 * h, c_white, c_white, "480", TXT_SML);
488 menu_text(18, -w2, 0 * h, c_yellow, c_red, "Textures", TXT_SML);
489 menu_text(19, -w2, -1 * h, c_yellow, c_red, "Geometry", TXT_SML);
490 menu_text(20, -w2, -2 * h, c_yellow, c_red, "Audio", TXT_SML);
491 menu_text(21, -w2, -3 * h, c_yellow, c_red, "Sound Vol", TXT_SML);
492 menu_text(22, -w2, -4 * h, c_yellow, c_red, "Music Vol", TXT_SML);
493 menu_text(23, +w2 - w4, 0 * h, c_white, c_white, "High", TXT_SML);
494 menu_text(24, +w2 - w4, -1 * h, c_white, c_white, "High", TXT_SML);
495 menu_text(25, +w2 - w4, -2 * h, c_white, c_white, "High", TXT_SML);
496 menu_text(26, +w2 - w4, -3 * h, c_white, c_white, "<", TXT_SML);
497 menu_text(27, +w2 - w4, -4 * h, c_white, c_white, "<", TXT_SML);
498 menu_text(28, +w2 + w4, 0 * h, c_white, c_white, "Low", TXT_SML);
499 menu_text(29, +w2 + w4, -1 * h, c_white, c_white, "Low", TXT_SML);
500 menu_text(30, +w2 + w4, -2 * h, c_white, c_white, "Low", TXT_SML);
501 menu_text(31, +w2 + w4, -3 * h, c_white, c_white, ">", TXT_SML);
502 menu_text(32, +w2 + w4, -4 * h, c_white, c_white, ">", TXT_SML);
503 menu_text(33, +w2, -3 * h, c_yellow, c_red, snds, TXT_SML);
504 menu_text(34, +w2, -4 * h, c_yellow, c_red, muss, TXT_SML);
505 menu_text(35, +w2, -5 * h, c_white, c_white, "Back", TXT_SML);
507 /* Active items */
509 menu_item(CONF_FULL, -w2, +3 * h, w, h);
510 menu_item(CONF_WIN, -w2, +2 * h, w, h);
511 menu_item(CONF_16x12, +w2, +5 * h, w, h);
512 menu_item(CONF_12x10, +w2, +4 * h, w, h);
513 menu_item(CONF_10x7, +w2, +3 * h, w, h);
514 menu_item(CONF_8x6, +w2, +2 * h, w, h);
515 menu_item(CONF_6x4, +w2, +1 * h, w, h);
516 menu_item(CONF_TEXHI, +w2 - w4, 0 * h, w2, h);
517 menu_item(CONF_TEXLO, +w2 + w4, 0 * h, w2, h);
518 menu_item(CONF_GEOHI, +w2 - w4, -1 * h, w2, h);
519 menu_item(CONF_GEOLO, +w2 + w4, -1 * h, w2, h);
520 menu_item(CONF_AUDHI, +w2 - w4, -2 * h, w2, h);
521 menu_item(CONF_AUDLO, +w2 + w4, -2 * h, w2, h);
522 menu_item(CONF_SNDDN, +w2 - w4, -3 * h, w2, h);
523 menu_item(CONF_SNDUP, +w2 + w4, -3 * h, w2, h);
524 menu_item(CONF_MUSDN, +w2 - w4, -4 * h, w2, h);
525 menu_item(CONF_MUSUP, +w2 + w4, -4 * h, w2, h);
526 menu_item(CONF_BACK, +w2, -5 * h, w, h);
528 /* Inactive label padding */
530 menu_item(18, -w2, +5 * h, w, h);
531 menu_item(19, -w2, +4 * h, w, h);
532 menu_item(20, -w2, 0 * h, w, h);
533 menu_item(21, -w2, -1 * h, w, h);
534 menu_item(22, -w2, -2 * h, w, h);
535 menu_item(23, -w2, -3 * h, w, h);
536 menu_item(24, -w2, -4 * h, w, h);
538 /* Item state */
540 menu_stat(CONF_FULL, (config_get_d(CONFIG_FULLSCREEN)) ? 1 : 0);
541 menu_stat(CONF_WIN, (config_get_d(CONFIG_FULLSCREEN)) ? 0 : 1);
542 menu_stat(CONF_16x12, (config_get_d(CONFIG_WIDTH) == 1600) ? 1 : 0);
543 menu_stat(CONF_12x10, (config_get_d(CONFIG_WIDTH) == 1280) ? 1 : 0);
544 menu_stat(CONF_10x7, (config_get_d(CONFIG_WIDTH) == 1024) ? 1 : 0);
545 menu_stat(CONF_8x6, (config_get_d(CONFIG_WIDTH) == 800) ? 1 : 0);
546 menu_stat(CONF_6x4, (config_get_d(CONFIG_WIDTH) == 640) ? 1 : 0);
547 menu_stat(CONF_TEXHI, (config_get_d(CONFIG_TEXTURES) == 1) ? 1 : 0);
548 menu_stat(CONF_TEXLO, (config_get_d(CONFIG_TEXTURES) == 2) ? 1 : 0);
549 menu_stat(CONF_GEOHI, (config_get_d(CONFIG_GEOMETRY) == 1) ? 1 : 0);
550 menu_stat(CONF_GEOLO, (config_get_d(CONFIG_GEOMETRY) == 0) ? 1 : 0);
551 menu_stat(CONF_AUDHI, (config_get_d(CONFIG_AUDIO_RATE) == 44100) ? 1 : 0);
552 menu_stat(CONF_AUDLO, (config_get_d(CONFIG_AUDIO_RATE) == 22050) ? 1 : 0);
553 menu_stat(CONF_SNDDN, 0);
554 menu_stat(CONF_SNDUP, 0);
555 menu_stat(CONF_MUSDN, 0);
556 menu_stat(CONF_MUSUP, 0);
557 menu_stat(CONF_BACK, 0);
559 /* Disable unsupported modes. */
561 if (!SDL_VideoModeOK(1600, 1200, 16, SDL_HWSURFACE))
562 menu_stat(CONF_16x12, -1);
563 if (!SDL_VideoModeOK(1280, 1024, 16, SDL_HWSURFACE))
564 menu_stat(CONF_12x10, -1);
565 if (!SDL_VideoModeOK(1024, 768, 16, SDL_HWSURFACE))
566 menu_stat(CONF_10x7, -1);
567 if (!SDL_VideoModeOK(800, 600, 16, SDL_HWSURFACE))
568 menu_stat(CONF_8x6, -1);
569 if (!SDL_VideoModeOK(640, 480, 16, SDL_HWSURFACE))
570 menu_stat(CONF_8x6, -1);
572 value = -1;
575 static void conf_leave(void)
577 config_save();
578 menu_free();
581 static void conf_paint(void)
583 menu_paint();
586 static int conf_point(int x, int y, int dx, int dy)
588 menu_point(x, y);
589 return 1;
592 static int conf_click(int b, int d)
594 return (b < 0 && d == 1) ? conf_action(menu_click()) : 1;
597 static int conf_keybd(int c)
599 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
602 /*---------------------------------------------------------------------------*/
604 #define PARTY_T 0
605 #define PARTY_1 1
606 #define PARTY_2 2
607 #define PARTY_3 3
608 #define PARTY_4 4
609 #define PARTY_B 5
611 static int party_action(int i)
613 switch (i)
615 case PARTY_1:
616 audio_play(AUD_MENU, 1.f);
617 hole_init();
618 hole_goto(1, 1);
619 goto_state(&st_next);
620 break;
621 case PARTY_2:
622 audio_play(AUD_MENU, 1.f);
623 hole_init();
624 hole_goto(1, 2);
625 goto_state(&st_next);
626 break;
627 case PARTY_3:
628 audio_play(AUD_MENU, 1.f);
629 hole_init();
630 hole_goto(1, 3);
631 goto_state(&st_next);
632 break;
633 case PARTY_4:
634 audio_play(AUD_MENU, 1.f);
635 hole_init();
636 hole_goto(1, 4);
637 goto_state(&st_next);
638 break;
639 case PARTY_B:
640 audio_play(AUD_MENU, 1.f);
641 goto_state(&st_title);
642 break;
644 return 1;
647 static void party_enter(void)
649 int mw, mh;
650 int lw, lh, w = config_get_d(CONFIG_WIDTH) / 2;
652 text_size("0", TXT_MED, &mw, &mh);
653 text_size("0", TXT_LRG, &lw, &lh);
655 menu_init(6, 6, 7);
657 menu_text(PARTY_T, 0, +1 * lh, c_white, c_white, "Players?", TXT_MED);
658 menu_text(PARTY_1, -3 * lw, 0, c_red, c_white, "1", TXT_LRG);
659 menu_text(PARTY_2, -1 * lw, 0, c_green, c_white, "2", TXT_LRG);
660 menu_text(PARTY_3, +1 * lw, 0, c_blue, c_white, "3", TXT_LRG);
661 menu_text(PARTY_4, +3 * lw, 0, c_yellow, c_white, "4", TXT_LRG);
662 menu_text(PARTY_B, 0, -1 * lh, c_yellow, c_red, "Back", TXT_MED);
664 menu_item(PARTY_T, 0, +1 * lh, w, mh);
665 menu_item(PARTY_1, -3 * lw, 0, 2 * lw, lh);
666 menu_item(PARTY_2, -1 * lw, 0, 2 * lw, lh);
667 menu_item(PARTY_3, +1 * lw, 0, 2 * lw, lh);
668 menu_item(PARTY_4, +3 * lw, 0, 2 * lw, lh);
669 menu_item(PARTY_B, 0, -1 * lh, w, mh);
671 menu_stat(PARTY_T, -1);
672 menu_stat(PARTY_1, 0);
673 menu_stat(PARTY_2, 0);
674 menu_stat(PARTY_3, 0);
675 menu_stat(PARTY_4, 0);
676 menu_stat(PARTY_B, 0);
678 audio_music_fade(2.0f);
681 static void party_leave(void)
683 menu_free();
686 static void party_paint(void)
688 menu_paint();
691 static int party_timer(float dt)
693 return 1;
696 static int party_point(int x, int y, int dx, int dy)
698 menu_point(x, y);
699 return 1;
702 static int party_click(int b, int d)
704 return (b < 0 && d == 1) ? party_action(menu_click()) : 1;
707 static int party_keybd(int c)
709 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
712 /*---------------------------------------------------------------------------*/
714 static void next_enter(void)
716 const GLfloat *c0 = c_yellow;
717 const GLfloat *c1 = c_red;
718 const GLfloat *c2 = c_white;
719 const GLfloat *c3 = c_play[curr_player()];
721 char str1[MAXSTR];
722 char str2[MAXSTR];
724 int mw, mh;
725 int sw, sh;
726 int lw, lh;
727 int w, h;
729 text_size("0", TXT_SML, &sw, &sh);
730 text_size("0", TXT_MED, &mw, &mh);
731 text_size("0", TXT_LRG, &lw, &lh);
733 w = config_get_d(CONFIG_WIDTH) / 2;
734 h = -(lh + sh) / 2;
736 sprintf(str1, "Hole %02d", curr_hole());
737 sprintf(str2, "%d", curr_player());
739 menu_init(3, 3, 4);
741 menu_text(0, 0, +mh, c0, c1, str1, TXT_MED);
742 menu_text(1, 0, 0, c3, c2, "Player", TXT_SML);
743 menu_text(2, 0, h, c3, c2, str2, TXT_LRG);
745 menu_item(0, 0, +mh, w, mh);
746 menu_item(1, 0, 0, lw * 2, sh);
747 menu_item(2, 0, h, lw * 2, lh);
749 if (curr_party() > 1)
750 switch (curr_player())
752 case 1: audio_play(AUD_PLAYER1, 1.0f); break;
753 case 2: audio_play(AUD_PLAYER2, 1.0f); break;
754 case 3: audio_play(AUD_PLAYER3, 1.0f); break;
755 case 4: audio_play(AUD_PLAYER4, 1.0f); break;
758 game_set_fly(1.f);
761 static void next_leave(void)
763 menu_free();
766 static void next_paint(void)
768 game_draw(0);
769 menu_paint();
772 static int next_click(int b, int d)
774 return (b < 0 && d == 1) ? goto_state(&st_flyby) : 1;
777 static int next_keybd(int c)
779 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
782 /*---------------------------------------------------------------------------*/
784 static void flyby_enter(void)
788 static void flyby_leave(void)
792 static void flyby_paint(void)
794 game_draw(0);
795 hud_draw();
798 static int flyby_timer(float dt)
800 float t = time_state();
802 if (dt > 0.f && t > 1.f)
803 return goto_state(&st_stroke);
804 else
805 game_set_fly(1.f - t);
807 return 1;
810 static int flyby_click(int b, int d)
812 if (b < 0 && d == 1)
814 game_set_fly(0.f);
815 return goto_state(&st_stroke);
817 return 1;
820 static int flyby_keybd(int c)
822 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
825 /*---------------------------------------------------------------------------*/
827 static void stroke_enter(void)
829 game_clr_mag();
830 config_set_d(CONFIG_CAMERA, 2);
831 SDL_ShowCursor(SDL_DISABLE);
832 SDL_WM_GrabInput(SDL_GRAB_ON);
835 static void stroke_leave(void)
837 SDL_WM_GrabInput(SDL_GRAB_OFF);
838 SDL_ShowCursor(SDL_ENABLE);
839 config_set_d(CONFIG_CAMERA, 0);
842 static void stroke_paint(void)
844 game_draw(0);
845 hud_draw();
848 static int stroke_point(int x, int y, int dx, int dy)
850 game_set_rot(dx);
851 game_set_mag(dy);
852 return 1;
855 static int stroke_timer(float dt)
857 float g[3] = { 0.f, 0.f, 0.f };
859 game_update_view(dt);
860 game_step(g, dt);
861 return 1;
864 static int stroke_click(int b, int d)
866 if (b < 0 && d == 1)
867 return goto_state(&st_roll);
869 return 1;
872 static int stroke_keybd(int c)
874 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
877 /*---------------------------------------------------------------------------*/
879 static void roll_enter(void)
881 game_putt();
884 static void roll_leave(void)
888 static void roll_paint(void)
890 game_draw(0);
891 hud_draw();
894 static int roll_timer(float dt)
896 float g[3] = { 0.0f, -9.8f, 0.0f };
898 switch (game_step(g, dt))
900 case GAME_STOP: goto_state(&st_stop); break;
901 case GAME_GOAL: goto_state(&st_goal); break;
902 case GAME_FALL: goto_state(&st_fall); break;
905 return 1;
908 static int roll_keybd(int c)
910 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
913 /*---------------------------------------------------------------------------*/
915 static void goal_enter(void)
917 hole_goal();
918 menu_init(137, 4, 150);
919 score_card("It's In!", c_green, c_green);
922 static void goal_leave(void)
924 menu_free();
927 static void goal_paint(void)
929 game_draw(0);
930 menu_paint();
933 static int goal_click(int b, int d)
935 if (b < 0 && d == 1)
937 if (hole_next())
938 return goto_state(&st_next);
939 else
940 return goto_state(&st_over);
942 return 1;
945 static int goal_keybd(int c)
947 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
950 /*---------------------------------------------------------------------------*/
952 static void stop_enter(void)
954 hole_stop();
955 menu_init(137, 4, 150);
956 score_card("Score Card", c_white, c_white);
959 static void stop_leave(void)
961 menu_free();
964 static void stop_paint(void)
966 game_draw(0);
967 menu_paint();
970 static int stop_click(int b, int d)
972 if (b < 0 && d == 1)
974 if (hole_next())
975 return goto_state(&st_next);
976 else
977 return goto_state(&st_over);
979 return 1;
982 static int stop_keybd(int c)
984 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
987 /*---------------------------------------------------------------------------*/
989 static void fall_enter(void)
991 hole_fall();
992 menu_init(137, 4, 150);
993 score_card("1 Stroke Penalty", c_black, c_red);
996 static void fall_leave(void)
998 menu_free();
1001 static void fall_paint(void)
1003 game_draw(0);
1004 menu_paint();
1007 static int fall_click(int b, int d)
1009 if (b < 0 && d == 1)
1011 if (hole_next())
1012 return goto_state(&st_next);
1013 else
1014 return goto_state(&st_over);
1016 return 1;
1019 static int fall_keybd(int c)
1021 return (c == SDLK_ESCAPE) ? goto_state(&st_over) : 1;
1024 /*---------------------------------------------------------------------------*/
1026 static void over_enter(void)
1028 audio_music_fade(2.f);
1030 menu_init(137, 4, 150);
1031 score_card("Final Score", c_yellow, c_red);
1034 static void over_leave(void)
1036 audio_music_stop();
1038 menu_free();
1039 hole_free();
1042 static void over_paint(void)
1044 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1045 menu_paint();
1048 static int over_keybd(int c)
1050 return (c == SDLK_ESCAPE) ? goto_state(&st_title) : 1;
1053 static int over_click(int b, int d)
1055 return (b < 0 && d == 1) ? goto_state(&st_title) : 1;
1058 /*---------------------------------------------------------------------------*/
1060 struct state st_null = {
1061 null_enter,
1062 null_leave,
1063 NULL,
1064 NULL,
1065 NULL,
1066 NULL,
1067 NULL,
1070 struct state st_title = {
1071 title_enter,
1072 title_leave,
1073 title_paint,
1074 title_timer,
1075 title_point,
1076 title_click,
1077 title_keybd,
1080 struct state st_conf = {
1081 conf_enter,
1082 conf_leave,
1083 conf_paint,
1084 NULL,
1085 conf_point,
1086 conf_click,
1087 conf_keybd,
1090 struct state st_party = {
1091 party_enter,
1092 party_leave,
1093 party_paint,
1094 party_timer,
1095 party_point,
1096 party_click,
1097 party_keybd,
1100 struct state st_next = {
1101 next_enter,
1102 next_leave,
1103 next_paint,
1104 NULL,
1105 NULL,
1106 next_click,
1107 next_keybd,
1110 struct state st_flyby = {
1111 flyby_enter,
1112 flyby_leave,
1113 flyby_paint,
1114 flyby_timer,
1115 NULL,
1116 flyby_click,
1117 flyby_keybd,
1120 struct state st_stroke = {
1121 stroke_enter,
1122 stroke_leave,
1123 stroke_paint,
1124 stroke_timer,
1125 stroke_point,
1126 stroke_click,
1127 stroke_keybd,
1130 struct state st_roll = {
1131 roll_enter,
1132 roll_leave,
1133 roll_paint,
1134 roll_timer,
1135 NULL,
1136 NULL,
1137 roll_keybd,
1140 struct state st_goal = {
1141 goal_enter,
1142 goal_leave,
1143 goal_paint,
1144 NULL,
1145 NULL,
1146 goal_click,
1147 goal_keybd,
1150 struct state st_stop = {
1151 stop_enter,
1152 stop_leave,
1153 stop_paint,
1154 NULL,
1155 NULL,
1156 stop_click,
1157 stop_keybd,
1160 struct state st_fall = {
1161 fall_enter,
1162 fall_leave,
1163 fall_paint,
1164 NULL,
1165 NULL,
1166 fall_click,
1167 fall_keybd,
1170 struct state st_over = {
1171 over_enter,
1172 over_leave,
1173 over_paint,
1174 NULL,
1175 NULL,
1176 over_click,
1177 over_keybd,