Пример #1
0
    def execute(self, bot):
        self.is_dribbling = True

        car = bot.info.my_car
        ball = bot.info.ball
        ball_landing = predict.next_ball_landing(bot)
        ball_to_goal = bot.info.enemy_goal - ball.pos

        # Decide on target pos and speed
        target = ball_landing.data["obj"].pos - self.offset_bias * normalize(ball_to_goal)
        dist = norm(target - bot.info.my_car.pos)
        speed = 1400 if ball_landing.time == 0 else dist / ball_landing.time

        # Do a flick?
        car_to_ball = ball.pos - car.pos
        dist = norm(car_to_ball)
        if dist <= self.required_distance_to_ball_for_flick:
            self.flick_timer += 0.016666
            if self.flick_timer > self.wait_before_flick:
                bot.plan = DodgePlan(bot.info.enemy_goal)  # use flick_init_jump_duration?
        else:
            self.flick_timer = 0

            # dodge on far distances
            if dist > 2450 and speed > 1410:
                ctt_n = normalize(target - car.pos)
                vtt = dot(bot.info.my_car.vel, ctt_n) / dot(ctt_n, ctt_n)
                if vtt > 750:
                    bot.plan = DodgePlan(target)

        controls = bot.drive.go_towards_point(bot, target, target_vel=speed, slide=False, boost=False, can_keep_speed=False, can_dodge=True, wall_offset_allowed=0)
        bot.controls = controls

        if bot.do_rendering:
            bot.renderer.draw_line_3d(car.pos, target, bot.renderer.pink())
Пример #2
0
    def go_towards_point(self,
                         bot,
                         point: vec3,
                         target_vel=1430,
                         slide=False,
                         boost=False,
                         can_keep_speed=True,
                         can_dodge=True,
                         wall_offset_allowed=130) -> SimpleControllerState:
        REQUIRED_ANG_FOR_SLIDE = 1.65
        REQUIRED_VELF_FOR_DODGE = 1100

        car = bot.info.my_car

        # Dodge is finished
        if self.dodge is not None and self.dodge.finished:
            self.dodge = None
            self.last_dodge_end_time = bot.info.current_game_time

        # Continue dodge
        if self.dodge is not None:
            self.dodge.target = point
            self.dodge.execute(bot)
            return self.dodge.controls

        # Begin recovery
        if not car.on_ground:
            bot.plan = RecoverPlan()
            return self.controls

        # Get down from wall by choosing a point close to ground
        if not is_near_wall(point, wall_offset_allowed) and angle_between(
                car.up(), vec3(0, 0, 1)) > math.pi * 0.31:
            point = lerp(xy(car.pos), xy(point), 0.5)

        # If the car is in a goal, avoid goal posts
        self.avoid_goal_post(bot, point)

        car_to_point = point - car.pos

        # The vector from the car to the point in local coordinates:
        # point_local[X]: how far in front of my car
        # point_local[Y]: how far to the left of my car
        # point_local[Z]: how far above my car
        point_local = dot(point - car.pos, car.theta)

        # Angle to point in local xy plane and other stuff
        angle = math.atan2(point_local[Y], point_local[X])
        dist = norm(point_local)
        vel_f = proj_onto_size(car.vel, car.forward())
        vel_towards_point = proj_onto_size(car.vel, car_to_point)

        # Start dodge
        if can_dodge and abs(angle) <= 0.02 and vel_towards_point > REQUIRED_VELF_FOR_DODGE\
                and dist > vel_towards_point + 500 + 700 and bot.info.current_game_time > self.last_dodge_end_time + self.dodge_cooldown:
            self.dodge = DodgePlan(point)

        # Is in turn radius deadzone?
        tr = turn_radius(abs(vel_f + 50))  # small bias
        tr_side = sign(angle)
        tr_center_local = vec3(0, tr * tr_side, 0)
        point_is_in_turn_radius_deadzone = norm(point_local -
                                                tr_center_local) < tr
        # Draw turn radius deadzone
        if car.on_ground and bot.do_rendering:
            tr_center_world = car.pos + dot(car.theta, tr_center_local)
            tr_center_world_2 = car.pos + dot(car.theta, -1 * tr_center_local)
            render.draw_circle(bot, tr_center_world, car.up(), tr, 22)
            render.draw_circle(bot, tr_center_world_2, car.up(), tr, 22)

        if point_is_in_turn_radius_deadzone:
            # Hard turn
            self.controls.steer = sign(angle)
            self.controls.boost = False
            self.controls.throttle = 0 if vel_f > 150 else 0.1
            if point_local[X] < 25:
                # Brake or go backwards when the point is really close but not in front of us
                self.controls.throttle = clip((25 - point_local[X]) * -.5, 0,
                                              -0.6)
                self.controls.steer = 0
                if vel_f > 300:
                    self.controls.handbrake = True

        else:
            # Should drop speed or just keep up the speed?
            if can_keep_speed and target_vel < vel_towards_point:
                target_vel = vel_towards_point
            else:
                # Small lerp adjustment
                target_vel = lerp(vel_towards_point, target_vel, 1.2)

            # Turn and maybe slide
            self.controls.steer = clip(angle + (2.5 * angle)**3, -1.0, 1.0)
            if slide and abs(angle) > REQUIRED_ANG_FOR_SLIDE:
                self.controls.handbrake = True
                self.controls.steer = sign(angle)
            else:
                self.controls.handbrake = False

            # Overshoot target vel for quick adjustment
            target_vel = lerp(vel_towards_point, target_vel, 1.2)

            # Find appropriate throttle/boost
            if vel_towards_point < target_vel:
                self.controls.throttle = 1
                if boost and vel_towards_point + 25 < target_vel and target_vel > 1400 \
                        and not self.controls.handbrake and is_heading_towards(angle, dist):
                    self.controls.boost = True
                else:
                    self.controls.boost = False

            else:
                vel_delta = target_vel - vel_towards_point
                self.controls.throttle = clip(0.2 + vel_delta / 500, 0, -1)
                self.controls.boost = False
                if self.controls.handbrake:
                    self.controls.throttle = min(0.4, self.controls.throttle)

        # Saved if something outside calls start_dodge() in the meantime
        self.last_point = point

        return self.controls
