class AimDodge(Maneuver): def __init__(self, car: Car, duration: float, target: vec3): super().__init__(car) self.dodge = AirDodge(car, duration, target) self.turn = AerialTurn(car) self.turn.target = look_at(direction(car, target), vec3(0, 0, 1)) self.jump = self.dodge.jump self.target = target def step(self, dt): self.dodge.step(dt) self.controls = self.dodge.controls self.finished = self.dodge.finished if not self.dodge.jump.finished and not self.car.on_ground: target_direction = direction(self.car, self.target + vec3(0, 0, 100)) up = target_direction * (-1) up[2] = 1 up = normalize(up) self.turn.target = look_at(target_direction, up) self.turn.step(dt) self.controls.pitch = self.turn.controls.pitch self.controls.yaw = self.turn.controls.yaw self.controls.roll = self.turn.controls.roll
class CarryAndFlick(Maneuver): """ Carry the ball on roof, and flick it if an opponent is close or if fast enough and facing the target. """ def __init__(self, car: Car, info: GameInfo, target: vec3): super().__init__(car) self.target = target self.info = info self.carry = Carry(car, info.ball, target) self.flick = AirDodge(car, jump_duration=0.1, target=info.ball.position) self.flicking = False def interruptible(self) -> bool: return not self.flicking 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 def render(self, draw: DrawingTool): if not self.flicking: self.carry.render(draw)
class Dribble(Maneuver): ''' Carry the ball on roof, and flick it if an opponent is close or if fast enough and facing the target. ''' def __init__(self, car: Car, info: GameInfo, target: vec3): super().__init__(car) self.target = target self.info = info self.carry = Carry(car, info.ball, target) self.flick = AirDodge(car, 0.15, info.ball.position) self.flicking = False 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 # check if it's a good idea to flick dir_to_target = direction(ground(car.position), ground(self.target)) if (distance(car.position, self.info.ball.position) < 150 and distance(ground(car.position), ground(self.info.ball.position)) < 80 and dot(car.forward(), dir_to_target) > 0.7 and norm(car.velocity) > distance(car, self.target) / 4 and norm(car.velocity) > 1300 and dot( dir_to_target, direction(ground(car.position), ground(self.info.ball.position))) > 0.9): self.flicking = True # flick if opponent is close for opponent in self.info.opponents: if (distance(opponent.position + opponent.velocity, car) < max( 300, norm(opponent.velocity) * 0.5) and dot(opponent.velocity, direction(opponent, self.info.ball)) > 0.5): if distance(car.position, self.info.ball.position) < 350: self.flicking = True else: self.finished = True else: self.flick.step(dt) self.controls = self.flick.controls self.finished = self.flick.finished def render(self, draw: DrawingTool): if not self.flicking: self.carry.render(draw)
class AirHover(Maneuver): ''' Double jump of the ground and hover in the air at target position. Currently useless, but maybe future potential for air-dribbling? ''' P = 1.8 D = 2.5 def __init__(self, car: Car, target: vec3): super().__init__(car) self.turn = AerialTurn(car) self.target = target self.jump = AirDodge(car, 0.2) def step(self, dt): if not self.jump.finished: self.jump.step(dt) self.controls = self.jump.controls return delta_target = self.target - self.car.position target_direction = normalize( vec3((delta_target[0]) * self.P - self.car.velocity[0] * self.D, (delta_target[1]) * self.P - self.car.velocity[1] * self.D, 1000)) self.turn.target = look_at(target_direction, self.car.up()) self.turn.step(dt) self.controls = self.turn.controls self.controls.boost = 0 # tap boost to keep height if (delta_target[2] - self.car.velocity[2] * 0.5) > 0: self.controls.boost = 1 # boost so we don't fall while relocating if dot(self.car.forward(), vec3(0, 0, 1)) < 0.5: self.controls.boost = 1