Initial import.
[neverball] / ball / st_goal.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 <string.h>
16
17 #include "gui.h"
18 #include "set.h"
19 #include "game.h"
20 #include "util.h"
21 #include "demo.h"
22 #include "level.h"
23 #include "audio.h"
24 #include "config.h"
25
26 #include "st_goal.h"
27 #include "st_save.h"
28 #include "st_over.h"
29 #include "st_done.h"
30 #include "st_title.h"
31 #include "st_level.h"
32
33 /*---------------------------------------------------------------------------*/
34
35 #define GOAL_NEXT 2
36 #define GOAL_SAME 3
37 #define GOAL_SAVE 4
38
39 static int high;
40 static int time_i;
41 static int coin_i;
42     
43 static int balls_id;
44 static int coins_id;
45 static int score_id;
46
47 static int goal_action(int i)
48 {
49     char player[MAXNAM];
50     size_t l;
51
52     audio_play(AUD_MENU, 1.0f);
53
54     config_get_s(CONFIG_PLAYER, player, MAXNAM);
55     l = strlen(player);
56
57     switch (i)
58     {
59     case GOAL_SAVE:
60         while (level_count())
61             ;
62         return goto_state(&st_save);
63
64     case GOAL_NEXT:
65         while (level_count())
66             ;
67         if (level_exit(NULL, 1))
68             return goto_state(&st_level);
69         else
70             return goto_state(&st_done);
71
72     case GOAL_SAME:
73         while (level_count())
74             ;
75         if (level_exit(NULL, 0))
76             return goto_state(&st_level);
77         else
78             return goto_state(&st_done);
79
80     case GUI_CL:
81         gui_keyboard_lock();
82         break;
83
84     case GUI_BS:
85         if (l > 0)
86         {
87             player[l - 1] = 0;
88
89             config_set_s(CONFIG_PLAYER, player);
90             level_name(curr_level(), player, time_i, coin_i);
91             set_most_coins(curr_level(), 4);
92             set_best_times(curr_level(), 4);
93         }
94         break;
95
96     default:
97         if (l < MAXNAM - 1)
98         {
99             player[l + 0] = gui_keyboard_char((char) i);
100             player[l + 1] = 0;
101
102             config_set_s(CONFIG_PLAYER, player);
103             level_name(curr_level(), player, time_i, coin_i);
104             set_most_coins(curr_level(), 4);
105             set_best_times(curr_level(), 4);
106         }
107     }
108     return 1;
109 }
110
111 static int goal_enter(void)
112 {
113     const char *s1 = "New Record";
114     const char *s2 = "GOAL";
115
116     int id, jd, kd;
117
118     time_i = 3;
119     coin_i = 3;
120     high   = level_sort(&time_i, &coin_i);
121
122     if ((id = gui_vstack(0)))
123     {
124         int gid;
125
126         if (high)
127             gid = gui_label(id, s1, GUI_MED, GUI_ALL, gui_grn, gui_grn);
128         else
129             gid = gui_label(id, s2, GUI_LRG, GUI_ALL, gui_blu, gui_grn);
130
131         gui_space(id);
132
133         if ((jd = gui_harray(id)))
134         {
135             if ((kd = gui_harray(jd)))
136             {
137                 balls_id = gui_count(kd,  10, GUI_MED, GUI_RGT);
138                 gui_label(kd, "Balls", GUI_SML, GUI_LFT, gui_wht, gui_wht);
139             }
140             if ((kd = gui_harray(jd)))
141             {
142                 score_id = gui_count(kd, 100, GUI_MED, GUI_RGT);
143                 gui_label(kd, "Score", GUI_SML, GUI_LFT, gui_wht, gui_wht);
144             }
145             if ((kd = gui_harray(jd)))
146             {
147                 coins_id = gui_count(kd, 100, GUI_MED, GUI_RGT);
148                 gui_label(kd, "Coins", GUI_SML, GUI_LFT, gui_wht, gui_wht);
149             }
150
151             gui_set_count(balls_id, curr_balls());
152             gui_set_count(score_id, curr_score());
153             gui_set_count(coins_id, curr_coins());
154         }
155
156         gui_space(id);
157
158         if ((jd = gui_harray(id)))
159         {
160             gui_most_coins(jd, 4, coin_i);
161             gui_best_times(jd, 4, time_i);
162         }
163
164         gui_space(id);
165
166         if ((jd = gui_harray(id)))
167         {
168             gui_state(jd, "Save Replay", GUI_SML, GOAL_SAVE, 0);
169             gui_state(jd, "Retry Level", GUI_SML, GOAL_SAME, 0);
170
171             if (level_last())
172                 gui_start(jd, "Finish",  GUI_SML, GOAL_NEXT, 0);
173             else
174                 gui_start(jd, "Next Level", GUI_SML, GOAL_NEXT, 0);
175         }
176
177         if (high) gui_keyboard(id);
178
179         gui_layout(id, 0, 0);
180         gui_pulse(gid, 1.2f);
181     }
182
183     set_most_coins(curr_level(), 4);
184     set_best_times(curr_level(), 4);
185
186     audio_music_fade_out(2.0f);
187     audio_play(AUD_GOAL, 1.0f);
188
189     config_clr_grab();
190
191     return id;
192 }
193
194 static void goal_leave(int id)
195 {
196     gui_delete(id);
197 }
198
199 static void goal_paint(int id, float st)
200 {
201     game_draw(0, st);
202     gui_paint(id);
203 }
204
205 static void goal_timer(int id, float dt)
206 {
207     static float DT = 0.0f;
208
209     float g[3] = { 0.0f, 9.8f, 0.0f };
210
211     DT += dt;
212
213     if (time_state() < 1.f)
214     {
215         game_step(g, dt, 0);
216         demo_play_step(dt);
217     }
218     else if (DT > 0.05f)
219     {
220         if (level_count())
221         {
222             int coins = curr_coins();
223             int score = curr_score();
224             int balls = curr_balls();
225
226             if (gui_value(coins_id) != coins)
227             {
228                 gui_set_count(coins_id, coins);
229                 gui_pulse(coins_id, 1.1f);
230             }
231             if (gui_value(score_id) != score)
232             {
233                 gui_set_count(score_id, score);
234                 gui_pulse(score_id, 1.1f);
235             }
236             if (gui_value(balls_id) != balls)
237             {
238                 gui_set_count(balls_id, balls);
239                 gui_pulse(balls_id, 2.0f);
240             }
241         }
242
243         DT = 0.0f;
244     }
245
246     gui_timer(id, dt);
247     audio_timer(dt);
248 }
249
250 static void goal_point(int id, int x, int y, int dx, int dy)
251 {
252     gui_pulse(gui_point(id, x, y), 1.2f);
253 }
254
255 static void goal_stick(int id, int a, int v)
256 {
257     if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
258         gui_pulse(gui_stick(id, v, 0), 1.2f);
259     if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
260         gui_pulse(gui_stick(id, 0, v), 1.2f);
261 }
262
263 static int goal_click(int b, int d)
264 {
265     if (b <= 0 && d == 1)
266         return goal_action(gui_token(gui_click()));
267     return 1;
268 }
269
270 static int goal_keybd(int c, int d)
271 {
272     if (d && c == SDLK_ESCAPE)
273         goto_state(&st_over);
274     return 1;
275 }
276
277 static int goal_buttn(int b, int d)
278 {
279     if (d)
280     {
281         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
282             return goal_click(0, 1);
283         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
284             return goto_state(&st_over);
285     }
286     return 1;
287 }
288
289 /*---------------------------------------------------------------------------*/
290
291 struct state st_goal = {
292     goal_enter,
293     goal_leave,
294     goal_paint,
295     goal_timer,
296     goal_point,
297     goal_stick,
298     goal_click,
299     goal_keybd,
300     goal_buttn,
301     1, 0
302 };
303