/* ===================================================================== * battery_charger_event * =====================================================================*/ static gboolean battery_charger_event(GooCanvasItem *item, GooCanvas *target, GdkEventButton *event, gpointer data) { if(board_paused || !boardRootItem) return FALSE; gc_sound_play_ogg ("sounds/bleep.wav", NULL); if (battery_charging) battery_charging = FALSE; else battery_charging = TRUE; gc_item_rotate_with_center(item, battery_charging ? 180 : 0 , TRIGGER_CENTER_X, TRIGGER_CENTER_Y ); return FALSE; }
void scale_anim_plate(void) { double delta_y; double angle; double scale; int diff; // in MODE_WEIGHT the granularity is gramm, so we use a different factor scale = (board_mode == MODE_WEIGHT) ? 2000.0 : 10.0; diff = get_weight_plate(0); delta_y = CLAMP(PLATE_Y_DELTA / scale * diff, -PLATE_Y_DELTA, PLATE_Y_DELTA); if(get_weight_plate(1) == 0) delta_y = -PLATE_Y_DELTA; /* Update the sign */ if (diff == 0) g_object_set(sign, "text", "=", NULL); else if (diff < 0) g_object_set(sign, "text", "<", NULL); else g_object_set(sign, "text", ">", NULL); if(last_delta != delta_y) { goo_canvas_item_translate(group_g, 0, -last_delta); goo_canvas_item_translate(group_d, 0, last_delta); last_delta = delta_y; angle = tan(delta_y / 138) * 180 / M_PI; goo_canvas_item_translate(group_g, 0, delta_y); goo_canvas_item_translate(group_d, 0, -delta_y); gc_item_rotate_with_center(bras, -angle, 138, 84); } if(diff == 0 && ask_for_answer) { double x_offset = BOARDWIDTH/2; double y_offset = BOARDHEIGHT*0.7; GooCanvasItem *item = goo_canvas_svg_new (boardRootItem, gc_skin_rsvg_get(), "svg-id", "#BUTTON_TEXT", NULL); SET_ITEM_LOCATION_CENTER(item, x_offset / 2, y_offset); goo_canvas_item_scale(item, 2, 1); answer_item = goo_canvas_text_new(boardRootItem, "", x_offset, y_offset, -1, GTK_ANCHOR_CENTER, "font", gc_skin_font_board_title_bold, "fill-color", "white", NULL); answer_string = g_string_new(NULL); key_press(0, NULL, NULL); } else if(diff == 0) process_ok(); }
/* ===================================================================== * 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; }