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 dodge_simulation(end_condition=None, car=None, hitbox_class=None, dodge=None, ball=None, game_info=None, boost=True): ''' Simulates an RLU dodge until the dodge ends, or one of pass_condition or fail_condtion are met. pass_condition means that the dodge does what we wanted. Returns True and the RLU car state at the end fail_condition returns (False, None), meaning the dodge doesn't achieve the desired result. ''' #Copy everything we need and set constants time = 0 dt = 1 / 60 car_copy = RLU_Car(car) dodge_copy = RLU_Dodge(car_copy) if dodge.target != None: dodge_copy.target = dodge.target if dodge.direction != None: dodge_copy.direction = dodge.direction if dodge.preorientation != None: dodge_copy.preorientation = dodge.preorientation if dodge.duration != None: dodge_copy.duration = dodge.duration else: dodge_copy.duration = 0 #Make sure there's time between the jump and the dodge so that we don't just keep holding jump if dodge.delay != None: dodge_copy.delay = dodge.delay else: dodge_copy.delay = max(dodge_copy.duration + 2 * dt, 0.05) #Adjust for non-octane hitboxes box = update_hitbox(car_copy, hitbox_class) #Loop until we hit end_condition or the dodge is over. while not end_condition(time, box, ball, game_info.team_sign): #Update simulations and adjust hitbox again time += dt dodge_copy.step(dt) controls = dodge_copy.controls if boost: controls.boost = 1 car_copy.step(controls, dt) box = update_hitbox(car_copy, hitbox_class) if dodge_copy.finished: #If the dodge never triggers condition, give up and move on #TODO: give up sooner to save computation time return Simulation() return Simulation(ball_contact=True, car=car_copy, box=box, time=time)
def step(self, dt): car = self.car target = ground(self.target) car_vel = norm(car.velocity) time_left = (distance(car, target) - self.finish_distance) / max(car_vel + 500, 1400) vf = dot(car.forward(), car.velocity) if self.driving and car.on_ground: self.action.target_pos = target self._time_on_ground += dt if self._time_on_ground > 0.2 and car.position[2] < 200 and angle_to(car, target, vf < 0) < 0.1: if vf > 0: if car_vel > 1000 and (not self.waste_boost or car.boost < 10): 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 elif time_left > self.halflip_duration and car_vel > 800: self.action = HalfFlip(car, self.waste_boost and time_left > 3) self.driving = False self.action.step(dt) self.controls = self.action.controls if self.driving and not car.on_ground: self.controls.boost = False 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 distance(car, target) < self.finish_distance and self.driving: self.finished = True if not self.waste_boost and car.boost < 70: self.controls.boost = 0
c.time = 0.0 c.location = vec3(1509.38, -686.19, 17.01) c.velocity = vec3(-183.501, 1398., 8.321) c.angular_velocity = vec3(0, 0, 0) c.rotation = mat3(-0.130158, -0.991493, -0.00117062, 0.991447, -0.130163, 0.00948812, -0.00955977, 0.0000743404, 0.999954) c.dodge_rotation = mat2(-0.130163, -0.991493, 0.991493, -0.130163) c.on_ground = True c.jumped = False c.double_jumped = False c.jump_timer = -1.0 c.dodge_timer = -1.0 dodge = Dodge(c) dodge.direction = vec2(-230.03, 463.42) dodge.duration = 0.1333 dodge.delay = 0.35 f = open("dodge_simulation.csv", "w") for i in range(300): dodge.step(0.008333) print(c.time, dodge.controls.jump, dodge.controls.pitch, dodge.controls.yaw) c.step(dodge.controls, 0.008333) f.write( f"{c.time}, {c.location[0]}, {c.location[1]}, {c.location[2]}, " f"{c.velocity[0]}, {c.velocity[1]}, {c.velocity[2]}, " f"{c.angular_velocity[0]}, {c.angular_velocity[1]}, {c.angular_velocity[2]}\n" )
def simulate(self, global_target=None): lol = 0 # Initialize the ball prediction # Estimate the probable duration of the jump and round it down to the floor decimal ball_prediction = self.get_ball_prediction_struct() if self.info.my_car.boost < 6: duration_estimate = math.floor( get_time_at_height(self.info.ball.position[2]) * 10) / 10 else: adjacent = norm( vec2(self.info.my_car.position - self.info.ball.position)) opposite = (self.info.ball.position[2] - self.info.my_car.position[2]) theta = math.atan(opposite / adjacent) t = get_time_at_height_boost(self.info.ball.position[2], theta, self.info.my_car.boost) duration_estimate = (math.ceil(t * 10) / 10) # Loop for 6 frames meaning adding 0.1 to the estimated duration. Keeps the time constraint under 0.3s for i in range(6): # Copy the car object and reset the values for the hitbox car = Car(self.info.my_car) # Create a dodge object on the copied car object # Direction is from the ball to the enemy goal # Duration is estimated duration plus the time added by the for loop # preorientation is the rotation matrix from the ball to the goal # TODO make it work on both sides # Test with preorientation. Currently it still picks a low duration at a later time meaning it # wont do any of the preorientation. dodge = Dodge(car) prediction_slice = ball_prediction.slices[round( 60 * (duration_estimate + i / 60))] physics = prediction_slice.physics ball_location = vec3(physics.location.x, physics.location.y, physics.location.z) # ball_location = vec3(0, ball_y, ball_z) dodge.duration = duration_estimate + i / 60 if dodge.duration > 1.4: break if global_target is not None: dodge.direction = vec2(global_target - ball_location) target = vec3(vec2(global_target)) + vec3( 0, 0, jeroens_magic_number * ball_location[2]) dodge.preorientation = look_at(target - ball_location, vec3(0, 0, 1)) else: dodge.target = ball_location dodge.direction = vec2(ball_location) + vec2(ball_location - car.position) dodge.preorientation = look_at(ball_location, vec3(0, 0, 1)) # Loop from now till the end of the duration fps = 30 for j in range(round(fps * dodge.duration)): lol = lol + 1 # Get the ball prediction slice at this time and convert the location to RLU vec3 prediction_slice = ball_prediction.slices[round(60 * j / fps)] physics = prediction_slice.physics ball_location = vec3(physics.location.x, physics.location.y, physics.location.z) dodge.step(1 / fps) T = dodge.duration - dodge.timer if T > 0: if dodge.timer < 0.2: dodge.controls.boost = 1 dodge.controls.pitch = 1 else: xf = car.position + 0.5 * T * T * vec3( 0, 0, -650) + T * car.velocity delta_x = ball_location - xf if angle_between(vec2(car.forward()), dodge.direction) < 0.3: if norm(delta_x) > 50: dodge.controls.boost = 1 dodge.controls.throttle = 0.0 else: dodge.controls.boost = 0 dodge.controls.throttle = clip( 0.5 * (200 / 3) * T * T, 0.0, 1.0) else: dodge.controls.boost = 0 dodge.controls.throttle = 0.0 else: dodge.controls.boost = 0 car.step(dodge.controls, 1 / fps) succesfull = self.dodge_succesfull(car, ball_location, dodge) if succesfull is not None: if succesfull: return True, j / fps, ball_location else: break return False, None, None