Пример #3
0
 def start_dodge(self):
     if self.dodge is None:
         self.dodge = DodgePlan(self.last_point)
Пример #4
0
class DriveController:
    def __init__(self):
        self.controls = SimpleControllerState()
        self.dodge = None
        self.last_point = None
        self.last_dodge_end_time = 0
        self.dodge_cooldown = 0.26
        self.recovery = None

    def start_dodge(self):
        if self.dodge is None:
            self.dodge = DodgePlan(self.last_point)

    def go_towards_point(self,
                         bot,
                         point: vec3,
                         target_vel=1430,
                         slide=False,
                         boost=False,
                         can_keep_speed=True,
                         can_dodge=True,
                         wall_offset_allowed=130) -> SimpleControllerState:
        REQUIRED_ANG_FOR_SLIDE = 1.65
        REQUIRED_VELF_FOR_DODGE = 1100

        car = bot.info.my_car

        # Dodge is finished
        if self.dodge is not None and self.dodge.finished:
            self.dodge = None
            self.last_dodge_end_time = bot.info.current_game_time

        # Continue dodge
        if self.dodge is not None:
            self.dodge.target = point
            self.dodge.execute(bot)
            return self.dodge.controls

        # Begin recovery
        if not car.on_ground:
            bot.plan = RecoverPlan()
            return self.controls

        # Get down from wall by choosing a point close to ground
        if not is_near_wall(point, wall_offset_allowed) and angle_between(
                car.up(), vec3(0, 0, 1)) > math.pi * 0.31:
            point = lerp(xy(car.pos), xy(point), 0.5)

        # If the car is in a goal, avoid goal posts
        self.avoid_goal_post(bot, point)

        car_to_point = point - car.pos

        # The vector from the car to the point in local coordinates:
        # point_local[X]: how far in front of my car
        # point_local[Y]: how far to the left of my car
        # point_local[Z]: how far above my car
        point_local = dot(point - car.pos, car.theta)

        # Angle to point in local xy plane and other stuff
        angle = math.atan2(point_local[Y], point_local[X])
        dist = norm(point_local)
        vel_f = proj_onto_size(car.vel, car.forward())
        vel_towards_point = proj_onto_size(car.vel, car_to_point)

        # Start dodge
        if can_dodge and abs(angle) <= 0.02 and vel_towards_point > REQUIRED_VELF_FOR_DODGE\
                and dist > vel_towards_point + 500 + 700 and bot.info.current_game_time > self.last_dodge_end_time + self.dodge_cooldown:
            self.dodge = DodgePlan(point)

        # Is in turn radius deadzone?
        tr = turn_radius(abs(vel_f + 50))  # small bias
        tr_side = sign(angle)
        tr_center_local = vec3(0, tr * tr_side, 0)
        point_is_in_turn_radius_deadzone = norm(point_local -
                                                tr_center_local) < tr
        # Draw turn radius deadzone
        if car.on_ground and bot.do_rendering:
            tr_center_world = car.pos + dot(car.theta, tr_center_local)
            tr_center_world_2 = car.pos + dot(car.theta, -1 * tr_center_local)
            render.draw_circle(bot, tr_center_world, car.up(), tr, 22)
            render.draw_circle(bot, tr_center_world_2, car.up(), tr, 22)

        if point_is_in_turn_radius_deadzone:
            # Hard turn
            self.controls.steer = sign(angle)
            self.controls.boost = False
            self.controls.throttle = 0 if vel_f > 150 else 0.1
            if point_local[X] < 25:
                # Brake or go backwards when the point is really close but not in front of us
                self.controls.throttle = clip((25 - point_local[X]) * -.5, 0,
                                              -0.6)
                self.controls.steer = 0
                if vel_f > 300:
                    self.controls.handbrake = True

        else:
            # Should drop speed or just keep up the speed?
            if can_keep_speed and target_vel < vel_towards_point:
                target_vel = vel_towards_point
            else:
                # Small lerp adjustment
                target_vel = lerp(vel_towards_point, target_vel, 1.2)

            # Turn and maybe slide
            self.controls.steer = clip(angle + (2.5 * angle)**3, -1.0, 1.0)
            if slide and abs(angle) > REQUIRED_ANG_FOR_SLIDE:
                self.controls.handbrake = True
                self.controls.steer = sign(angle)
            else:
                self.controls.handbrake = False

            # Overshoot target vel for quick adjustment
            target_vel = lerp(vel_towards_point, target_vel, 1.2)

            # Find appropriate throttle/boost
            if vel_towards_point < target_vel:
                self.controls.throttle = 1
                if boost and vel_towards_point + 25 < target_vel and target_vel > 1400 \
                        and not self.controls.handbrake and is_heading_towards(angle, dist):
                    self.controls.boost = True
                else:
                    self.controls.boost = False

            else:
                vel_delta = target_vel - vel_towards_point
                self.controls.throttle = clip(0.2 + vel_delta / 500, 0, -1)
                self.controls.boost = False
                if self.controls.handbrake:
                    self.controls.throttle = min(0.4, self.controls.throttle)

        # Saved if something outside calls start_dodge() in the meantime
        self.last_point = point

        return self.controls

    def avoid_goal_post(self, bot, point):
        car = bot.info.my_car
        car_to_point = point - car.pos

        # Car is not in goal, not adjustment needed
        if abs(car.pos[Y]) < FIELD_LENGTH / 2:
            return

        # Car can go straight, not adjustment needed
        if car_to_point[X] == 0:
            return

        # Do we need to cross a goal post to get to the point?
        goalx = GOAL_WIDTH / 2 - 100
        goaly = FIELD_LENGTH / 2 - 100
        t = max((goalx - car.pos[X]) / car_to_point[X],
                (-goalx - car.pos[X]) / car_to_point[X])
        # This is the y coordinate when car would hit a goal wall. Is that inside the goal?
        crossing_goalx_at_y = abs(car.pos[Y] + t * car_to_point[Y])
        if crossing_goalx_at_y > goaly:
            # Adjustment is needed
            point[X] = clip(point[X], -goalx, goalx)
            point[Y] = clip(point[Y], -goaly, goaly)
            if bot.do_rendering:
                bot.renderer.draw_line_3d(car.pos, point, bot.renderer.green())

    def go_home(self, bot):
        car = bot.info.my_car
        home = bot.info.own_goal
        target = home

        closest_enemy, enemy_dist = bot.info.closest_enemy(bot.info.ball.pos)

        car_to_home = home - car.pos
        dist = norm(car_to_home)
        vel_f_home = proj_onto_size(car.vel, car_to_home)

        if vel_f_home * 2 > dist:
            target = bot.info.ball.pos

        boost = dist > 1500 or enemy_dist < dist
        dodge = dist > 1500 or enemy_dist < dist

        return self.go_towards_point(bot,
                                     target,
                                     2300,
                                     True,
                                     boost=boost,
                                     can_dodge=dodge)