@Override
  public void applyMoveAction(double s_elapsed) {
    switch (next_action.move) {
      case NONE:
        double move_velocity = Math.hypot(move_x_velocity, move_y_velocity);
        double delta = s_elapsed * SPEED_DECREASE_PER_SECOND * move_x_velocity / move_velocity;
        if (Math.abs(move_x_velocity) > Math.abs(delta)) {
          move_x_velocity -= delta;
        }
        else {
          move_x_velocity = 0.0;
        }
        delta = s_elapsed * SPEED_DECREASE_PER_SECOND * move_y_velocity / move_velocity;
        if (Math.abs(move_y_velocity) > Math.abs(delta)) {
          move_y_velocity -= delta;
        }
        else {
          move_y_velocity = 0.0;
        }
        break;
      case FORWARD:
        double max = move_speed * Math.cos(direction);
        move_x_velocity += SPEED_INCREASE_PER_SECOND * Math.cos(direction) * s_elapsed;
        if (Math.abs(move_x_velocity) > Math.abs(max)) {
          move_x_velocity = max;
        }
        max = move_speed * Math.sin(direction);
        move_y_velocity += SPEED_INCREASE_PER_SECOND * Math.sin(direction) * s_elapsed;
        if (Math.abs(move_y_velocity) > Math.abs(max)) {
          move_y_velocity = max;
        }
        break;
      case BACKWARD:
        max = move_speed * Math.cos(direction);
        move_x_velocity -= SPEED_INCREASE_PER_SECOND * Math.cos(direction) * s_elapsed;
        if (Math.abs(move_x_velocity) > Math.abs(max)) {
          move_x_velocity = -max;
        }
        max = move_speed * Math.sin(direction);
        move_y_velocity -= SPEED_INCREASE_PER_SECOND * Math.sin(direction) * s_elapsed;
        if (Math.abs(move_y_velocity) > Math.abs(max)) {
          move_y_velocity = -max;
        }
        break;
      default:
        throw new DescentMapException("Unexpected MoveDirection: " + next_action.move);
    }
  }