Example #1
0
/* =====================================================================
 * 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;
}
Example #2
0
/* =====================================================================
 * 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;
}