class Arrive(Maneuver): def __init__(self, car: Car, target=vec3(0, 0, 0), time=0, target_direction: vec3 = None): super().__init__(car) self.target_direction = target_direction self.target = target self.time = time self.drive = Drive(car, target) self.travel = Travel(car) self.lerp_t = 0.6 def step(self, dt): target = self.target car = self.car if self.target_direction is not None: car_vel = norm(car.vel) target_direction = normalize(self.target_direction) shift = clamp( distance(car.pos, target) * self.lerp_t, 0, car_vel * 1.5) if shift < turn_radius(clamp(car_vel, 1400, 2000) * 1.1): shift = 0 translated_target = target - target_direction * shift translated_time = self.time - distance( translated_target, target) / max(1, clamp(car_vel, 500, 2300)) else: translated_target = target translated_time = self.time self.drive.target_pos = translated_target dist_to_target = distance(car.pos, translated_target) target_speed = clamp( dist_to_target / max(0.001, translated_time - car.time), 0, 2300) self.drive.target_speed = target_speed if car.boost < 1 and dist_to_target > 3000: self.travel.target = target self.travel.step(dt) self.controls = self.travel.controls else: self.drive.step(dt) self.controls = self.drive.controls self.finished = self.car.time >= self.time return self.finished def render(self, draw: DrawingTool): self.drive.render(draw) if self.target_direction is not None: draw.color(draw.lime) draw.triangle(self.target - self.target_direction * 250, self.target_direction)
class Arrive(Maneuver): """ Arrive at a target position at a certain time (game seconds). You can also specify `target_direction`, and it will try to arrive at an angle. However this does work well only if the car is already roughly facing the specified direction, and only if it's far enough. """ def __init__(self, car: Car): super().__init__(car) self.drive = Drive(car) self.travel = Travel(car) self.action = self.drive self.target_direction: Optional[None] = None self.target: vec3 = None self.arrival_time: float = 0 self.backwards: bool = False self.lerp_t = 0.57 self.allow_dodges_and_wavedashes: bool = True self.additional_shift = 0 def interruptible(self) -> bool: return self.action.interruptible() 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 < 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 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 def render(self, draw: DrawingTool): self.drive.render(draw) if self.target_direction is not None: draw.color(draw.lime) draw.triangle(self.target - self.target_direction * 250, self.target_direction)
class Arrive(Maneuver): ''' Arrive at a target position at a certain time (game seconds). You can also specify `target_direction`, and it will try to arrive at an angle. However this does work well only if the car is already roughly facing the specified direction, and only if it's far enough. ''' def __init__(self, car: Car): super().__init__(car) self.target_direction: vec3 = None self.target: vec3 = None self.time: float = 0 self.drive = Drive(car) self.travel = Travel(car) self.lerp_t = 0.6 self.allow_dodges_and_wavedashes: bool = True self.additional_shift = 0 def step(self, dt): target = self.target car = self.car if self.target_direction is not None: car_vel = norm(car.velocity) target_direction = normalize(self.target_direction) shift = clamp( distance(car.position, target) * self.lerp_t, 0, car_vel * 1.5) if shift - self.additional_shift < turn_radius( clamp(car_vel, 1400, 2000) * 1.1): shift = 0 else: shift += self.additional_shift translated_target = target - target_direction * shift translated_time = self.time - distance( translated_target, target) * 0.7 / max( 1, clamp(car_vel, 500, 2300)) else: translated_target = target translated_time = self.time self.drive.target_pos = translated_target dist_to_target = distance(car.position, translated_target) target_speed = clamp( dist_to_target / max(0.001, translated_time - car.time), 0, 2300) self.drive.target_speed = target_speed if (self.allow_dodges_and_wavedashes and car.boost < 5 and dist_to_target > clamp(norm(car.velocity) + 600, 1400, 2300) and norm(car.velocity) < target_speed - 600 or not self.travel.driving): self.travel.target = target self.travel.step(dt) self.controls = self.travel.controls else: self.drive.step(dt) self.controls = self.drive.controls self.finished = self.car.time >= self.time return self.finished def render(self, draw: DrawingTool): self.drive.render(draw) if self.target_direction is not None: draw.color(draw.lime) draw.triangle(self.target - self.target_direction * 250, self.target_direction)