Ejemplo n.º 1
0
void
Camera::reset(const Vector& tuxpos)
{
  translation.x = tuxpos.x - SCREEN_WIDTH/3 * 2;
  translation.y = tuxpos.y - SCREEN_HEIGHT/2;
  shakespeed = 0;
  shaketimer.stop();
  keep_in_bounds(translation);
}
Ejemplo n.º 2
0
void
Camera::update_scroll_autoscroll(float elapsed_time)
{
  Player* player = sector->player;
  if(player->is_dying())
    return;

  translation = autoscroll_walker->advance(elapsed_time);

  keep_in_bounds(translation);
}
Ejemplo n.º 3
0
void
Camera::scroll_to(const Vector& goal, float scrolltime)
{
  scroll_from = translation;
  scroll_goal = goal;
  keep_in_bounds(scroll_goal);

  scroll_to_pos = 0;
  scrollspeed = 1.0 / scrolltime;
  mode = SCROLLTO;
}
Ejemplo n.º 4
0
void
Camera::update_scroll_normal(float elapsed_time)
{
  const CameraConfig& config = *(this->config);
  Player* player = sector->player;
  // TODO: co-op mode needs a good camera
  Vector player_pos(player->get_bbox().get_middle().x,
                                    player->get_bbox().get_bottom());
  static Vector last_player_pos = player_pos;
  Vector player_delta = player_pos - last_player_pos;
  last_player_pos = player_pos;

  // check that we don't have division by zero later
  if(elapsed_time < CAMERA_EPSILON)
    return;

  /****** Vertical Scrolling part ******/
  int ymode = config.ymode;

  if(player->is_dying() || sector->get_height() == 19*32) {
    ymode = 0;
  }
  if(ymode == 1) {
    cached_translation.y = player_pos.y - SCREEN_HEIGHT * config.target_y;
  }
  if(ymode == 2) {
    // target_y is the high we target our scrolling at. This is not always the
    // high of the player, but if he is jumping upwards we should use the
    // position where he last touched the ground. (this probably needs
    // exceptions for trampolines and similar things in the future)
    float target_y;
    if(player->fall_mode == Player::JUMPING)
      target_y = player->last_ground_y + player->get_bbox().get_height();
    else
      target_y = player->get_bbox().p2.y;
    target_y -= SCREEN_HEIGHT * config.target_y;

    // delta_y is the distance we'd have to travel to directly reach target_y
    float delta_y = cached_translation.y - target_y;
    // speed is the speed the camera would need to reach target_y in this frame
    float speed_y = delta_y / elapsed_time;

    // limit the camera speed when jumping upwards
    if(player->fall_mode != Player::FALLING
       && player->fall_mode != Player::TRAMPOLINE_JUMP) {
      speed_y = clamp(speed_y, -config.max_speed_y, config.max_speed_y);
    }

    // scroll with calculated speed
    cached_translation.y -= speed_y * elapsed_time;
  }
  if(ymode == 3) {
    float halfsize = config.kirby_rectsize_y * 0.5f;
    cached_translation.y = clamp(cached_translation.y,
                                 player_pos.y - SCREEN_HEIGHT * (0.5f + halfsize),
                                 player_pos.y - SCREEN_HEIGHT * (0.5f - halfsize));
  }
  if(ymode == 4) {
    float upperend = SCREEN_HEIGHT * config.edge_x;
    float lowerend = SCREEN_HEIGHT * (1 - config.edge_x);

    if (player_delta.y < -CAMERA_EPSILON) {
      // walking left
      lookahead_pos.y -= player_delta.y * config.dynamic_speed_sm;

      if(lookahead_pos.y > lowerend) {
        lookahead_pos.y = lowerend;
      }
    } else if (player_delta.y > CAMERA_EPSILON) {
      // walking right
      lookahead_pos.y -= player_delta.y * config.dynamic_speed_sm;
      if(lookahead_pos.y < upperend) {
        lookahead_pos.y = upperend;
      }
    }

    // adjust for level ends
    if (player_pos.y < upperend) {
      lookahead_pos.y = upperend;
    }
    if (player_pos.y > sector->get_width() - upperend) {
      lookahead_pos.y = lowerend;
    }

    cached_translation.y = player_pos.y - lookahead_pos.y;
  }

  translation.y = cached_translation.y;

  if(ymode != 0) {
    float top_edge, bottom_edge;
    if(config.clamp_y <= 0) {
      top_edge = 0;
      bottom_edge = SCREEN_HEIGHT;
    } else {
      top_edge = SCREEN_HEIGHT*config.clamp_y;
      bottom_edge = SCREEN_HEIGHT*(1-config.clamp_y);
    }

    float peek_to = 0;
    float translation_compensation = player_pos.y - translation.y;

    if(player->peeking_direction_y() == ::UP) {
      peek_to = bottom_edge - translation_compensation;
    } else if(player->peeking_direction_y() == ::DOWN) {
      peek_to = top_edge - translation_compensation;
    }

    float peek_move = (peek_to - peek_pos.y) * PEEK_ARRIVE_RATIO;
    if(fabs(peek_move) < 1.0) {
      peek_move = 0.0;
    }

    peek_pos.y += peek_move;

    translation.y -= peek_pos.y;

    if(config.clamp_y > 0) {
      translation.y = clamp(translation.y,
                            player_pos.y - SCREEN_HEIGHT * (1-config.clamp_y),
                            player_pos.y - SCREEN_HEIGHT * config.clamp_y);
      cached_translation.y = clamp(cached_translation.y,
                                   player_pos.y - SCREEN_HEIGHT * (1-config.clamp_y),
                                   player_pos.y - SCREEN_HEIGHT * config.clamp_y);
    }
  }

  /****** Horizontal scrolling part *******/
  int xmode = config.xmode;

  if(player->is_dying())
    xmode = 0;

  if(xmode == 1) {
    cached_translation.x = player_pos.x - SCREEN_WIDTH * config.target_x;
  }
  if(xmode == 2) {
    // our camera is either in leftscrolling, rightscrolling or
    // nonscrollingmode.
    //
    // when suddenly changing directions while scrolling into the other
    // direction abort scrolling, since tux might be going left/right at a
    // relatively small part of the map (like when jumping upwards)

    // Find out direction in which the player moves
    LookaheadMode walkDirection;
    if (player_delta.x < -CAMERA_EPSILON) walkDirection = LOOKAHEAD_LEFT;
    else if (player_delta.x > CAMERA_EPSILON) walkDirection = LOOKAHEAD_RIGHT;
    else if (player->dir == ::LEFT) walkDirection = LOOKAHEAD_LEFT;
    else walkDirection = LOOKAHEAD_RIGHT;

    float LEFTEND, RIGHTEND;
    if(config.sensitive_x > 0) {
      LEFTEND = SCREEN_WIDTH * config.sensitive_x;
      RIGHTEND = SCREEN_WIDTH * (1-config.sensitive_x);
    } else {
      LEFTEND = SCREEN_WIDTH;
      RIGHTEND = 0;
    }

    if(lookahead_mode == LOOKAHEAD_NONE) {
      /* if we're undecided then look if we crossed the left or right
       * "sensitive" area */
      if(player_pos.x < cached_translation.x + LEFTEND) {
        lookahead_mode = LOOKAHEAD_LEFT;
      } else if(player_pos.x > cached_translation.x + RIGHTEND) {
        lookahead_mode = LOOKAHEAD_RIGHT;
      }
      /* at the ends of a level it's obvious which way we will go */
      if(player_pos.x < SCREEN_WIDTH*0.5) {
        lookahead_mode = LOOKAHEAD_RIGHT;
      } else if(player_pos.x >= sector->get_width() - SCREEN_WIDTH*0.5) {
        lookahead_mode = LOOKAHEAD_LEFT;
      }

      changetime = -1;
    } else if(lookahead_mode != walkDirection) {
      /* player changed direction while camera was scrolling...
       * he has to do this for a certain time to add robustness against
       * sudden changes */
      if(changetime < 0) {
        changetime = game_time;
      } else if(game_time - changetime > config.dirchange_time) {
        if(lookahead_mode == LOOKAHEAD_LEFT &&
           player_pos.x > cached_translation.x + RIGHTEND) {
          lookahead_mode = LOOKAHEAD_RIGHT;
        } else if(lookahead_mode == LOOKAHEAD_RIGHT &&
                  player_pos.x < cached_translation.x + LEFTEND) {
          lookahead_mode = LOOKAHEAD_LEFT;
        } else {
          lookahead_mode = LOOKAHEAD_NONE;
        }
      }
    } else {
      changetime = -1;
    }

    LEFTEND = SCREEN_WIDTH * config.edge_x;
    RIGHTEND = SCREEN_WIDTH * (1-config.edge_x);

    // calculate our scroll target depending on scroll mode
    float target_x;
    if(lookahead_mode == LOOKAHEAD_LEFT)
      target_x = player_pos.x - RIGHTEND;
    else if(lookahead_mode == LOOKAHEAD_RIGHT)
      target_x = player_pos.x - LEFTEND;
    else
      target_x = cached_translation.x;

    // that's the distance we would have to travel to reach target_x
    float delta_x = cached_translation.x - target_x;
    // the speed we'd need to travel to reach target_x in this frame
    float speed_x = delta_x / elapsed_time;

    // limit our speed
    float player_speed_x = player_delta.x / elapsed_time;
    float maxv = config.max_speed_x + (fabsf(player_speed_x * config.dynamic_max_speed_x));
    speed_x = clamp(speed_x, -maxv, maxv);

    // apply scrolling
    cached_translation.x -= speed_x * elapsed_time;
  }
  if(xmode == 3) {
    float halfsize = config.kirby_rectsize_x * 0.5f;
    cached_translation.x = clamp(cached_translation.x,
                                 player_pos.x - SCREEN_WIDTH * (0.5f + halfsize),
                                 player_pos.x - SCREEN_WIDTH * (0.5f - halfsize));
  }
  if(xmode == 4) {
    float LEFTEND = SCREEN_WIDTH * config.edge_x;
    float RIGHTEND = SCREEN_WIDTH * (1 - config.edge_x);

    if (player_delta.x < -CAMERA_EPSILON) {
      // walking left
      lookahead_pos.x -= player_delta.x * config.dynamic_speed_sm;
      if(lookahead_pos.x > RIGHTEND) {
        lookahead_pos.x = RIGHTEND;
      }

    } else if (player_delta.x > CAMERA_EPSILON) {
      // walking right
      lookahead_pos.x -= player_delta.x * config.dynamic_speed_sm;
      if(lookahead_pos.x < LEFTEND) {
        lookahead_pos.x = LEFTEND;
      }
    }

    // adjust for level ends
    if (player_pos.x < LEFTEND) {
      lookahead_pos.x = LEFTEND;
    }
    if (player_pos.x > sector->get_width() - LEFTEND) {
      lookahead_pos.x = RIGHTEND;
    }

    cached_translation.x = player_pos.x - lookahead_pos.x;
  }

  translation.x = cached_translation.x;

  if(xmode != 0) {
    float left_edge, right_edge;
    if(config.clamp_x <= 0) {
      left_edge = 0;
      right_edge = SCREEN_WIDTH;
    } else {
      left_edge = SCREEN_WIDTH*config.clamp_x;
      right_edge = SCREEN_WIDTH*(1-config.clamp_x);
    }

    float peek_to = 0;
    float translation_compensation = player_pos.x - translation.x;

    if(player->peeking_direction_x() == ::LEFT) {
      peek_to = right_edge - translation_compensation;
    } else if(player->peeking_direction_x() == ::RIGHT) {
      peek_to = left_edge - translation_compensation;
    }

    float peek_move = (peek_to - peek_pos.x) * PEEK_ARRIVE_RATIO;
    if(fabs(peek_move) < 1.0) {
      peek_move = 0.0;
    }

    peek_pos.x += peek_move;

    translation.x -= peek_pos.x;

    if(config.clamp_x > 0) {
      translation.x = clamp(translation.x,
                            player_pos.x - SCREEN_WIDTH * (1-config.clamp_x),
                            player_pos.x - SCREEN_WIDTH * config.clamp_x);

      cached_translation.x = clamp(cached_translation.x,
                                   player_pos.x - SCREEN_WIDTH * (1-config.clamp_x),
                                   player_pos.x - SCREEN_WIDTH * config.clamp_x);
    }
  }

  keep_in_bounds(translation);
  keep_in_bounds(cached_translation);
}
Ejemplo n.º 5
0
void
Camera::update_scroll_normal(float elapsed_time)
{
  assert(sector != 0);
  Player* player = sector->player;
  
  // check that we don't have division by zero later
  if(elapsed_time < EPSILON)
    return;

  /****** Vertical Scrolling part ******/
  bool do_y_scrolling = true;

  if(player->is_dying() || sector->solids->get_height() == 19)
    do_y_scrolling = false;

  if(do_y_scrolling) {
    // target_y is the high we target our scrolling at. This is not always the
    // high of the player, but if he is jumping upwards we should use the
    // position where he last touched the ground. (this probably needs
    // exceptions for trampolines and similar things in the future)
    float target_y;
    if(player->fall_mode == Player::JUMPING)
      target_y = player->last_ground_y + player->get_bbox().get_height();
    else
      target_y = player->get_bbox().p2.y;

    // delta_y is the distance we'd have to travel to directly reach target_y
    float delta_y = translation.y - (target_y - SCREEN_HEIGHT*2/3);
    // speed is the speed the camera would need to reach target_y in this frame
    float speed_y = delta_y / elapsed_time;

    // limit the camera speed when jumping upwards
    if(player->fall_mode != Player::FALLING 
        && player->fall_mode != Player::TRAMPOLINE_JUMP) {
      if(speed_y > max_speed_y)
        speed_y = max_speed_y;
      else if(speed_y < -max_speed_y)
        speed_y = -max_speed_y;
    }

    // finally scroll with calculated speed
    translation.y -= speed_y * elapsed_time;
  }

  /****** Horizontal scrolling part *******/

  // our camera is either in leftscrolling, rightscrolling or nonscrollingmode.
  
  // when suddenly changing directions while scrolling into the other direction.
  // abort scrolling, since tux might be going left/right at a relatively small
  // part of the map (like when jumping upwards)
  if((player->dir == ::LEFT && scrollchange == RIGHT)
      || (player->dir == ::RIGHT && scrollchange == LEFT))
    scrollchange = NONE;
  // when in left 1/3rd of screen scroll left
  if(player->get_bbox().get_middle().x < translation.x + SCREEN_WIDTH/3 - 16
      && do_backscrolling)
    scrollchange = LEFT;
  // scroll right when in right 1/3rd of screen
  else if(player->get_bbox().get_middle().x > translation.x + SCREEN_WIDTH/3*2+16)
    scrollchange = RIGHT;

  // calculate our scroll target depending on scroll mode
  float target_x;
  if(scrollchange == LEFT)
    target_x = player->get_bbox().get_middle().x - SCREEN_WIDTH/3*2;
  else if(scrollchange == RIGHT)
    target_x = player->get_bbox().get_middle().x - SCREEN_WIDTH/3;
  else
    target_x = translation.x;

  // that's the distance we would have to travel to reach target_x
  float delta_x = translation.x - target_x;
  // the speed we'd need to travel to reach target_x in this frame
  float speed_x = delta_x / elapsed_time;

  // limit our speed
  float maxv = 130 + (fabsf(player->physic.get_velocity_x() * 1.3));
  if(speed_x > maxv)
    speed_x = maxv;
  else if(speed_x < -maxv)
    speed_x = -maxv;
 
  // apply scrolling
  translation.x -= speed_x * elapsed_time;

  keep_in_bounds(translation);
  shake();
}