Esempio n. 1
0
    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:

        self.game.read_game_information(packet, self.get_rigid_body_tick(),
                                        self.get_field_info())

        self.controls = SimpleControllerState()

        if not self.action:
            self.action = Reorient(self.my_car)
            self.action.eps_phi = 0.01
            self.action.eps_omega = 0.02

        if self.timer == 0.0:

            # randomly generate a proper orthogonal matrix
            self.action.target_orientation = axis_to_rotation(
                vec3(random.uniform(-2, 2), random.uniform(-2, 2),
                     random.uniform(-2, 2)))

        o = self.action.target_orientation
        f = vec3(o[0, 0], o[1, 0], o[2, 0])
        position = Vector3(0, 0, 1000)
        velocity = Vector3(0, 0, 0)

        car_state = CarState(
            physics=Physics(location=position, velocity=velocity))

        # spawn the ball in front of the desired orientation to visually indicate where we're trying to go
        ball_state = BallState(
            physics=Physics(location=Vector3(500 * f[0], 500 *
                                             f[1], 500 * f[2] + 1000),
                            velocity=Vector3(0, 0, 0),
                            angular_velocity=Vector3(0, 0, 0)))

        self.set_game_state(GameState(ball=ball_state, cars={0: car_state}))

        self.action.step(self.game.time_delta)
        self.controls = self.action.controls

        self.timer += self.game.time_delta
        if self.timer > 2.0:
            self.timer = 0.0

        error = angle_between(self.my_car.orientation,
                              self.action.target_orientation)

        self.renderer.begin_rendering("path")
        red = self.renderer.create_color(255, 230, 30, 30)
        self.renderer.draw_string_2d(50, 50, 3, 3,
                                     f"error: {error:.4f} radians", red)
        self.renderer.draw_string_2d(50, 100, 3, 3,
                                     f"Roll:   {self.controls.roll:+.2f}", red)
        self.renderer.draw_string_2d(50, 150, 3, 3,
                                     f"Pitch: {self.controls.pitch:+.2f}", red)
        self.renderer.draw_string_2d(50, 200, 3, 3,
                                     f"Yaw:  {self.controls.yaw:+.2f}", red)
        self.renderer.end_rendering()

        return self.controls
Esempio n. 2
0
    def __init__(self, car: Car, info: GameInfo, target=None):
        self.drive = Drive(car)
        self.reorient = Reorient(car)

        self.jumping = False
        self.time_for_jump = float("inf")
        self.timer = 0.0

        super().__init__(car, info, target)
Esempio n. 3
0
    def __init__(self, car: Car, jump_when_upside_down=True):
        super().__init__(car)

        self.jump_when_upside_down = jump_when_upside_down
        self.landing = False
        self.reorient = Reorient(self.car)

        self.trajectory: List[vec3] = []
        self.landing_pos: Optional[vec3] = None
Esempio n. 4
0
class AimDodge(AirDodge):
    """
    Execute a regular dodge, but also turn the car towards the target (and slightly more up) before dodging.
    Useful for dodging into the ball.
    """

    def __init__(self, car: Car, duration: float, target: vec3):
        super().__init__(car, duration, target)
        self.reorient = Reorient(car)

    def step(self, dt):
        super().step(dt)

        if not self.jump.finished and not self.car.on_ground:
            target_direction = direction(self.car, self.target + vec3(0, 0, 200))
            up = target_direction * (-1)
            up[2] = 1
            up = normalize(up)
            self.reorient.target_orientation = look_at(target_direction, up)
            self.reorient.step(dt)
            self.controls.pitch = self.reorient.controls.pitch
            self.controls.yaw = self.reorient.controls.yaw
            self.controls.roll = self.reorient.controls.roll
