def update(self, packet: GameTickPacket): self.car_info = packet.game_cars[self.index] physics = self.car_info.physics self.position = Vec3(physics.location) self.velocity = Vec3(physics.velocity) self.angular_velocity = Vec3(physics.angular_velocity) self.orientation = Orientation(physics.rotation)
def __init__(self, packet: GameTickPacket = None, phys=None, time=0): super().__init__() self.position = Vec3() self.velocity: Vec3 = Vec3() self.angular_velocity = Vec3() self.time = time self.update(packet, phys)
def update(self, packet=None, phys=None): if packet is not None: self.latest_touch = packet.game_ball.latest_touch phys = packet.game_ball.physics self.position = Vec3(phys.location) self.velocity = Vec3(phys.velocity) self.angular_velocity = Vec3(phys.angular_velocity)
def __init__(self, position: Vec3 = None, velocity: Vec3 = None): if position is None: position = Vec3(0) if velocity is None: velocity = Vec3(0) super().__init__(position) self.velocity = velocity
def __init__(self, team: int, field_info_packet: FieldInfoPacket): orientation = Orientation(Vec3(0)) orientation.up = Vec3(0, 0, 1) orientation.right = Vec3(1 if team else -1, 0, 0) orientation.forward = Vec3(0, -1 if team else 1, 0) super().__init__(orientation=orientation) self.boosts = [] self._init_boosts(field_info_packet) self._init_goals()
def update(self, packet: GameTickPacket = None, phys=None): if packet is not None: self.latest_touch = packet.game_ball.latest_touch phys = packet.game_ball.physics self.position = Vec3(phys.location) self.velocity = Vec3(phys.velocity) self.angular_velocity = Vec3(phys.angular_velocity) if self.z - self.radius < 2: self.roll_counter += 1 else: self.roll_counter = 0
def line_flat(start: Vec3, end: Vec3, color: str = ""): """Draw a line in 3D space which is confined to ground level (z=20 units, to prevent the line being hidden by grass or other ground decorations). :param start: start location :param end: end location :param color: string naming the color :return: None """ renderer.draw_line_3d(start.flat() + flat_z, end.flat() + flat_z, get_color(color))
def __init__( self, position: Vec3 = 0, velocity: Vec3 = 0, angular_velocity: Vec3 = 0, orientation: Orientation = None, ): super().__init__(position, velocity) self.angular_velocity = Vec3(angular_velocity) if orientation is None: orientation = Orientation(Vec3()) self.orientation = orientation
def init_goals(self): goal_width = 1786 self.opp_goal_center = Location(5120 * self.forward + Vec3(0, 0, 320)) self.own_goal_center = Location(5120 * self.backward + Vec3(0, 0, 320)) self.own_left_post = Location( self.own_goal_center + (goal_width / 2) * self.left ) self.own_right_post = Location( self.own_goal_center + (goal_width / 2) * self.right ) self.opp_left_post = Location( self.opp_goal_center + (goal_width / 2) * self.right ) self.opp_right_post = Location( self.opp_goal_center + (goal_width / 2) * self.left )
def next_bounce(self, game_time: float = 0) -> Ball: """Return the first bounce after the specified match time. If there is no bounce in the predicted ball path, return the last predicted moment. """ # Todo: this is worth optimizing (tested) for i in range(1, self.prediction.num_slices): dv = Vec3(self.prediction.slices[i].physics.velocity) - Vec3( self.prediction.slices[i - 1].physics.velocity) if i + 1 == self.prediction.num_slices or ( self.prediction.slices[i].game_seconds > game_time and dv.length() > self.bounce_threshold): ball = Ball( phys=self.prediction.slices[i].physics, time=self.prediction.slices[i].game_seconds, ) ball.dv = dv return ball
def path(points, line_color="", point_color=""): if point_color == "": point_color = line_color prev_pt = None h = Vec3(z=20) for pt in points: if prev_pt is not None: line_3d(prev_pt + h, pt + h, line_color) point(pt, size=10, color=point_color) prev_pt = pt
def analyze(self, max_ms: float = 2): stop_ns = perf_counter_ns() + max_ms * 1e6 while self.slices_analyzed < self.prediction.num_slices: current_slice = self.prediction.slices[self.slices_analyzed] if self.slices_analyzed > 0: previous_slice = self.prediction.slices[self.slices_analyzed - 1] # See if the ball bounced: if len(self.bounces) < self.max_bounces: v1 = Vec3(current_slice.physics.velocity) v2 = Vec3(previous_slice.physics.velocity) if (v1 - v2).length() > self.bounce_threshold: self.bounces.append( (self.slices_analyzed - 1, v1 - v2)) if self.roll_time is None: if abs(current_slice.physics.velocity.z ) < self.bounce_threshold / 2: if current_slice.physics.location.z - Ball.radius < 30: self.roll_time = self.slices_analyzed self.slices_analyzed += 1 if perf_counter_ns() > stop_ns: return
def line(this_line: Line, color: str = "", bump_color: str = ""): if bump_color == "": bump_color = color bumps = 0 bump_spd = 5000 length = 20000 height = Vec3(z=20) start = height + this_line.base_point - this_line.direction * length / 2 end = height + this_line.base_point + this_line.direction * length / 2 line_3d(start, end, color) for i in range(bumps): bump_period = length / (bumps * bump_spd) t = (i + (time.time() / bump_period) % 1) * length / bumps point(start + t * this_line.direction, size=7, color=bump_color)
def line(line: Line, color: str = "", bump_color: str = ""): if bump_color == "": bump_color = color bumps = 5 bump_spd = 5000 length = 20000 bump_period = length / (bumps * bump_spd) height = Vec3(z=20) start = line.pos - line.dir * length / 2 + height end = line.pos + line.dir * length / 2 + height line_3d(start, end, color) for i in range(bumps): t = (i + (time.time() / bump_period) % 1) * length / bumps point(start + t * line.dir, size=7, color=bump_color)
def check_prediction(self, packet: GameTickPacket): """Check the predicted ball against the actual current one.""" actual_ball_velocity = Vec3(packet.game_ball.physics.velocity) # Advance to the current game time in our prediction structure: while self.prediction.slices[self.index_now + 1].game_seconds <= self.game_time: self.index_now += 1 if self.index_now >= self.prediction.num_slices: self.valid = False return # Make sure we're still close to the reality: self.valid = (actual_ball_velocity - self.prediction.slices[self.index_now].physics.velocity ).length() < self.accuracy_threshold_velocity
def steer_to(self, target: Vec3, no_handbrake=False): halt_sec = 0.15 # How long (estimated) it takes to halt a turn car = Match.agent_car if car.forward_speed >= 0: err = car.yaw_to(target) else: err = -car.yaw_to(target + 2 * target.to(car)) if abs(err) < 0.01: steer = 0 elif abs(err) < 0.05: steer = copysign(0.2, err) else: steer = copysign(1, err) if car.yaw_rate != 0: if 0 < err / car.yaw_rate < halt_sec: steer = -steer if err / car.yaw_rate > 2 * halt_sec and not no_handbrake: self.handbrake() else: self.handbrake(False) self.steer(steer)
def ndot(v1: Vec3, v2: Vec3) -> float: return 0.5 + v1.ndot(v2) / 2
If any other string (or no string) is given, the default `white` will be used. """ import time from typing import List from rlbot.utils.rendering.rendering_manager import RenderingManager from vitamins.geometry import Vec3, Line renderer: RenderingManager = None colors = {} white = None flat_z = Vec3(z=20) def set_renderer(rd: RenderingManager): global renderer, white renderer = rd def get_color(name: str = ""): return getattr(renderer, name, renderer.white)() def line_3d(start: Vec3, end: Vec3, color: str = ""): """Draw a 3D line between two locations with the given color. :param start: start location
def score(self, bot, dir=None): if dir is None: dir = bot.field.fwd self.velocity = dir * 2300 self.position = bot.field.center + 5000 * dir + Vec3(z=500) self.reset(bot)
def line_flat(vec1: Vec3, vec2: Vec3, color: str = ""): renderer.draw_line_3d(vec1.flat() + flat_z, vec2.flat() + flat_z, get_color(color))
def position(self) -> Vec3: return Vec3(self.x, self.y, self.z)