1- import math
21from typing import List
32
43from rlbot .agents .base_agent import BaseAgent , SimpleControllerState
54from rlbot .utils .structures .game_data_struct import GameTickPacket
65from rlbot .utils .structures .quick_chats import QuickChats
76
7+ from util .aerial import AerialStep , LineUpForAerialStep
8+ from util .drive import steer_toward_target
89from util .goal_detector import find_future_goal
9- from util .orientation import Orientation
1010from util .sequence import Sequence , ControlStep
1111from util .spikes import SpikeWatcher
1212from util .vec import Vec3
1313
14+
1415# Would you like to use numpy utilities? Check out the np_util folder!
1516
1617class MyBot (BaseAgent ):
@@ -27,6 +28,8 @@ def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
2728 see the motion of the ball, etc. and return controls to drive your car.
2829 """
2930
31+ # This is good to keep at the beginning of get_output. It will allow you to continue
32+ # any sequences that you may have started during a previous call to get_output.
3033 if self .active_sequence and not self .active_sequence .done :
3134 return self .active_sequence .tick (packet )
3235
@@ -39,9 +42,7 @@ def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
3942 if predicted_goal :
4043 goal_text = f"Goal in { predicted_goal .time - packet .game_info .seconds_elapsed :.2f} s"
4144
42- ball_location = Vec3 (packet .game_ball .physics .location )
4345 my_car = packet .game_cars [self .index ]
44- car_location = Vec3 (my_car .physics .location )
4546 car_velocity = Vec3 (my_car .physics .velocity )
4647
4748 # Example of using a sequence
@@ -57,64 +58,32 @@ def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
5758
5859 # Example of using the spike watcher.
5960 # This will make the bot say I got it! when it spikes the ball,
60- # then release it 3 seconds later.
61+ # then release it 2 seconds later.
6162 if self .spike_watcher .carrying_car == my_car :
6263 if self .spike_watcher .carry_duration == 0 :
6364 self .send_quick_chat (QuickChats .CHAT_EVERYONE , QuickChats .Information_IGotIt )
64- elif self .spike_watcher .carry_duration > 3 :
65+ elif self .spike_watcher .carry_duration > 2 :
6566 return SimpleControllerState (use_item = True )
6667
67- # The rest of this code just ball chases.
68- # Find the direction of your car using the Orientation class
69- car_orientation = Orientation (my_car .physics .rotation )
70- car_direction = car_orientation .forward
71-
72- target = ball_location
73- car_to_target = target - car_location
74- steer_correction_radians = find_correction (car_direction , car_to_target )
68+ # Example of doing an aerial. This will cause the car to jump and fly toward the
69+ # ceiling in the middle of the field.
70+ if my_car .boost > 50 and my_car .has_wheel_contact :
71+ self .start_aerial (Vec3 (0 , 0 , 2000 ), packet .game_info .seconds_elapsed + 4 )
7572
73+ # If nothing else interesting happened, just chase the ball!
74+ ball_location = Vec3 (packet .game_ball .physics .location )
75+ self .controller_state .steer = steer_toward_target (my_car , ball_location )
7676 self .controller_state .throttle = 1.0
7777
78- # Change the multiplier to influence the sharpness of steering. You'll wiggle if it's too high.
79- self .controller_state .steer = limit_to_safe_range (- steer_correction_radians * 5 )
80-
78+ # Draw some text on the screen
8179 draw_debug (self .renderer , [goal_text ])
8280
8381 return self .controller_state
8482
85-
86- def limit_to_safe_range (value : float ) -> float :
87- """
88- Controls like throttle, steer, pitch, yaw, and roll need to be in the range of -1 to 1.
89- This will ensure your number is in that range. Something like 0.45 will stay as it is,
90- but a value of -5.6 would be changed to -1.
91- """
92- if value < - 1 :
93- return - 1
94- if value > 1 :
95- return 1
96- return value
97-
98-
99- def find_correction (current : Vec3 , ideal : Vec3 ) -> float :
100- """
101- Finds the angle from current to ideal vector in the xy-plane. Angle will be between -pi and +pi.
102- """
103-
104- # The in-game axes are left handed, so use -x
105- current_in_radians = math .atan2 (current .y , - current .x )
106- ideal_in_radians = math .atan2 (ideal .y , - ideal .x )
107-
108- diff = ideal_in_radians - current_in_radians
109-
110- # Make sure that diff is between -pi and +pi.
111- if abs (diff ) > math .pi :
112- if diff < 0 :
113- diff += 2 * math .pi
114- else :
115- diff -= 2 * math .pi
116-
117- return diff
83+ def start_aerial (self , target : Vec3 , arrival_time : float ):
84+ self .active_sequence = Sequence ([
85+ LineUpForAerialStep (target , arrival_time , self .index ),
86+ AerialStep (target , arrival_time , self .index )])
11887
11988
12089def draw_debug (renderer , text_lines : List [str ]):
0 commit comments