def step(self, dt): car = self.car if self.phase == 1: if norm(car.velocity) > 1400: self.phase = 2 self.action = AirDodge(car, 0.05, car.position + car.velocity) if self.phase == 2: self.action.controls.boost = self.action.state_timer < 0.1 if car.on_ground and self.action.finished: self.action = self.drive self.phase = 3 if self.phase == 3: if distance(car, vec3(0, 0, 93)) < norm(car.velocity) * 0.4: self.phase = 4 self.action = AirDodge(car, 0.05, self.info.ball.position) self.counter_fake_kickoff() if self.phase == 4: if self.action.finished: self.finished = True super().step(dt)
def avoid_demos_and_team_bumps(self, drones: List[Drone]): collisions = self.info.detect_collisions(time_limit=0.2, dt=1 / 60) drones_by_index: Dict[int, Drone] = { drone.index: drone for drone in drones } for collision in collisions: index1, index2, time = collision self.logger.debug( f"Collision: {index1} ->*<- {index2} in {time:.2f} seconds.") # avoid team bumps if index1 in drones_by_index and index2 in drones_by_index: if drones_by_index[index1] is self.drone_going_for_ball: drones_by_index[index2].controls.jump = drones_by_index[ index2].car.on_ground else: drones_by_index[index1].controls.jump = drones_by_index[ index1].car.on_ground # TODO: if both drones aren't going for ball, decide which one is the better choice for jumping # dodge demolitions # TODO: Refactor so there's no duplicate code elif index1 in drones_by_index: opponent = self.info.cars[index2] if norm(opponent.velocity) > 2000: drones_by_index[index1].controls.jump = drones_by_index[ index1].car.on_ground elif index2 in drones_by_index: opponent = self.info.cars[index1] if norm(opponent.velocity) > 2000: drones_by_index[index2].controls.jump = drones_by_index[ index2].car.on_ground
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 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.aerial_turn.target = three_vec3_to_mat3(f, l, u) else: target_direction = normalize( normalize(self.car.velocity) - vec3(0, 0, 3)) self.aerial_turn.target = look_at(target_direction, vec3(0, 0, 1))
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
def update_status(self, info: Game): if norm(info.ball.location) > 140 and norm( info.ball.location) > 9: # this only works for soccar if norm(info.ball.location - info.my_car.location) < 240: self.finished = True else: self.failed = True
def get_intersect(agent, car): ball_prediction = agent.get_ball_prediction_struct() intercept_time = (norm(agent.info.ball.position - car.position) - 200) / max(1, int(norm(car.velocity))) intercept_index = cap(int(intercept_time * 60), 0, ball_prediction.num_slices - 1) intercept_location = ball_prediction.slices[ intercept_index].physics.location return vec3(intercept_location.x, intercept_location.y, intercept_location.z)
def step(self, dt): if self.aerialing: self.aerial.target_orientation = look_at( direction(self.car, self.target), vec3(0, 0, -1)) self.aerial.step(dt) self.controls = self.aerial.controls self.finished = self.aerial.finished else: super().step(dt) # simulate aerial from current state simulated_car = self.simulate_flight(self.car) # if the car ended up too far, we're too fast and we need to slow down if ground_distance(self.car, self.aerial.target) + 100 < ground_distance( self.car, simulated_car): # self.controls.throttle = -1 pass # if it ended up near the target, we could take off elif distance(simulated_car, self.aerial.target) < self.MAX_DISTANCE_ERROR: if angle_to(self.car, self.aerial.target) < 0.1 or norm( self.car.velocity) < 1000: if self.DELAY_TAKEOFF: # extrapolate current state a small amount of time future_car = Car(self.car) time = 0.2 future_car.time += time displacement = future_car.velocity * time if norm(future_car.velocity) > 500\ else normalize(future_car.velocity) * 500 * time future_car.position += displacement # simulate aerial fot the extrapolated car again future_simulated_car = self.simulate_flight( future_car, write_to_flight_path=False) # if the aerial is also successful, that means we should continue driving instead of taking off # this makes sure that we go for the most late possible aerials, which are the most effective if distance( future_simulated_car, self.aerial.target) > self.MAX_DISTANCE_ERROR: self.aerialing = True else: self.too_early = True else: self.aerialing = True else: # self.controls.boost = True self.controls.throttle = 1
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
def estimate_time(car: Car, target, dd=1) -> float: turning_radius = 1 / Drive.max_turning_curvature(norm(car.velocity) + 500) turning = angle_between(car.forward() * dd, direction( car, target)) * turning_radius / 1800 if turning < 0.5: turning = 0 dist = ground_distance(car, target) - 200 if dist < 0: return turning speed = dot(car.velocity, car.forward()) time = 0 result = None if car.boost > 0 and dd > 0: boost_time = car.boost / 33.33 result = BOOST.simulate_until_limit(speed, distance_limit=dist, time_limit=boost_time) dist -= result.distance_traveled time += result.time_passed speed = result.speed_reached if dist > 0 and speed < 1410: result = THROTTLE.simulate_until_limit(speed, distance_limit=dist) dist -= result.distance_traveled time += result.time_passed speed = result.speed_reached if result is None or not result.distance_limit_reached: time += dist / speed return time * 1.05 + turning
def step(self, dt: float): # Always throttle. self.controls.throttle = 1.0 # Use boost if should after first jump and not supersonic. speed = norm(self.car.velocity) self.controls.boost = ( # self.use_boost and self.timer > FIRST_JUMP_DURATION and speed < 2250 self.use_boost and speed < 2290) if self.timer < FIRST_JUMP_DURATION: self.controls.jump = True self.controls.pitch = 1.0 elif self.timer < FIRST_JUMP_DURATION + BETWEEN_JUMPS_DELAY: self.controls.jump = False self.controls.pitch = 1.0 elif (self.timer < FIRST_JUMP_DURATION + BETWEEN_JUMPS_DELAY + SECOND_JUMP_DURATION): self.controls.jump = True self.controls.pitch = -1.0 self.controls.roll = -0.3 * self.direction else: self.controls.jump = False self.controls.pitch = 1.0 self.controls.roll = -1.0 * self.direction self.controls.yaw = -1.0 * self.direction self.timer += dt self.finished = (self.timer > TIMEOUT) or (self.car.on_ground and self.timer > 0.5)
def simulate_landing(self): dummy = Car(self.car) self.trajectory = [vec3(dummy.position)] self.landing = False collision_normal: Optional[vec3] = None dt = 1 / 60 simulation_duration = 0.8 for i in range(int(simulation_duration / dt)): dummy.step(Input(), dt) self.trajectory.append(vec3(dummy.position)) collision_sphere = sphere(dummy.position, 50) collision_ray = Field.collide(collision_sphere) collision_normal = collision_ray.direction if (norm(collision_normal) > 0.0 or dummy.position[2] < 0) and i > 20: self.landing = True self.landing_pos = dummy.position break if self.landing: u = collision_normal f = normalize(dummy.velocity - dot(dummy.velocity, u) * u) l = normalize(cross(u, f)) self.aerial_turn.target = mat3(f[0], l[0], u[0], f[1], l[1], u[1], f[2], l[2], u[2]) else: target_direction = normalize( normalize(self.car.velocity) - vec3(0, 0, 3)) self.aerial_turn.target = look_at(target_direction, vec3(0, 0, 1))
def predict_car_drive(self, index, time_limit=2.0, dt=1 / 60) -> List[vec3]: """Simple prediction of a driving car assuming no acceleration.""" car = self.cars[index] time_steps = int(time_limit / dt) speed = norm(car.velocity) ang_vel_z = car.angular_velocity[2] # predict circular path if ang_vel_z != 0 and car.on_ground: radius = speed / ang_vel_z centre = car.position - cross(normalize(xy(car.velocity)), vec3(0, 0, 1)) * radius centre_to_car = vec2(car.position - centre) return [ vec3(dot(rotation(ang_vel_z * dt * i), centre_to_car)) + centre for i in range(time_steps) ] # predict straight path return [ car.position + car.velocity * dt * i for i in range(time_steps) ]
def step(self, dt: float): if self.phase == 1 and norm(self.car.velocity) > 600: self.action = HalfFlip(self.car) self.phase = 2 if self.phase == 2 and self.action.finished: self.drive.target_pos = vec3(0, self.car.position[1], 0) self.drive.backwards = False self.action = self.drive self.phase = 3 if self.phase == 3 and norm(self.car.velocity) > 1300: self.finished = True self.action.step(dt) self.controls = self.action.controls
def step(self, dt: float): car = self.car if self.phase == 1: if norm(car.velocity) > 800: self.action = SpeedFlip( car, right_handed=local(car, self.info.ball.position)[1] < 0) self.phase = 2 self._speed_flip_start_time = car.time if self.phase == 2: if self.action.finished and self.car.on_ground: self.action = self.drive self.drive.target_pos = vec3(0, 0, 0) self.phase = 3 if self.phase == 3: if ground_distance(self.car, vec3(0, 0, 0)) < 500: self.action = AirDodge(car, 0.1, vec3(0, 0, 0)) self.phase = 4 if self.phase == 4: if self.action.finished: self.finished = True # abort when taking too long if car.time > self._speed_flip_start_time + 3.0: self.finished = True super().step(dt)
def step(self, dt): car = self.car target = ground(self.target) car_speed = norm(car.velocity) time_left = (ground_distance(car, target) - self.finish_distance) / max(car_speed + 500, 1400) forward_speed = dot(car.forward(), car.velocity) if self.driving and car.on_ground: self.action.target_pos = target self._time_on_ground += dt # check if it's a good idea to dodge, wavedash or halfflip if (self._time_on_ground > 0.2 and car.position[2] < 200 and angle_to(car, target, forward_speed < 0) < 0.1): # if going forward, use a dodge or a wavedash if forward_speed > 0: use_boost_instead = self.waste_boost and car.boost > 20 if car_speed > 1200 and not use_boost_instead: if time_left > self.DODGE_DURATION: dodge = Dodge(car) dodge.duration = 0.05 dodge.direction = vec2(direction(car, target)) self.action = dodge self.driving = False elif time_left > self.WAVEDASH_DURATION: wavedash = Wavedash(car) wavedash.direction = vec2(direction(car, target)) self.action = wavedash self.driving = False # if going backwards, use a halfflip elif time_left > self.HALFFLIP_DURATION and car_speed > 800: self.action = HalfFlip(car, self.waste_boost and time_left > 3) self.driving = False self.action.step(dt) self.controls = self.action.controls # make sure we're not boosting airborne if self.driving and not car.on_ground: self.controls.boost = False # make sure we're not stuck turtling if not car.on_ground: self.controls.throttle = 1 if self.action.finished and not self.driving: self.driving = True self._time_on_ground = 0 self.action = self.drive self.drive.backwards = False if ground_distance(car, target) < self.finish_distance and self.driving: self.finished = True
def step(self, dt): if self.dodging: self.dodge.step(dt) self.controls = self.dodge.controls else: super().step(dt) if (self.arrive.arrival_time - self.car.time < self.dodge.jump.duration + 0.13 and abs(self.arrive.drive.target_speed - norm(self.car.velocity)) < 1000 and (dot(normalize(self.car.velocity), ground_direction(self.car, self.arrive.target)) > 0.95 or norm(self.car.velocity) < 500)): self.dodging = True if self.dodge.finished: self.finished = True
def has_ball_contact(time, box, ball, team_sign): ''' Returns whether or not box (RLU obb) intersects ball, and box's nearest point to the ball. ''' contact_point = nearest_point(box, Vec3_to_vec3(ball.pos, team_sign)) ball_contact = norm(contact_point - Vec3_to_vec3(ball.pos, team_sign)) < 92.75 return ball_contact, contact_point
def should_dodge(agent): return norm(agent.info.ball.location - agent.info.my_car.location) < 300 and max( dot(agent.info.my_car.velocity, agent.info.ball.location - agent.info.my_car.location), dot(agent.info.my_car.forward(), agent.info.ball.location - agent.info.my_car.location)) > 1300 # Go for it! """"Method that checks if we should dodge""" car = agent.info.my_car their_goal = agent.their_goal close_to_goal = distance_2d(car.location, their_goal.center) < 4000 aiming_for_goal = abs( line_backline_intersect(their_goal.center[1], vec2(car.location), vec2(car.forward()))) < 850 bot_to_target = agent.info.ball.location - car.location local_bot_to_target = dot(bot_to_target, agent.info.my_car.rotation) angle_front_to_target = math.atan2(local_bot_to_target[1], local_bot_to_target[0]) close_to_ball = norm(vec2(bot_to_target)) < 750 good_angle = abs(angle_front_to_target) < math.radians(15) return close_to_ball and close_to_goal and aiming_for_goal and good_angle
def step(self, dt): if self.dodging: self.dodge.step(dt) self.controls = self.dodge.controls else: super().step(dt) if (self.arrive.arrival_time - self.car.time < self.dodge.jump.duration + 0.17 and abs(self.arrive.drive.target_speed - norm(self.car.velocity)) < 1000): self.dodging = True if self.dodge.finished: self.finished = True
def can_dodge(agent, target): """Returns whether its wise to dodge""" bot_to_target = target - agent.info.my_car.location local_bot_to_target = dot(bot_to_target, agent.info.my_car.rotation) angle_front_to_target = math.atan2(local_bot_to_target[1], local_bot_to_target[0]) distance_bot_to_target = norm(vec2(bot_to_target)) good_angle = math.radians(-10) < angle_front_to_target < math.radians(10) on_ground = agent.info.my_car.on_ground and agent.info.my_car.location[ 2] < 100 going_fast = velocity_2d(agent.info.my_car.velocity) > 1250 target_not_in_goal = not agent.my_goal.inside(target) return (good_angle and distance_bot_to_target > 2000 and on_ground and going_fast and target_not_in_goal)
def step(self, dt): delta_target = self.target - self.car.position if norm(delta_target) > 500: delta_target = direction(self.car.position, self.target) * 500 target_direction = delta_target - self.car.velocity + vec3(0, 0, 500) self.turn.target = look_at(target_direction, direction(self.car.position, vec3(0, 0, 0))) self.turn.step(dt) self.controls = self.turn.controls self.controls.boost = delta_target[2] - self.car.velocity[2] * 0.5 > 0 and self.car.forward()[2] > 0.2 self.controls.throttle = not self.car.on_ground self.controls.jump = self.car.position[2] < 30 and self.info.time % 1.0 < 0.5
def step(self, dt: float): car = self.car if self.phase == 1: if norm(car.velocity) > 1050: self.action = SpeedFlip( car, right_handed=local(car, self.info.ball.position)[1] < 0) self.phase = 2 if self.phase == 2: if self.action.finished and self.info.ball.position[0] != 0: self.finished = True super().step(dt)
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 * (norm(ball.velocity) * 3 + 500)) self.arrive.target = intercept.ground_pos - hit_dir * 165 self.arrive.target_direction = hit_dir self.dodge.jump.duration = self.get_jump_duration(ball.position[2]) self.dodge.target = intercept.ball.position self.arrive.additional_shift = self.get_jump_duration( ball.position[2]) * 1000
def determine_max_speed(self, local_target): low = 100 high = 2200 if self.kickoff: return high for i in range(5): mid = (low + high) / 2 radius = (1 / RLUDrive.max_turning_curvature(mid)) local_circle = vec3(0, copysign(radius, local_target[1]), 0) dist = norm(local_circle - xy(local_target)) if dist < radius: high = mid else: low = mid return high
def followTick(self, packet: GameTickPacket) -> bool: isBallInCenter = packet.game_ball.physics.location.x == 0 and packet.game_ball.physics.location.y == 0 if not isBallInCenter: return False self.controller.boost = False self.controller.throttle = 1 target = self.agent.game.ball.position if self.agent.car.boost < 40 and abs(self.agent.car.position[1]) > 2816 and norm(self.agent.car.position - self.agent.game.cars[self.kickoffCar].position) > 1500: target = vec3(math.copysign(144 - 10, self.agent.car.position[0]), 2816, 0) self.controller.steer = PID.toPoint(self.agent.car, target) return True
def step(self, dt: float): self.speed = abs(self.speed) car_to_target = (self.target - self.car.location) local_target = dot(car_to_target, self.car.rotation) angle = atan2(local_target[1], local_target[0]) vel = norm(self.car.velocity) in_air = (not self.car.on_ground) on_wall = (self.car.location[2] > 250 and not in_air) reverse = (cos(angle) < 0 and not (on_wall or in_air or self.kickoff)) get_off_wall = (on_wall and local_target[2] > 450) if get_off_wall: car_to_target[2] = -self.car.location[2] local_target = dot(car_to_target, self.car.rotation) angle = atan2(local_target[1], local_target[0]) max_speed = self.determine_max_speed(local_target) self.update_rlu_drive(reverse, max_speed) self.rlu_drive.step(dt) self.finished = self.rlu_drive.finished self.controls = self.rlu_drive.controls self.controls.handbrake = False if reverse: angle = -invert_angle(angle) if self.power_turn and not on_wall: angle *= -1 self.controls.handbrake = (vel > 200) self.controls.steer = cap(angle * 3, -1, 1) self.controls.boost = False if not self.controls.handbrake: self.controls.handbrake = (abs(angle) > radians(70) and vel > 500 and not on_wall) if self.controls.handbrake: self.controls.handbrake = (dot(self.car.velocity, car_to_target) > -150) if in_air: self.aerial_turn.target = look_at(xy(car_to_target), vec3(0, 0, 1)) self.aerial_turn.step(dt) aerial_turn_controls = self.aerial_turn.controls self.controls.pitch = aerial_turn_controls.pitch self.controls.yaw = aerial_turn_controls.yaw self.controls.roll = aerial_turn_controls.roll self.controls.boost = False
def step(self, dt): # slow down when we're about to pick up the boost, so we can turn faster afterwards if distance(self.car, self.pad) < norm(self.car.velocity) * 0.2: self.travel.drive.target_speed = 1400 self.travel.step(dt) self.controls = self.travel.controls # finish when someone picks up the pad if self.pad_was_active and self.pad.state == BoostPadState.Unavailable: self.finished = True self.pad_was_active = self.pad.state == BoostPadState.Available # finish when we picked the boost up but the previous condition somehow wasn't true if self.car.boost > 99 or distance(self.car, self.pad) < 100: self.finished = True
def defendTick(self, packet: GameTickPacket, myGoalPosition: vec3) -> bool: speed = norm(self.agent.car.velocity) if speed < 10: self.startTime = self.agent.currentTick self.isDiagonalKickoff = abs(self.agent.car.position[0]) >= 1024 self.isSemiDiagonalKickoff = abs(abs(self.agent.car.position[0]) - 256) < 128 self.isStraightKickoff = not self.isDiagonalKickoff and not self.isSemiDiagonalKickoff self.controller.boost = False self.controller.pitch = 0 self.controller.yaw = 0 self.controller.roll = 0 if self.isStraightKickoff: self.controller.steer = 0 if abs(self.agent.car.position[1]) > 4444 and self.controller.throttle != -1: self.controller.throttle = 1 else: if self.agent.car.velocity[1] * (2*self.agent.car.team-1) < 0 or abs(self.agent.car.position[1]) < 4466: self.controller.throttle = -1 else: return self.agent.stateMachine.changeStateAndContinueTick(HalfFlip, packet, True, True) elif self.isSemiDiagonalKickoff: self.controller.throttle = -1 if abs(self.agent.car.position[1]) < 3940: self.controller.steer = -math.copysign(1, self.agent.car.position[0]) * (2*self.agent.car.team-1) else: self.controller.steer = PID.toPointReverse(self.agent.car, vec3(0, math.copysign(5400, self.agent.car.position[1]), 0)) if abs(self.agent.car.position[1]) > 3990 and self.controller.steer * math.copysign(1, self.agent.car.position[0]) * (2*self.agent.car.team-1) < 0.1: return self.agent.stateMachine.changeStateAndContinueTick(HalfFlip, packet, True, True) return True else: self.controller.throttle = -1 self.controller.steer = PID.toPointReverse(self.agent.car, vec3(math.copysign(3072, self.agent.car.position[0]), math.copysign(4096, self.agent.car.position[1]), 0)) if abs(self.agent.car.position[1]) < 2650 or self.controller.steer * math.copysign(1, self.agent.car.position[0]) * (2*self.agent.car.team-1) < -0.1: return True return self.agent.stateMachine.changeStateAndContinueTick(HalfFlip, packet) return True
def step(self, dt): if self.car.on_ground and norm(self.car.position + self.car.velocity - xy(self.target)) > 2500: self.drive.speed = 1000 self.drive.target = self.target self.drive.step(dt) self.controls = self.drive.controls self.controls.handbrake = angle_between(self.car.forward(), self.target - self.car.position) > 1.2 return self.hover.target = self.target self.hover.up = normalize(self.car.position * -1) self.hover.step(dt) self.controls = self.hover.controls self.controls.throttle = not self.car.on_ground self.controls.jump = (self.car.position[2] < 30 or self.car.on_ground) and self.__time_spent_on_ground > 0.1 if self.info.round_active: self.__time_spent_on_ground += dt if not self.car.on_ground: self.__time_spent_on_ground = 0.0