factorization of many copy/pasted functions
[neverball] / ball / st_title.c
1 /*   
2  * Copyright (C) 2003 Robert Kooima
3  *
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.
8  *
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.
13  */
14
15 #include "gui.h"
16 #include "vec3.h"
17 #include "back.h"
18 #include "demo.h"
19 #include "game.h"
20 #include "audio.h"
21 #include "config.h"
22 #include "st_shared.h"
23
24 #include "st_title.h"
25 #include "st_demo.h"
26 #include "st_conf.h"
27 #include "st_set.h"
28 #include "st_name.h"
29
30 /*---------------------------------------------------------------------------*/
31
32 static float real_time = 0.0f;
33 static float demo_time = 0.0f;
34 static int   mode      = 0;
35
36 #define TITLE_PLAY 1
37 #define TITLE_HELP 2
38 #define TITLE_DEMO 3
39 #define TITLE_CONF 4
40 #define TITLE_EXIT 5
41
42 static int title_action(int i)
43 {
44     char player[MAXNAM];
45     audio_play(AUD_MENU, 1.0f);
46
47     switch (i)
48     {
49     case TITLE_PLAY: 
50         config_get_s(CONFIG_PLAYER, player, MAXNAM);
51         if (player[0] == '\0')
52             return goto_name(&st_set, &st_title);
53         else
54             return goto_state(&st_set);
55     case TITLE_HELP: return goto_state(&st_help);
56     case TITLE_DEMO: return goto_state(&st_demo);
57     case TITLE_CONF: return goto_state(&st_conf);
58     case TITLE_EXIT: return 0;
59     }
60     return 1;
61 }
62
63 static int title_enter(void)
64 {
65     int id, jd, kd;
66
67     /* Build the title GUI. */
68
69     if ((id = gui_vstack(0)))
70     {
71         gui_label(id, _("Neverball"), GUI_LRG, GUI_ALL, 0, 0);
72         gui_space(id);
73
74         if ((jd = gui_harray(id)))
75         {
76             gui_filler(jd);
77
78             if ((kd = gui_varray(jd)))
79             {
80                 gui_start(kd, sgettext("menu^Play"),    GUI_MED, TITLE_PLAY, 1);
81                 gui_state(kd, sgettext("menu^Replay"),  GUI_MED, TITLE_DEMO, 0);
82                 gui_state(kd, sgettext("menu^Help"),    GUI_MED, TITLE_HELP, 0);
83                 gui_state(kd, sgettext("menu^Options"), GUI_MED, TITLE_CONF, 0);
84                 gui_state(kd, sgettext("menu^Exit"),    GUI_MED, TITLE_EXIT, 0);
85             }
86
87             gui_filler(jd);
88         }
89         gui_layout(id, 0, 0);
90     }
91
92     /* Start the title screen music. */
93
94     audio_music_fade_to(0.5f, "bgm/title.ogg");
95
96     /* Initialize the first level of the first set for display. */
97
98     game_init("map-rlk/title.sol", "map-back/jupiter.sol", "png/space.png", 0, 0);
99
100     real_time = 0.0f;
101     demo_time = 0.0f;
102     mode = 0;
103
104     return id;
105 }
106
107 static void title_leave(int id)
108 {
109     demo_replay_stop(0);
110     gui_delete(id);
111 }
112
113 static void title_timer(int id, float dt)
114 {
115     static const char *demo = NULL;
116     float t;
117
118     real_time += dt;
119
120     switch (mode)
121     {
122     case 0: /* Mode 0: Pan across title level. */
123
124         if (real_time <= 20.0f)
125             game_set_fly(fcosf(V_PI * real_time / 20.0f));
126         else
127         {
128             game_fade(+1.0f);
129             real_time = 0.0f;
130             mode = 1;
131         }
132         break;
133
134     case 1: /* Mode 1: Fade out.  Load demo level. */
135
136         if (real_time > 1.0f)
137         {
138             if ((demo = demo_pick()))
139             {
140                 demo_replay_init(demo, NULL, NULL, NULL, NULL);
141                 demo_time = 0.0f;
142                 real_time = 0.0f;
143                 mode = 2;
144             }
145             else
146             {
147                 game_fade(-1.0f);
148                 real_time = 0.0f;
149                 mode = 0;
150             }
151         }
152         break;
153
154     case 2: /* Mode 2: Run demo. */
155
156         while (demo_time < real_time)
157             if (demo_replay_step(&t))
158                 demo_time += t;
159             else
160             { 
161                 demo_replay_stop(0);
162                 game_fade(+1.0f);
163                 real_time = 0.0f;
164                 mode = 3;
165             }
166         break;
167
168     case 3: /* Mode 3: Fade out.  Load title level. */
169
170         if (real_time > 1.0f)
171         {
172             game_init("map-rlk/title.sol", "map-back/jupiter.sol", "png/space.png", 0, 0);
173             real_time = 0.0f;
174             mode = 0;
175         }
176         break;
177     }
178
179     gui_timer(id, dt);
180     audio_timer(dt);
181     game_step_fade(dt);
182 }
183
184 static int title_keybd(int c, int d)
185 {
186     if (d && c == SDLK_c && ALLOW_CHEAT)
187         config_tgl_d(CONFIG_CHEAT);
188     return 1; 
189 }
190         
191 static int title_buttn(int b, int d)
192 {
193     if (d)
194     {
195         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
196             return title_action(gui_token(gui_click()));
197         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
198             return 0;
199     }
200     return 1;
201 }
202
203 /*---------------------------------------------------------------------------*/
204
205 static int help_enter(void)
206 {
207     const char *s0 =
208         _("Move the mouse or joystick to tilt the floor\\"
209         "causing the ball to roll.  Roll over coins to\\"
210         "collect them.  Collect coins to unlock the goal\\"
211         "and finish the level.  Earn an extra ball for\\"
212         "each 100 coins collected.\\");
213
214     const char *s4 = _("Left and right mouse buttons rotate the view.");
215     const char *s5 = _("Hold Shift for faster view rotation.");
216     const char *s6 = _("Pause / Release Pointer");
217     const char *s7 = _("Exit / Cancel Menu");
218     const char *s8 = _("Chase View");
219     const char *s9 = _("Lazy View");
220     const char *sA = _("Manual View");
221     const char *sB = _("Comments?  Problems?  robert.kooima@gmail.com");
222
223     const char *k0 = _("Spacebar");
224     const char *k1 = _("Escape");
225     const char *k2 = SDL_GetKeyName(config_get_d(CONFIG_KEY_CAMERA_1));
226     const char *k3 = SDL_GetKeyName(config_get_d(CONFIG_KEY_CAMERA_2));
227     const char *k4 = SDL_GetKeyName(config_get_d(CONFIG_KEY_CAMERA_3));
228
229     int id, jd;
230
231     if ((id = gui_vstack(0)))
232     {
233         gui_multi(id, s0, GUI_SML, GUI_ALL, gui_wht, gui_wht);
234         gui_space(id);
235
236         if ((jd = gui_harray(id)))
237         {
238             gui_label(jd, s6, GUI_SML, GUI_NE, gui_wht, gui_wht);
239             gui_label(jd, k0, GUI_SML, GUI_NW, gui_yel, gui_yel);
240         }
241         if ((jd = gui_harray(id)))
242         {
243             gui_label(jd, s7, GUI_SML, 0,      gui_wht, gui_wht);
244             gui_label(jd, k1, GUI_SML, 0,      gui_yel, gui_yel);
245         }
246         if ((jd = gui_harray(id)))
247         {
248             gui_label(jd, s8, GUI_SML, 0,      gui_wht, gui_wht);
249             gui_label(jd, k2, GUI_SML, 0,      gui_yel, gui_yel);
250         }
251         if ((jd = gui_harray(id)))
252         {
253             gui_label(jd, s9, GUI_SML, 0,      gui_wht, gui_wht);
254             gui_label(jd, k3, GUI_SML, 0,      gui_yel, gui_yel);
255         }
256         if ((jd = gui_harray(id)))
257         {
258             gui_label(jd, sA, GUI_SML, GUI_SE, gui_wht, gui_wht);
259             gui_label(jd, k4, GUI_SML, GUI_SW, gui_yel, gui_yel);
260         }
261
262         gui_space(id);
263         gui_label(id, s4, GUI_SML, GUI_TOP, gui_wht, gui_wht);
264         gui_label(id, s5, GUI_SML, GUI_BOT, gui_wht, gui_wht);
265         gui_space(id);
266         gui_label(id, sB, GUI_SML, GUI_ALL, gui_wht, gui_wht);
267
268         gui_layout(id, 0, 0);
269     }
270     return id;
271 }
272
273 static void help_paint(int id, float st)
274 {
275     game_draw(0, st);
276     config_pop_matrix();
277     gui_paint(id);
278 }
279
280 static int help_click(int b, int d)
281 {
282     return d ? goto_state(&st_title) : 1;
283 }
284
285 static int help_keybd(int c, int d)
286 {
287     return d ? goto_state(&st_title) : 1;
288 }
289
290 static int help_buttn(int b, int d)
291 {
292     return d ? goto_state(&st_title) : 1;
293 }
294
295 /*---------------------------------------------------------------------------*/
296
297 struct state st_title = {
298     title_enter,
299     title_leave,
300     shared_paint,
301     title_timer,
302     shared_point,
303     shared_stick,
304     shared_click,
305     title_keybd,
306     title_buttn,
307     1, 0
308 };
309
310 struct state st_help = {
311     help_enter,
312     shared_leave,
313     help_paint,
314     shared_timer,
315     NULL,
316     NULL,
317     help_click,
318     help_keybd,
319     help_buttn,
320     1, 0
321 };