Esempio n. 5
0
class DoubleJumpStrike(Strike):
    def intercept_predicate(self, car, ball):
        return 250 < ball.position[2] < 550

    def __init__(self, car: Car, info: GameInfo, target=None):
        self.drive = Drive(car)
        self.reorient = Reorient(car)

        self.jumping = False
        self.time_for_jump = float("inf")
        self.timer = 0.0

        super().__init__(car, info, target)

    def configure(self, intercept: Intercept):
        super().configure(intercept)
        self.drive.target_pos = ground(intercept.position)
        self.time_for_jump = self.double_jump_time_needed(
            intercept.position[2])

    def interruptible(self) -> bool:
        return not self.jumping and super().interruptible()

    def step(self, dt):
        if self.jumping:
            self.controls = Input()
            # first jump for full 0.2 sec
            if self.timer <= 0.2:
                self.controls.jump = True
            # single tick between jumps
            elif self.timer <= 0.2 + dt * JUMP_FALSE_TICKS:
                self.controls.jump = False
            # second jump
            else:
                self.controls.jump = True
                self.jumping = False
            self.timer += dt

        else:
            self.finished = self.intercept.time < self.info.time

            if self.car.on_ground:
                # manage speed before jump
                distance_to_target = ground_distance(self.car.position,
                                                     self.intercept.position)
                if distance_to_target < MIN_DIST_BEFORE_SPEED_CONTROL:
                    target_speed = distance_to_target / self.time_for_jump
                    self.drive.target_speed = -target_speed if self._should_strike_backwards else target_speed
                    self.drive.step(dt)
                    self.controls = self.drive.controls

                else:
                    super().step(dt)

                # decide when to jump
                ground_vel = ground(self.car.velocity)
                direction_to_target = ground_direction(self.car.position,
                                                       self.intercept.position)
                alignment = dot(normalize(ground_vel), direction_to_target)
                # check alignment
                if alignment >= MIN_ALIGNMENT:
                    # check that speed is correct
                    speed_in_direction = dot(ground_vel, direction_to_target)
                    time_to_target = distance_to_target / speed_in_direction
                    if self.time_for_jump - ALLOWED_TIME_ERROR <= time_to_target <= self.time_for_jump + ALLOWED_TIME_ERROR:
                        self.jumping = True

            # after jump (when the car is in the air)
            else:
                # face the ball for some additional height
                self.reorient.target_orientation = look_at(
                    direction(self.car.position, self.info.ball),
                    vec3(0, 0, 1))
                self.reorient.step(dt)
                self.controls = self.reorient.controls

    @staticmethod
    def double_jump_time_needed(height):
        """Return the time needed for the double jump to reach a given height"""
        # polynomial approximation
        a = 1.872348977E-8 * height * height * height
        b = -1.126747937E-5 * height * height
        c = 3.560647225E-3 * height
        d = -7.446058499E-3
        return a + b + c + d
Esempio n. 6
0
 def __init__(self, car: Car, duration: float, target: vec3):
     super().__init__(car, duration, target)
     self.reorient = Reorient(car)
Esempio n. 7
0
class Recovery(Maneuver):
    """Boost down and try to land smoothly"""
    def __init__(self, car: Car, jump_when_upside_down=True):
        super().__init__(car)

        self.jump_when_upside_down = jump_when_upside_down
        self.landing = False
        self.reorient = Reorient(self.car)

        self.trajectory: List[vec3] = []
        self.landing_pos: Optional[vec3] = None

    def interruptible(self) -> bool:
        return False

    def step(self, dt):
        self.simulate_landing()

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

        self.controls.boost = angle_between(self.car.forward(), vec3(
            0, 0, -1)) < 1.5 and not self.landing
        self.controls.throttle = 1  # in case we're turtling

        # jump if the car is upside down and has wheel contact
        if (self.jump_when_upside_down and self.car.on_ground
                and dot(self.car.up(), vec3(0, 0, 1)) < -0.95):
            self.controls.jump = True
            self.landing = False

        else:
            self.finished = self.car.on_ground

    def simulate_landing(self):
        pos = vec3(self.car.position)
        vel = vec3(self.car.velocity)
        grav = vec3(0, 0, -650)
        self.trajectory = [vec3(pos)]
        self.landing = False
        collision_normal: Optional[vec3] = None

        dt = 1 / 60
        simulation_duration = 0.8
        for i in range(int(simulation_duration / dt)):
            pos += vel * dt
            vel += grav * dt
            if norm(vel) > 2300: vel = normalize(vel) * 2300
            self.trajectory.append(vec3(pos))

            collision_sphere = sphere(pos, 50)
            collision_ray = Field.collide(collision_sphere)
            collision_normal = collision_ray.direction

            if (norm(collision_normal) > 0.0 or pos[2] < 0) and i > 20:
                self.landing = True
                self.landing_pos = pos
                break

        if self.landing:
            u = collision_normal
            f = normalize(vel - dot(vel, u) * u)
            l = normalize(cross(u, f))
            self.reorient.target_orientation = three_vec3_to_mat3(f, l, u)
        else:
            target_direction = normalize(
                normalize(self.car.velocity) - vec3(0, 0, 3))
            self.reorient.target_orientation = look_at(target_direction,
                                                       vec3(0, 0, 1))

    def render(self, draw: DrawingTool):
        if self.landing:
            draw.color(draw.cyan)
            draw.polyline(self.trajectory)

            if self.landing_pos:
                draw.crosshair(self.landing_pos)

        draw.color(draw.green)
        draw.vector(self.car.position,
                    forward(self.reorient.target_orientation) * 200)

        draw.color(draw.red)
        draw.vector(self.car.position, self.car.forward() * 200)