def simulate(self): ball_prediction = self.get_ball_prediction_struct() duration_estimate = math.floor( get_time_at_height(self.game.ball.location[2], 0.2) * 10) / 10 for i in range(6): car = Car(self.game.my_car) ball = Ball(self.game.ball) batmobile = obb() batmobile.half_width = vec3(64.4098892211914, 42.335182189941406, 14.697200775146484) batmobile.center = car.location + dot(car.rotation, vec3(9.01, 0, 12.09)) batmobile.orientation = car.rotation dodge = Dodge(car) dodge.duration = duration_estimate + i / 60 dodge.target = ball.location for j in range(round(60 * dodge.duration)): dodge.target = ball.location dodge.step(1 / 60) car.step(dodge.controls, 1 / 60) prediction_slice = ball_prediction.slices[j] physics = prediction_slice.physics ball_location = vec3(physics.location.x, physics.location.y, physics.location.z) dodge.target = ball_location batmobile.center = car.location + dot(car.rotation, vec3(9.01, 0, 12.09)) batmobile.orientation = car.rotation if intersect(sphere(ball_location, 93.15), batmobile) and abs( ball_location[2] - car.location[2] ) < 25 and car.location[2] < ball_location[2]: return True, j / 60, ball_location return False, None, None
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 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