Ejemplo n.º 1
0
    def step(self, dt):
        ball = Ball(self.ball)
        car = self.car

        # simulate ball until it gets near the floor
        while (ball.position[2] > 120 or ball.velocity[2] > 0) and ball.time < car.time + 10:
            ball.step(1/60)

        ball_local = local(car, ground(ball.position))
        target = local(car, self.target)

        shift = ground(direction(ball_local, target))
        shift[1] *= 1.8
        shift = normalize(shift)
        
        max_turn = clamp(norm(car.velocity) / 800, 0, 1)
        max_shift = normalize(vec3(1 - max_turn, max_turn * sign(shift[1]), 0))

        if abs(shift[1]) > abs(max_shift[1]) or shift[0] < 0:
            shift = max_shift
        shift *= clamp(car.boost, 40, 60)

        shift[1] *= clamp(norm(car.velocity)/1000, 1, 2)

        self._shift_direction = normalize(world(car, shift) - car.position)

        target = world(car, ball_local - shift)
        speed = distance(car.position, target) / max(0.001, ball.time - car.time)

        self.drive.target_speed = speed
        self.drive.target_pos = target

        self.drive.step(dt)
        self.controls = self.drive.controls
        self.finished = self.ball.position[2] < 100 or ground_distance(self.ball, self.car) > 2000
Ejemplo n.º 2
0
    def step(self, dt):
        target = self.target
        car = self.car

        if self.target_direction is not None:
            car_speed = norm(car.velocity)
            target_direction = normalize(self.target_direction)

            # in order to arrive in a direction, we need to shift the target in the opposite direction
            # the magnitude of the shift is based on how far are we from the target
            shift = clamp(
                ground_distance(car.position, target) * self.lerp_t, 0,
                car_speed * 1.5)

            # if we're too close to the target, aim for the actual target so we don't miss it
            if shift - self.additional_shift < Drive.turn_radius(
                    clamp(car_speed, 1400, 2000) * 1.1):
                shift = 0
            else:
                shift += self.additional_shift

            shifted_target = target - target_direction * shift

            time_shift = ground_distance(shifted_target, target) * 0.7 / clamp(
                car_speed, 500, 2300)
            shifted_arrival_time = self.arrival_time - time_shift

        else:
            shifted_target = target
            shifted_arrival_time = self.arrival_time

        self.drive.target_pos = shifted_target
        self.travel.target = shifted_target

        dist_to_target = ground_distance(car.position, shifted_target)
        time_left = nonzero(shifted_arrival_time - car.time)
        target_speed = clamp(dist_to_target / time_left, 0, 2300)
        self.drive.target_speed = target_speed
        self.drive.backwards = self.backwards

        # dodges and wavedashes can mess up correctly arriving, so we use them only if we really need them
        if ((self.allow_dodges_and_wavedashes
             and norm(car.velocity) < target_speed - 600 and car.boost < 20
             and not self.backwards)
                or not self.travel.driving  # a dodge/wavedash is in progress
            ):
            self.action = self.travel
        else:
            self.action = self.drive

        self.action.step(dt)
        self.controls = self.action.controls

        self.finished = self.car.time >= self.arrival_time
Ejemplo n.º 3
0
    def step(self, dt):
        if not self.flicking:
            self.carry.step(dt)
            self.controls = self.carry.controls
            self.finished = self.carry.finished
            car = self.car
            ball = self.info.ball

            # check if it's a good idea to flick
            dir_to_target = ground_direction(car, self.target)
            if (distance(car, ball) < 150 and ground_distance(car, ball) < 100
                    and dot(car.forward(), dir_to_target) > 0.7
                    and norm(car.velocity) > clamp(
                        distance(car, self.target) / 3, 1000, 1700)
                    and dot(dir_to_target, ground_direction(car, ball)) > 0.9):
                self.flicking = True

            # flick if opponent is close
            for opponent in self.info.get_opponents():
                if (distance(opponent.position + opponent.velocity, car) < max(
                        300.0,
                        norm(opponent.velocity) * 0.5)
                        and dot(opponent.velocity,
                                direction(opponent, self.info.ball)) > 0.5):
                    if distance(car.position, self.info.ball.position) < 200:
                        self.flicking = True
                    else:
                        self.finished = True
        else:
            self.flick.target = self.info.ball.position + self.info.ball.velocity * 0.2
            self.flick.step(dt)
            self.controls = self.flick.controls
            self.finished = self.flick.finished
Ejemplo n.º 4
0
    def circle(self, pos: vec3, radius: float):
        segments = int(clamp(radius / 20, 10, 50))
        step = 2 * math.pi / segments
        points = []

        for i in range(segments):
            angle = step * i
            points.append(pos +
                          vec3(math.cos(angle), math.sin(angle), 0) * radius)

        self.closed_polyline(points)
Ejemplo n.º 5
0
    def arc(self, pos: vec3, radius: float, start_angle: float,
            end_angle: float):
        segments = int(
            clamp(radius * abs(start_angle - end_angle) / 20, 10, 50))
        step = (end_angle - start_angle) / segments
        points = []

        for i in range(segments + 1):
            angle = start_angle + step * i
            points.append(
                pos +
                vec3(math.cos(angle) * radius,
                     math.sin(angle) * radius, 0))

        self.polyline(points)
Ejemplo n.º 6
0
    def configure(self, intercept: Intercept):
        super().configure(intercept)

        ball = intercept.ball
        target_direction = ground_direction(ball, self.target)
        hit_dir = ground_direction(ball.velocity, target_direction * 4000)

        self.arrive.target = intercept.ground_pos - hit_dir * 100
        self.arrive.target_direction = hit_dir

        additional_jump = clamp(
            (ball.position[2] - 92) / 500, 0, 1.5) * self.jump_time_multiplier
        self.dodge.jump.duration = 0.05 + additional_jump
        self.dodge.target = intercept.ball.position
        self.arrive.additional_shift = additional_jump * 500
Ejemplo n.º 7
0
 def turn_radius(speed: float) -> float:
     spd = clamp(speed, 0, 2300)
     return 156 + 0.1 * spd + 0.000069 * spd**2 + 0.000000164 * spd**3 + -5.62E-11 * spd**4
Ejemplo n.º 8
0
 def get_jump_duration(self, ball_height: float) -> float:
     return 0.05 + clamp(
         (ball_height - 92) / 500, 0, 1.5) * self.jump_time_multiplier
Ejemplo n.º 9
0
def estimate_max_car_speed(car: Car):
    return clamp(max(norm(car.velocity), 1300) + car.boost * 100, 1600, 2300)