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 "audio.h"
17 #include "config.h"
18 #include "demo.h"
19 #include "video.h"
20
21 #include "game_common.h"
22 #include "game_server.h"
23 #include "game_client.h"
24
25 #include "st_title.h"
26 #include "st_help.h"
27 #include "st_shared.h"
28
29 /*---------------------------------------------------------------------------*/
30
31 enum
32 {
33 HELP_PAGE = GUI_LAST,
34 HELP_DEMO
35 };
36
37 enum
38 {
39 PAGE_RULES,
40 PAGE_CONTROLS,
41 PAGE_MODES,
42 PAGE_TRICKS
43 };
44
45 static const char demos[][16] = {
46 "gui/demo1.nbr",
47 "gui/demo2.nbr"
48 };
49
50 static int page = PAGE_RULES;
51
52 /*---------------------------------------------------------------------------*/
53
help_action(int tok,int val)54 static int help_action(int tok, int val)
55 {
56 audio_play(AUD_MENU, 1.0f);
57
58 switch (tok)
59 {
60 case GUI_BACK:
61 page = PAGE_RULES;
62 return goto_state(&st_title);
63
64 case HELP_DEMO:
65 if (demo_replay_init(demos[val], NULL, NULL, NULL, NULL, NULL))
66 return goto_state(&st_help_demo);
67 break;
68
69 case HELP_PAGE:
70 page = val;
71 return goto_state(&st_help);
72
73 }
74 return 1;
75 }
76
77 /* -------------------------------------------------------------------------- */
78
help_button(int id,const char * text,int token,int value)79 static int help_button(int id, const char *text, int token, int value)
80 {
81 int jd = gui_state(id, text, GUI_SML, token, value);
82
83 /* Hilight current page. */
84
85 if (token == HELP_PAGE && value == page)
86 {
87 gui_set_hilite(jd, 1);
88 gui_focus(jd);
89 }
90
91 return jd;
92 }
93
help_menu(int id)94 static int help_menu(int id)
95 {
96 int jd;
97
98 gui_space(id);
99
100 if ((jd = gui_harray(id)))
101 {
102 help_button(jd, _("Tricks"), HELP_PAGE, PAGE_TRICKS);
103 help_button(jd, _("Modes"), HELP_PAGE, PAGE_MODES);
104 help_button(jd, _("Controls"), HELP_PAGE, PAGE_CONTROLS);
105 help_button(jd, _("Rules"), HELP_PAGE, PAGE_RULES);
106 help_button(jd, _("Back"), GUI_BACK, 0);
107 }
108 return jd;
109 }
110
111 /* -------------------------------------------------------------------------- */
112
page_rules(int id)113 static int page_rules(int id)
114 {
115 const char *s0 = _(
116 "Move the mouse or joystick\\"
117 "or use keyboard arrows to\\"
118 "tilt the floor causing the\\"
119 "ball to roll.\\");
120 const char *s1 = _(
121 "Roll over coins to collect\\"
122 "them. Collect coins to\\"
123 "unlock the goal and finish\\"
124 "the level.\\");
125
126 int w = video.device_w;
127 int h = video.device_h;
128
129 int jd, kd, ld;
130
131 if ((jd = gui_hstack(id)))
132 {
133 gui_filler(jd);
134
135 if ((kd = gui_varray(jd)))
136 {
137 if ((ld = gui_vstack(kd)))
138 {
139 gui_space(ld);
140 gui_multi(ld, s0, GUI_SML, gui_wht, gui_wht);
141 gui_filler(ld);
142 }
143
144 if ((ld = gui_vstack(kd)))
145 {
146 gui_space(ld);
147 gui_multi(ld, s1, GUI_SML, gui_wht, gui_wht);
148 gui_filler(ld);
149 }
150 }
151
152 gui_space(jd);
153
154 if ((kd = gui_varray(jd)))
155 {
156 if ((ld = gui_vstack(kd)))
157 {
158 gui_space(ld);
159 gui_image(ld, "gui/help1.jpg", 5 * w / 16, 5 * h / 16);
160 gui_filler(ld);
161 }
162
163 if ((ld = gui_vstack(kd)))
164 {
165 gui_space(ld);
166 gui_image(ld, "gui/help2.jpg", 5 * w / 16, 5 * h / 16);
167 gui_filler(ld);
168 }
169 }
170
171 gui_filler(jd);
172 }
173 return id;
174 }
175
page_controls(int id)176 static int page_controls(int id)
177 {
178 const char *s_rotate = _("Left and right mouse buttons rotate the view.\\"
179 "Hold Shift for faster view rotation.");
180 const char *s_exit = _("Exit / Pause");
181 const char *s_camera1 = _("Chase Camera");
182 const char *s_camera2 = _("Lazy Camera");
183 const char *s_camera3 = _("Manual Camera");
184 const char *s_shot = _("Screenshot");
185
186 /*
187 * SDL_GetKeyName overwrites some of its results, that's why we
188 * don't cache the pointers anymore.
189 */
190
191 const SDL_Keycode k_exit = KEY_EXIT;
192 const SDL_Keycode k_cam1 = config_get_d(CONFIG_KEY_CAMERA_1);
193 const SDL_Keycode k_cam2 = config_get_d(CONFIG_KEY_CAMERA_2);
194 const SDL_Keycode k_cam3 = config_get_d(CONFIG_KEY_CAMERA_3);
195 const SDL_Keycode k_shot = KEY_SCREENSHOT;
196
197 int jd, kd;
198
199 gui_space(id);
200
201 if ((jd = gui_vstack(id)))
202 {
203 if ((kd = gui_harray(jd)))
204 {
205 gui_label(kd, s_exit, GUI_SML, gui_wht, gui_wht);
206 gui_label(kd, SDL_GetKeyName(k_exit), GUI_SML, gui_yel, gui_yel);
207 }
208 if ((kd = gui_harray(jd)))
209 {
210 gui_label(kd, s_camera1, GUI_SML, gui_wht, gui_wht);
211 gui_label(kd, SDL_GetKeyName(k_cam1), GUI_SML, gui_yel, gui_yel);
212 }
213 if ((kd = gui_harray(jd)))
214 {
215 gui_label(kd, s_camera2, GUI_SML, gui_wht, gui_wht);
216 gui_label(kd, SDL_GetKeyName(k_cam2), GUI_SML, gui_yel, gui_yel);
217 }
218 if ((kd = gui_harray(jd)))
219 {
220 gui_label(kd, s_camera3, GUI_SML, gui_wht, gui_wht);
221 gui_label(kd, SDL_GetKeyName(k_cam3), GUI_SML, gui_yel, gui_yel);
222 }
223 if ((kd = gui_harray(jd)))
224 {
225 gui_label(kd, s_shot, GUI_SML, gui_wht, gui_wht);
226 gui_label(kd, SDL_GetKeyName(k_shot), GUI_SML, gui_yel, gui_yel);
227 }
228
229 gui_set_rect(jd, GUI_ALL);
230 }
231
232 gui_space(id);
233
234 gui_multi(id, s_rotate, GUI_SML, gui_wht, gui_wht);
235
236 return id;
237 }
238
page_modes(int id)239 static int page_modes(int id)
240 {
241 int jd;
242
243 gui_space(id);
244
245 if ((jd = gui_vstack(id)))
246 {
247 gui_label(jd, _("Normal Mode"), GUI_SML, 0, 0);
248 gui_multi(jd,
249 _("Finish a level before the time runs out.\\"
250 "You need to collect coins in order to open the goal."),
251 GUI_SML, gui_wht, gui_wht);
252
253 gui_set_rect(jd, GUI_ALL);
254 }
255
256 gui_space(id);
257
258 if ((jd = gui_vstack(id)))
259 {
260 gui_label(jd, _("Challenge Mode"), GUI_SML, 0, 0);
261 gui_multi(jd,
262 _("Start playing from the first level of the set.\\"
263 "You start with only three balls, do not lose them.\\"
264 "Earn an extra ball for each 100 coins collected."),
265 GUI_SML, gui_wht, gui_wht);
266
267 gui_set_rect(jd, GUI_ALL);
268 }
269
270 return id;
271 }
272
page_tricks(int id)273 static int page_tricks(int id)
274 {
275 const char *s0 = _(
276 "Corners can be used to jump.\\"
277 "Get rolling and take aim\\"
278 "at the angle. You may be able\\"
279 "to reach new places.\\");
280 const char *s1 = _(
281 "Tilting in 2 directions increases\\"
282 "the slope. Use the manual camera\\"
283 "and turn the camera by 45\\"
284 "degrees for best results.\\");
285
286 int w = video.device_w;
287 int h = video.device_h;
288
289 int jd, kd, ld;
290
291 if ((jd = gui_hstack(id)))
292 {
293 gui_filler(jd);
294
295 if ((kd = gui_varray(jd)))
296 {
297 if ((ld = gui_vstack(kd)))
298 {
299 gui_space(ld);
300 gui_image(ld, "gui/help3.jpg", w / 4, h / 4);
301 gui_state(ld, _("Watch demo"), GUI_SML, 0, 0);
302 gui_filler(ld);
303
304 gui_set_state(ld, HELP_DEMO, 0);
305 }
306
307 if ((ld = gui_vstack(kd)))
308 {
309 gui_space(ld);
310 gui_image(ld, "gui/help4.jpg", w / 4, h / 4);
311 gui_state(ld, _("Watch demo"), GUI_SML, 0, 0);
312 gui_filler(ld);
313
314 gui_set_state(ld, HELP_DEMO, 1);
315 }
316 }
317
318 gui_space(jd);
319
320 if ((kd = gui_varray(jd)))
321 {
322 if ((ld = gui_vstack(kd)))
323 {
324 gui_space(ld);
325 gui_multi(ld, s0, GUI_SML, gui_wht, gui_wht);
326 gui_filler(ld);
327 }
328
329 if ((ld = gui_vstack(kd)))
330 {
331 gui_space(ld);
332 gui_multi(ld, s1, GUI_SML, gui_wht, gui_wht);
333 gui_filler(ld);
334 }
335 }
336
337 gui_filler(jd);
338 }
339 return id;
340 }
341
342 /* -------------------------------------------------------------------------- */
343
help_gui(void)344 static int help_gui(void)
345 {
346 int id;
347
348 if ((id = gui_vstack(0)))
349 {
350 help_menu(id);
351
352 switch (page)
353 {
354 case PAGE_RULES: page_rules(id); break;
355 case PAGE_CONTROLS: page_controls(id); break;
356 case PAGE_MODES: page_modes(id); break;
357 case PAGE_TRICKS: page_tricks(id); break;
358 }
359
360 gui_layout(id, 0, +1);
361 }
362
363 return id;
364 }
365
help_enter(struct state * st,struct state * prev)366 static int help_enter(struct state *st, struct state *prev)
367 {
368 return help_gui();
369 }
370
help_keybd(int c,int d)371 static int help_keybd(int c, int d)
372 {
373 if (d)
374 {
375 if (c == KEY_EXIT)
376 return help_action(GUI_BACK, 0);
377 }
378 return 1;
379 }
380
help_buttn(int b,int d)381 static int help_buttn(int b, int d)
382 {
383 if (d)
384 {
385 int active = gui_active();
386
387 if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
388 return help_action(gui_token(active), gui_value(active));
389 if (config_tst_d(CONFIG_JOYSTICK_BUTTON_B, b))
390 return help_action(GUI_BACK, 0);
391 }
392 return 1;
393 }
394
395 /*---------------------------------------------------------------------------*/
396
help_demo_enter(struct state * st,struct state * prev)397 static int help_demo_enter(struct state *st, struct state *prev)
398 {
399 game_client_fly(0.0f);
400 return 0;
401 }
402
help_demo_leave(struct state * st,struct state * next,int id)403 static void help_demo_leave(struct state *st, struct state *next, int id)
404 {
405 demo_replay_stop(0);
406 }
407
help_demo_paint(int id,float t)408 static void help_demo_paint(int id, float t)
409 {
410 game_client_draw(0, t);
411 }
412
help_demo_timer(int id,float dt)413 static void help_demo_timer(int id, float dt)
414 {
415 game_step_fade(dt);
416
417 if (!demo_replay_step(dt))
418 goto_state(&st_help);
419
420 game_client_blend(demo_replay_blend());
421 }
422
help_demo_keybd(int c,int d)423 static int help_demo_keybd(int c, int d)
424 {
425 if (d)
426 {
427 if (c == KEY_EXIT)
428 return goto_state(&st_help);
429 }
430 return 1;
431 }
432
help_demo_buttn(int b,int d)433 static int help_demo_buttn(int b, int d)
434 {
435 if (d)
436 {
437 if (config_tst_d(CONFIG_JOYSTICK_BUTTON_B, b))
438 return goto_state(&st_help);
439 }
440 return 1;
441 }
442 /*---------------------------------------------------------------------------*/
443
444 struct state st_help = {
445 help_enter,
446 shared_leave,
447 shared_paint,
448 shared_timer,
449 shared_point,
450 shared_stick,
451 shared_angle,
452 shared_click,
453 help_keybd,
454 help_buttn
455 };
456
457 struct state st_help_demo = {
458 help_demo_enter,
459 help_demo_leave,
460 help_demo_paint,
461 help_demo_timer,
462 NULL,
463 NULL,
464 NULL,
465 NULL,
466 help_demo_keybd,
467 help_demo_buttn
468 };
469