1 /*
2 * Tux Racer
3 * Copyright (C) 1999-2001 Jasmin F. Patry
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include "tuxracer.h"
21 #include "audio.h"
22 #include "keyboard.h"
23 #include "keyframe.h"
24 #include "course_render.h"
25 #include "multiplayer.h"
26 #include "gl_util.h"
27 #include "fps.h"
28 #include "loop.h"
29 #include "render_util.h"
30 #include "view.h"
31 #include "tux.h"
32 #include "tux_shadow.h"
33 #include "phys_sim.h"
34 #include "part_sys.h"
35 #include "screenshot.h"
36 #include "fog.h"
37 #include "viewfrustum.h"
38 #include "track_marks.h"
39 #include "hud.h"
40 #include "joystick.h"
41
42 /* Time constant for automatic steering centering (s) */
43 #define TURN_DECAY_TIME_CONSTANT 0.5
44
45 /* Maximum time over which jump can be charged */
46 #define MAX_JUMP_AMT 1.0
47
48 /* Time constant for automatic rolling centering (s) */
49 #define ROLL_DECAY_TIME_CONSTANT 0.2
50
51 #define JUMP_CHARGE_DECAY_TIME_CONSTANT 0.1
52
53 /* If too high off the ground, tux flaps instead of jumping */
54 #define JUMP_MAX_START_HEIGHT 0.30
55
56 static bool_t right_turn;
57 static bool_t left_turn;
58 static bool_t trick_modifier;
59 static bool_t paddling;
60 static bool_t charging;
61 static bool_t braking;
62 static scalar_t charge_start_time;
63 static int last_terrain;
64
racing_init(void)65 void racing_init(void)
66 {
67 player_data_t *plyr = get_player_data( local_player() );
68
69 winsys_set_display_func( main_loop );
70 winsys_set_idle_func( main_loop );
71 winsys_set_reshape_func( reshape );
72 winsys_set_mouse_func( NULL );
73 winsys_set_motion_func( NULL );
74 winsys_set_passive_motion_func( NULL );
75 winsys_set_mouse_func( NULL );
76
77 /* Initialize view */
78 if ( getparam_view_mode() < 0 ||
79 getparam_view_mode() >= NUM_VIEW_MODES )
80 {
81 setparam_view_mode( ABOVE );
82 }
83 set_view_mode( plyr, (view_mode_t)getparam_view_mode() );
84
85 /* We need to reset controls here since callbacks won't have been
86 called in paused mode. This results in duplication between this
87 code and init_physical_simulation. Oh well. */
88 left_turn = right_turn = paddling = False;
89 trick_modifier = False;
90 charging = False;
91 plyr->control.turn_fact = 0.0;
92 plyr->control.turn_animation = 0.0;
93 plyr->control.is_braking = False;
94 plyr->control.is_paddling = False;
95 plyr->control.jumping = False;
96 plyr->control.jump_charging = False;
97
98 /* Set last_terrain to a value not used below */
99 last_terrain = 0;
100
101 if ( g_game.prev_mode != PAUSED ) {
102 init_physical_simulation();
103 }
104
105 last_terrain = 0;
106
107 g_game.race_aborted = False;
108
109 play_music( "racing" );
110 /* play_sound( "start_race", 0 ); */
111 }
112
calc_jump_amt(scalar_t time_step)113 void calc_jump_amt( scalar_t time_step )
114 {
115 player_data_t *plyr = get_player_data( local_player() );
116
117 if ( plyr->control.jump_charging ) {
118 plyr->control.jump_amt = min(
119 MAX_JUMP_AMT, g_game.time - charge_start_time );
120 } else if ( plyr->control.jumping ) {
121 plyr->control.jump_amt *=
122 ( 1.0 - ( g_game.time - plyr->control.jump_start_time ) /
123 JUMP_FORCE_DURATION );
124 } else {
125 plyr->control.jump_amt = 0;
126 }
127 }
128
racing_loop(scalar_t time_step)129 void racing_loop( scalar_t time_step )
130 {
131 int width, height;
132 player_data_t *plyr = get_player_data( local_player() );
133 bool_t joy_left_turn = False;
134 bool_t joy_right_turn = False;
135 scalar_t joy_turn_fact = 0.0;
136 bool_t joy_paddling = False;
137 bool_t joy_braking = False;
138 bool_t joy_tricks = False;
139 bool_t joy_charging = False;
140 bool_t airborne;
141 vector_t dir;
142 scalar_t speed;
143 scalar_t terrain_weights[NumTerrains];
144 int new_terrain = 0;
145 int slide_volume;
146
147
148 dir = plyr->vel;
149 speed = normalize_vector(&dir);
150
151 airborne = (bool_t) ( plyr->pos.y > ( find_y_coord(plyr->pos.x,
152 plyr->pos.z) +
153 JUMP_MAX_START_HEIGHT ) );
154
155 width = getparam_x_resolution();
156 height = getparam_y_resolution();
157
158 check_gl_error();
159
160 new_frame_for_fps_calc();
161
162 update_audio();
163
164 clear_rendering_context();
165
166 setup_fog();
167
168
169 /*
170 * Joystick
171 */
172 if ( is_joystick_active() ) {
173 scalar_t joy_x;
174 scalar_t joy_y;
175
176 update_joystick();
177
178 joy_x = get_joystick_x_axis();
179 joy_y = get_joystick_y_axis();
180
181 if ( joy_x > 0.1 ) {
182 joy_right_turn = True;
183 joy_turn_fact = joy_x;
184 } else if ( joy_x < -0.1 ) {
185 joy_left_turn = True;
186 joy_turn_fact = joy_x;
187 }
188
189 if ( getparam_joystick_brake_button() >= 0 ) {
190 joy_braking =
191 is_joystick_button_down( getparam_joystick_brake_button() );
192 }
193 if ( !joy_braking ) {
194 joy_braking = (bool_t) ( joy_y > 0.5 );
195 }
196
197 if ( getparam_joystick_paddle_button() >= 0 ) {
198 joy_paddling =
199 is_joystick_button_down( getparam_joystick_paddle_button() );
200 }
201 if ( !joy_paddling ) {
202 joy_paddling = (bool_t) ( joy_y < -0.5 );
203 }
204
205 if ( getparam_joystick_jump_button() >= 0 ) {
206 joy_charging =
207 is_joystick_button_down( getparam_joystick_jump_button() );
208 }
209
210 if ( getparam_joystick_trick_button() >= 0 ) {
211 joy_tricks =
212 is_joystick_button_down( getparam_joystick_trick_button() );
213 }
214 }
215
216 /* Update braking */
217 plyr->control.is_braking = (bool_t) ( braking || joy_braking );
218
219 if ( airborne ) {
220 new_terrain = (1<<NumTerrains);
221
222 /*
223 * Tricks
224 */
225 if ( trick_modifier || joy_tricks ) {
226 if ( left_turn || joy_left_turn ) {
227 plyr->control.barrel_roll_left = True;
228 }
229 if ( right_turn || joy_right_turn ) {
230 plyr->control.barrel_roll_right = True;
231 }
232 if ( paddling || joy_paddling ) {
233 plyr->control.front_flip = True;
234 }
235 if ( plyr->control.is_braking ) {
236 plyr->control.back_flip = True;
237 }
238 }
239
240
241 } else {
242
243 get_surface_type(plyr->pos.x, plyr->pos.z, terrain_weights);
244 if (terrain_weights[Snow] > 0) {
245 new_terrain |= (1<<Snow);
246 }
247 if (terrain_weights[Rock] > 0) {
248 new_terrain |= (1<<Rock);
249 }
250 if (terrain_weights[Ice] > 0) {
251 new_terrain |= (1<<Ice);
252 }
253
254 }
255
256 /*
257 * Jumping
258 */
259 calc_jump_amt( time_step );
260
261 if ( ( charging || joy_charging ) &&
262 !plyr->control.jump_charging && !plyr->control.jumping )
263 {
264 plyr->control.jump_charging = True;
265 charge_start_time = g_game.time;
266 }
267
268 if ( ( !charging && !joy_charging ) && plyr->control.jump_charging ) {
269 plyr->control.jump_charging = False;
270 plyr->control.begin_jump = True;
271 }
272
273
274 /*
275 * Turning
276 */
277 if ( ( left_turn || joy_left_turn ) ^ (right_turn || joy_right_turn ) ) {
278 bool_t turning_left = (bool_t) ( left_turn || joy_left_turn );
279
280 if ( joy_left_turn || joy_right_turn ) {
281 plyr->control.turn_fact = joy_turn_fact;
282 } else {
283 plyr->control.turn_fact = (turning_left?-1:1);
284 }
285
286 plyr->control.turn_animation += (turning_left?-1:1) *
287 0.15 * time_step / 0.05;
288 plyr->control.turn_animation =
289 min(1.0, max(-1.0, plyr->control.turn_animation));
290 } else {
291 plyr->control.turn_fact = 0;
292
293 /* Decay turn animation */
294 if ( time_step < ROLL_DECAY_TIME_CONSTANT ) {
295 plyr->control.turn_animation *=
296 1.0 - time_step/ROLL_DECAY_TIME_CONSTANT;
297 } else {
298 plyr->control.turn_animation = 0.0;
299 }
300 }
301
302
303 /*
304 * Paddling
305 */
306 if ( ( paddling || joy_paddling ) && plyr->control.is_paddling == False ) {
307 plyr->control.is_paddling = True;
308 plyr->control.paddle_time = g_game.time;
309 }
310
311 /*
312 * Play flying sound
313 */
314 if (new_terrain & (1<<NumTerrains)) {
315 set_sound_volume("flying_sound", min(128, speed*2));
316 if (!(last_terrain & (1<<NumTerrains))) {
317 play_sound( "flying_sound", -1 );
318 }
319 } else {
320 if (last_terrain & (1<<NumTerrains)) {
321 halt_sound( "flying_sound" );
322 }
323 }
324
325 /*
326 * Play sliding sound
327 */
328 slide_volume = min( (((pow(plyr->control.turn_fact, 2)*128)) +
329 (plyr->control.is_braking?128:0) +
330 (plyr->control.jumping?128:0) +
331 20) *
332 (speed/10), 128 );
333 if (new_terrain & (1<<Snow)) {
334 set_sound_volume("snow_sound", slide_volume * terrain_weights[Snow]);
335 if (!(last_terrain & (1<<Snow))) {
336 play_sound( "snow_sound", -1 );
337 }
338 } else {
339 if (last_terrain & (1<<Snow)) {
340 halt_sound( "snow_sound" );
341 }
342 }
343 if (new_terrain & (1<<Rock)) {
344 set_sound_volume("rock_sound", 128*pow((speed/2), 2) *
345 terrain_weights[Rock]);
346 if (!(last_terrain & (1<<Rock))) {
347 play_sound( "rock_sound", -1 );
348 }
349 } else {
350 if (last_terrain & (1<<Rock)) {
351 halt_sound( "rock_sound" );
352 }
353 }
354 if (new_terrain & (1<<Ice)) {
355 set_sound_volume("ice_sound", slide_volume * terrain_weights[Ice]);
356 if (!(last_terrain & (1<<Ice))) {
357 play_sound( "ice_sound", -1 );
358 }
359 } else {
360 if (last_terrain & (1<<Ice)) {
361 halt_sound( "ice_sound" );
362 }
363 }
364 last_terrain = new_terrain;
365
366
367 /*
368 * Tricks
369 */
370 if ( plyr->control.barrel_roll_left || plyr->control.barrel_roll_right ) {
371 plyr->control.barrel_roll_factor +=
372 ( plyr->control.barrel_roll_left ? -1 : 1 ) * 0.15 * time_step / 0.05;
373 if ( (plyr->control.barrel_roll_factor > 1) ||
374 (plyr->control.barrel_roll_factor < -1) ) {
375 plyr->control.barrel_roll_factor = 0;
376 plyr->control.barrel_roll_left = plyr->control.barrel_roll_right = False;
377 }
378 }
379 if ( plyr->control.front_flip || plyr->control.back_flip ) {
380 plyr->control.flip_factor +=
381 ( plyr->control.back_flip ? -1 : 1 ) * 0.15 * time_step / 0.05;
382 if ( (plyr->control.flip_factor > 1) ||
383 (plyr->control.flip_factor < -1) ) {
384 plyr->control.flip_factor = 0;
385 plyr->control.front_flip = plyr->control.back_flip = False;
386 }
387 }
388
389 update_player_pos( plyr, time_step );
390
391 /*
392 * Track Marks
393 */
394 add_track_mark( plyr );
395
396
397 update_view( plyr, time_step );
398
399 setup_view_frustum( plyr, NEAR_CLIP_DIST,
400 getparam_forward_clip_distance() );
401
402 draw_sky(plyr->view.pos);
403
404 draw_fog_plane();
405
406 set_course_clipping( True );
407 set_course_eye_point( plyr->view.pos );
408 setup_course_lighting();
409 render_course();
410 draw_trees();
411
412 if ( getparam_draw_particles() ) {
413 update_particles( time_step );
414 draw_particles( plyr );
415 }
416
417 draw_tux();
418 draw_tux_shadow();
419
420 draw_hud( plyr );
421
422 reshape( width, height );
423
424 winsys_swap_buffers();
425
426 g_game.time += time_step;
427 }
428
racing_term(void)429 static void racing_term(void)
430 {
431 halt_sound( "flying_sound" );
432 halt_sound( "rock_sound" );
433 halt_sound( "ice_sound" );
434 halt_sound( "snow_sound" );
435 break_track_marks();
436 }
437
438
START_KEYBOARD_CB(quit_racing_cb)439 START_KEYBOARD_CB( quit_racing_cb )
440 {
441 if ( release ) return;
442 g_game.race_aborted = True;
443 set_game_mode( GAME_OVER );
444 }
445 END_KEYBOARD_CB
446
447
START_KEYBOARD_CB(turn_left_cb)448 START_KEYBOARD_CB( turn_left_cb )
449 {
450 left_turn = (bool_t) !release;
451 }
452 END_KEYBOARD_CB
453
454
START_KEYBOARD_CB(turn_right_cb)455 START_KEYBOARD_CB( turn_right_cb )
456 {
457 right_turn = (bool_t) !release;
458 }
459 END_KEYBOARD_CB
460
461
START_KEYBOARD_CB(trick_modifier_cb)462 START_KEYBOARD_CB( trick_modifier_cb )
463 {
464 trick_modifier = (bool_t) !release;
465 }
466 END_KEYBOARD_CB
467
468
START_KEYBOARD_CB(brake_cb)469 START_KEYBOARD_CB( brake_cb )
470 {
471 braking = (bool_t) !release;
472 }
473 END_KEYBOARD_CB
474
START_KEYBOARD_CB(paddle_cb)475 START_KEYBOARD_CB( paddle_cb )
476 {
477 paddling = (bool_t) !release;
478 }
479 END_KEYBOARD_CB
480
481
START_KEYBOARD_CB(above_view_cb)482 START_KEYBOARD_CB( above_view_cb )
483 {
484 if ( release ) return;
485 set_view_mode( plyr, ABOVE );
486 setparam_view_mode( ABOVE );
487 }
488 END_KEYBOARD_CB
489
START_KEYBOARD_CB(follow_view_cb)490 START_KEYBOARD_CB( follow_view_cb )
491 {
492 if ( release ) return;
493 set_view_mode( plyr, FOLLOW );
494 setparam_view_mode( FOLLOW );
495 }
496 END_KEYBOARD_CB
497
START_KEYBOARD_CB(behind_view_cb)498 START_KEYBOARD_CB( behind_view_cb )
499 {
500 if ( release ) return;
501 set_view_mode( plyr, BEHIND );
502 setparam_view_mode( BEHIND );
503 }
504 END_KEYBOARD_CB
505
START_KEYBOARD_CB(screenshot_cb)506 START_KEYBOARD_CB( screenshot_cb )
507 {
508 if ( release ) return;
509 screenshot();
510 }
511 END_KEYBOARD_CB
512
START_KEYBOARD_CB(pause_cb)513 START_KEYBOARD_CB( pause_cb )
514 {
515 if ( release ) return;
516 set_game_mode( PAUSED );
517 }
518 END_KEYBOARD_CB
519
START_KEYBOARD_CB(reset_cb)520 START_KEYBOARD_CB( reset_cb )
521 {
522 if ( release ) return;
523 set_game_mode( RESET );
524 }
525 END_KEYBOARD_CB
526
START_KEYBOARD_CB(jump_cb)527 START_KEYBOARD_CB( jump_cb )
528 {
529 charging = (bool_t) !release;
530 }
531 END_KEYBOARD_CB
532
racing_register()533 void racing_register()
534 {
535 int status = 0;
536
537 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
538 "escape", getparam_quit_key, quit_racing_cb );
539 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
540 "j", getparam_turn_left_key, turn_left_cb );
541 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
542 "l", getparam_turn_right_key, turn_right_cb );
543 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
544 "d", getparam_trick_modifier_key,
545 trick_modifier_cb );
546 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
547 "space", getparam_brake_key, brake_cb );
548 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
549 "k", getparam_paddle_key, paddle_cb );
550
551 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
552 "1", getparam_behind_view_key,
553 behind_view_cb );
554 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
555 "2", getparam_follow_view_key,
556 follow_view_cb );
557 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
558 "3", getparam_above_view_key, above_view_cb );
559
560 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
561 "=", getparam_screenshot_key, screenshot_cb );
562 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
563 "p", getparam_pause_key, pause_cb );
564 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
565 "r", getparam_reset_key, reset_cb );
566 status |= add_keymap_entry( RACING, CONFIGURABLE_KEY,
567 "i", getparam_jump_key, jump_cb );
568
569 check_assertion( status == 0, "out of keymap entries" );
570
571 register_loop_funcs( RACING, racing_init, racing_loop, racing_term );
572 }
573