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