1 /* $Id: loop.c,v 1.146 2009/11/10 18:55:36 oohara Exp $ */
2
3 #include <stdio.h>
4
5 #include "tenm_object.h"
6 #include "tenm_table.h"
7 #include "player.h"
8 #include "tenm_timer.h"
9 #include "tenm_input.h"
10 #include "const.h"
11 #include "tenm_graphic.h"
12 #include "background.h"
13 #include "scheduler.h"
14 #include "score.h"
15 #include "chain.h"
16 #include "stage.h"
17 #include "ship.h"
18 #include "stage-select.h"
19 #include "pause.h"
20 #include "result.h"
21 #include "esc-ok.h"
22 #include "option.h"
23 #include "info.h"
24 #include "record_data.h"
25 #include "record_io.h"
26 #include "slow.h"
27
28 #include "loop.h"
29
30 static int main_loop(int tutorial);
31 static void ship_bonus(void);
32 /*
33 static int draw_all_mass(tenm_object *my, int n);
34 */
35
36 /* returns 1 if the program should quit, 0 if not */
37 int
game_loop(int tutorial)38 game_loop(int tutorial)
39 {
40 int i;
41 int status = 0;
42 game_record *record = NULL;
43
44 clear_chain();
45 clear_chain_scroll();
46 clear_score();
47 clear_score_scroll();
48 clear_ship();
49 clear_ship_scroll();
50 set_stage_number(1);
51 for (i = 1; i <= 6; i++)
52 {
53 set_stage_id(i, -1);
54 set_stage_name(i, NULL);
55 set_stage_difficulty(i, -1);
56 }
57
58 record = game_record_load();
59 if (record == NULL)
60 {
61 fprintf(stderr, "game_loop: game_record_load failed\n");
62 return 1;
63 }
64 if ((!tutorial) && (!cheating()))
65 increment_play_total(record);
66
67 while (1 == 1)
68 {
69 if (tutorial)
70 {
71 set_stage_id(get_stage_number(), -1);
72 }
73 else
74 {
75 clear_chain_scroll();
76 clear_score_scroll();
77 clear_ship_scroll();
78 status = stage_select(record);
79 if (status != 0)
80 break;
81 }
82
83 status = main_loop(tutorial);
84
85 if ((!cheating()) && (get_stage_id(get_stage_number()) >= 0))
86 {
87 /* the order does matter here (when you clear this plan first time) */
88 increment_play_plan(record, get_stage_id(get_stage_number()));
89 game_record_update(record);
90 if (status == 0)
91 increment_clear_plan(record, get_stage_id(get_stage_number()));
92 }
93
94 if (tutorial)
95 break;
96 if (status != 0)
97 break;
98
99 add_stage_number(1);
100 if (get_stage_number() >= 6)
101 {
102 ship_bonus();
103 game_record_update(record);
104 break;
105 }
106 }
107
108 if (!cheating())
109 {
110 if (game_record_save(record) != 0)
111 fprintf(stderr, "game_loop: game_record_save failed\n");
112 }
113 if (record != NULL)
114 game_record_delete(record);
115 record = NULL;
116
117 if ((!tutorial) && (status != 2))
118 {
119 if (show_result() != 0)
120 return 1;
121 }
122
123 if (status == 2)
124 return 1;
125
126 return 0;
127 }
128
129 /* return
130 * 0 if the player cleared the stage
131 * 1 if the game or the tutorial is over
132 * 2 if the program should quit
133 * player (arg 1) is freed if and only if the return value is non-zero
134 */
135 static int
main_loop(int tutorial)136 main_loop(int tutorial)
137 {
138 int i;
139 int t = 0;
140 int frame_passed = 0;
141 int status = 0;
142 int temp;
143 tenm_object *player = NULL;
144 const option *op = NULL;
145
146 op = get_option();
147 if (op == NULL)
148 {
149 fprintf(stderr, "game_loop: get_option failed\n");
150 return 2;
151 }
152
153 set_background(0);
154
155 tenm_table_clear_all();
156
157 clear_chain();
158
159 player = player_new(tutorial);
160 if (player == NULL)
161 {
162 fprintf(stderr, "game_loop: player_new failed\n");
163 return 2;
164 }
165
166 tenm_set_focus_handler((void (*)(int)) pause_by_mouse);
167 clear_pause();
168 clear_slow();
169
170 tenm_timer_reset();
171
172 while (1 == 1)
173 {
174 /* quit the program if a SDL_QUIT event happened
175 * (for example, if a SIGINT signal (sent by Ctrl+c) is received)
176 */
177 if (tenm_event_handle() != 0)
178 {
179 status = 2;
180 break;
181 }
182
183 /* back to the title if ESC is pressed */
184 if (tenm_get_key_status() & 32)
185 {
186 if (get_esc_ok())
187 {
188 set_esc_ok(0);
189 status = 1;
190 break;
191 }
192 }
193 else
194 {
195 set_esc_ok(1);
196 }
197
198 /* pause */
199 if (do_pause(tenm_get_key_status() & 64))
200 {
201 frame_passed++;
202 /* update the "paused" message */
203 tenm_redraw_window();
204 /* do_pause() needs this wait */
205 tenm_wait_next_frame();
206 continue;
207 }
208
209 for (i = 1; i <= 30; i++)
210 {
211 if (tenm_table_detect_collision(player) != 0)
212 player = NULL;
213 if (tenm_table_move(player, 30) != 0)
214 player = NULL;
215 }
216
217 /* scheduler() must be called before tenm_table_do_action()
218 * to clear action_needed flag correctly */
219 temp = scheduler(tutorial, t);
220
221 if (tenm_table_do_action(player) != 0)
222 player = NULL;
223
224 clear_window_with_background();
225
226 tenm_table_draw(player);
227
228 show_score(player);
229 show_ship(player);
230 show_chain(player);
231
232 /* for those who want to see the world as it is */
233 /* note that
234 * (1) the player is not in the table
235 * (2) this is slow
236 */
237 /*
238 tenm_table_apply_all((int (*)(tenm_object *, int)) draw_all_mass, 0);
239 */
240
241 tenm_redraw_window();
242
243 tenm_wait_next_frame();
244 /* slow down if CAPS lock is set */
245 if ((op->slow != 0) && (do_slow(tenm_get_key_status() & 128)))
246 tenm_wait_next_frame();
247
248 if (player == NULL)
249 {
250 /* no more life, game over */
251 status = 1;
252 break;
253 }
254
255 t++;
256 frame_passed++;
257 if (temp == SCHEDULER_NEXT_STAGE)
258 break;
259 }
260
261 if (frame_passed > 0)
262 {
263 printf("average fps: %f\n", tenm_calculate_fps(frame_passed));
264 fflush(stdout);
265 }
266
267 tenm_table_clear_all();
268 if (player != NULL)
269 tenm_object_delete(player);
270
271 return status;
272 }
273
274 static void
ship_bonus(void)275 ship_bonus(void)
276 {
277 if (get_stage_number() != 6)
278 return;
279 if (get_stage_cleared(6) != 0)
280 return;
281
282 set_stage_id(6, 0);
283 add_score(get_ship() * 30000);
284 set_stage_cleared(6, 1);
285 }
286
287 #if 0
288 static int
289 draw_all_mass(tenm_object *my, int n)
290 {
291 /* sanity check */
292 if (my == NULL)
293 return 0;
294
295 if (my->mass == NULL)
296 return 0;
297 if (my->attr == 0)
298 return 0;
299
300 if (tenm_draw_mass(my->mass, tenm_map_color(0, 0, 0)) != 0)
301 {
302 fprintf(stderr, "draw_all_mass: tenm_draw_mass failed (%d)\n",
303 my->table_index);
304 }
305
306 return 0;
307 }
308 #endif /* 0 */
309