/* ===================================================================== * Periodically recalculate some submarine parameters, with a larger delay * =====================================================================*/ static gboolean update_timeout_slow() { gdouble delta_assiette; if(!boardRootItem) return FALSE; if(board_paused) return TRUE; /* speed : don't reach instantly the ordered speed */ if (speed_ordered != submarine_horizontal_speed) { submarine_horizontal_speed += (speed_ordered-submarine_horizontal_speed)/10.0; if (fabs(speed_ordered - submarine_horizontal_speed) < 0.1) submarine_horizontal_speed = speed_ordered; } /* assiette */ delta_assiette = (ballast_ar_air - ballast_av_air)/200.0 + (barre_av_angle - barre_ar_angle)/5.0*submarine_horizontal_speed; assiette -= delta_assiette*UPDATE_DELAY/10000.0; if (assiette < -30.0) assiette = -30.0; if (assiette > 30.0) assiette = 30.0; /* If surfacing, diminish the 'assiette' */ if ( depth <= 5.0 + SURFACE_DEPTH) { assiette *= depth/(depth+1.0); } /* update some dynamic parameters */ /* resulting_weight > 0 ==> the sub goes deeper regleur : this is the qty of water */ resulting_weight = weight - ballast_av_air - ballast_ar_air + regleur; submarine_vertical_speed = resulting_weight/300.0 + submarine_horizontal_speed*sin(DEG_TO_RAD(-assiette)); /* if depth rudders are in the same direction */ if (barre_ar_angle != 0.0 && barre_av_angle != 0.0) { if (fabs(barre_ar_angle)/barre_ar_angle == fabs(barre_av_angle)/barre_av_angle) { gdouble a = (fabs(barre_ar_angle) > fabs(barre_av_angle)) ? barre_av_angle : barre_ar_angle; submarine_vertical_speed += a * submarine_horizontal_speed/30.0; } } /* position & depth */ submarine_x += submarine_horizontal_speed * cos(DEG_TO_RAD(assiette)) * UPDATE_DELAY_SLOW/1000.0; depth += submarine_vertical_speed * UPDATE_DELAY_SLOW/1000.0; if (depth < SURFACE_DEPTH) depth = SURFACE_DEPTH; if (depth > MAX_DEPTH) depth = MAX_DEPTH; // show an alert if some parameters reach the limit if (depth >= MAX_DEPTH-20.0 || assiette == -30.0 || assiette == 30.0 || air == 0.0 || battery == 0.0) g_object_set (alert_submarine, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); else g_object_set (alert_submarine, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); /* if the submarine dives, stop charging air tanks and batteries */ if ( depth >= SURFACE_DEPTH+10.0 ) { if (air_charging) { air_charging = FALSE; gc_item_rotate_with_center(air_compressor_item, 0, TRIGGER_CENTER_X, TRIGGER_CENTER_Y ); } if (battery_charging) { battery_charging = FALSE; gc_item_rotate_with_center(battery_charger_item, 0, TRIGGER_CENTER_X, TRIGGER_CENTER_Y ); } } /* Check the submarine passed the right door */ if ( submarine_x > WRAP_X && !gamewon ) { /* Check its within the gate range */ GooCanvasBounds bounds; goo_canvas_item_get_bounds (submarine_item, &bounds); guint antena_height = 30; if(bounds.y1 + antena_height < gate_top_current_y || bounds.y2 > gate_bottom_y) { /* It's a crash */ submarine_explosion(); } else { gamewon = TRUE; ok(); } } /* Open the door */ if(treasure_captured && gate_top_current_y > gate_top_y) open_door(); /* display the submarine */ goo_canvas_item_set_simple_transform(submarine_item, submarine_x - submarine_width/2.0, depth + SURFACE_DEPTH - submarine_height/2.0, 1, -assiette); /* the frigate */ if ( frigate_item ) { /* detects a collision between the frigate and the submarine */ if (depth <= 30.0 && !submarine_destroyed) { GooCanvasBounds bounds; goo_canvas_item_get_bounds(frigate_item, &bounds); gdouble frigate_x = bounds.x1 + (bounds.x2 - bounds.x1) / 2; if ( abs(submarine_x - frigate_x) < 100 ) { submarine_explosion(); return TRUE; } } } /* whale detection */ { gdouble dist1 = hypot( submarine_x - whale_x, depth - whale_y); if ( ( dist1 < WHALE_DETECTION_RADIUS ) && !submarine_destroyed ) { g_object_set (whale, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); g_object_set (big_explosion, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); submarine_explosion(); return TRUE; } } /* treasure detection */ { gdouble dist1 = hypot( submarine_x - treasure_x, depth - treasure_y); if ( (dist1 < TREASURE_DETECTION_RADIUS) && !treasure_captured ) { gc_sound_play_ogg("sounds/tuxok.wav", NULL); g_object_set (treasure, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); treasure_captured = TRUE; open_door(); } } return TRUE; }
/* ===================================================================== * Periodically recalculate some submarine parameters, with a larger delay * =====================================================================*/ static gboolean update_timeout_slow() { gdouble delta_assiette; if(!boardRootItem) return FALSE; if(board_paused) return TRUE; /* speed : don't reach instantly the ordered speed */ if (speed_ordered != submarine_horizontal_speed) { submarine_horizontal_speed += (speed_ordered-submarine_horizontal_speed)/10.0; if (fabs(speed_ordered - submarine_horizontal_speed) < 0.1) submarine_horizontal_speed = speed_ordered; } /* assiette */ delta_assiette = (ballast_ar_air - ballast_av_air)/200.0 + (barre_av_angle - barre_ar_angle)/5.0*submarine_horizontal_speed; assiette -= delta_assiette*UPDATE_DELAY/10000.0; if (assiette < -30.0) assiette = -30.0; if (assiette > 30.0) assiette = 30.0; /* If surfacing, diminish the 'assiette' */ if ( depth <= 5.0 + SURFACE_DEPTH) { assiette *= depth/(depth+1.0); } /* update some dynamic parameters */ /* resulting_weight > 0 ==> the sub goes deeper regleur : this is the qty of water */ resulting_weight = weight - ballast_av_air - ballast_ar_air + regleur; submarine_vertical_speed = resulting_weight/300.0 + submarine_horizontal_speed*sin(DEG_TO_RAD(-assiette)); /* if depth rudders are in the same direction */ if (barre_ar_angle != 0.0 && barre_av_angle != 0.0) { if (fabs(barre_ar_angle)/barre_ar_angle == fabs(barre_av_angle)/barre_av_angle) { gdouble a = (fabs(barre_ar_angle) > fabs(barre_av_angle)) ? barre_av_angle : barre_ar_angle; submarine_vertical_speed += a * submarine_horizontal_speed/30.0; } } /* position & depth */ submarine_x += submarine_horizontal_speed * cos(DEG_TO_RAD(assiette)) * UPDATE_DELAY_SLOW/1000.0; depth += submarine_vertical_speed * UPDATE_DELAY_SLOW/1000.0; if (depth < SURFACE_DEPTH) depth = SURFACE_DEPTH; if (depth > MAX_DEPTH) depth = MAX_DEPTH; // show an alert if some parameters reach the limit if (depth >= MAX_DEPTH-20.0 || assiette == -30.0 || assiette == 30.0 || air == 0.0 || battery == 0.0) g_object_set (alert_submarine, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); else g_object_set (alert_submarine, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); /* if the submarine dives, stop charging air tanks and batteries */ if ( depth >= SURFACE_DEPTH+10.0 ) { if (air_charging) { air_charging = FALSE; gc_item_rotate_with_center(air_compressor_item, 0, TRIGGER_CENTER_X, TRIGGER_CENTER_Y ); } if (battery_charging) { battery_charging = FALSE; gc_item_rotate_with_center(battery_charger_item, 0, TRIGGER_CENTER_X, TRIGGER_CENTER_Y ); } } /* if the submarine is too close from right, put it on the left */ if ( submarine_x > WRAP_X ) { /* Check its within the gate range */ GooCanvasBounds bounds; goo_canvas_item_get_bounds (submarine_item, &bounds); if(bounds.y1 < gate_top_current_y || bounds.y2 > gate_bottom_y) { /* It's a crash */ submarine_explosion(); } else { gamewon = TRUE; /* Let the user play indefinitly at level 3 */ if(gcomprisBoard->level<3) gc_bonus_display(gamewon, GC_BONUS_SMILEY); else { submarine_x = SUBMARINE_INITIAL_X; depth = SUBMARINE_INITIAL_DEPTH; } } } /* Open the door */ if(treasure_captured && gate_top_current_y > gate_top_y) open_door(); /* display the submarine */ goo_canvas_item_set_simple_transform(submarine_item, submarine_x - submarine_width/2.0, depth + SURFACE_DEPTH - submarine_height/2.0, 1, -assiette); /* the frigate */ { GooCanvasBounds bounds; goo_canvas_item_get_bounds(frigate_item, &bounds); //goo_canvas_item_translate(frigate_item, - FRIGATE_SPEED * UPDATE_DELAY_SLOW/1000.0, 0.0); /* detects a collision between the frigate and the submarine */ if (depth <= 30.0 && !submarine_destroyed) if ( (submarine_x - submarine_width <= bounds.x1 && submarine_x >= bounds.x2) || (submarine_x - submarine_width >= bounds.x1 && submarine_x - submarine_width <= bounds.x2) || (submarine_x >= bounds.x1 && submarine_x <= bounds.x2) ) { submarine_explosion(); } /* wraps the destroyer if it reached the left side (and disappeared for a long time)*/ //if (bounds.x2 < -300.0) //gc_item_absolute_move( frigate_item, BOARDWIDTH, bounds.y1 ); } /* whale detection */ { gdouble dist1, dist2, dist3; dist1 = hypot( submarine_x -submarine_width/2 -whale_x, depth+SURFACE_IN_BACKGROUND-whale_y); dist2 = hypot(submarine_x - submarine_width - whale_x, depth+SURFACE_IN_BACKGROUND-whale_y); dist3 = hypot(submarine_x - whale_x, depth+SURFACE_IN_BACKGROUND-whale_y); /* magnetic detection (dist1) or collision with the whale (dist2 & dist3) */ if ( (dist1 < WHALE_DETECTION_RADIUS || dist2 < WHALE_DETECTION_RADIUS || dist3 < WHALE_DETECTION_RADIUS) && !submarine_destroyed ) { g_object_set (whale, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); g_object_set (big_explosion, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); submarine_explosion(); } } /* treasure detection */ { gdouble dist1, dist2, dist3; dist1 = hypot( submarine_x -submarine_width/2 -treasure_x, depth+SURFACE_IN_BACKGROUND-treasure_y); dist2 = hypot(submarine_x - submarine_width - treasure_x, depth+SURFACE_IN_BACKGROUND-treasure_y); dist3 = hypot(submarine_x - treasure_x, depth+SURFACE_IN_BACKGROUND-treasure_y); /* magnetic detection (dist1) or collision with the treasure (dist2 & dist3) */ if ( (dist1 < TREASURE_DETECTION_RADIUS || dist2 < TREASURE_DETECTION_RADIUS || dist3 < TREASURE_DETECTION_RADIUS) && !treasure_captured ) { gc_sound_play_ogg("sounds/tuxok.wav", NULL); g_object_set (treasure, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); treasure_captured = TRUE; open_door(); } } return TRUE; }