diff --git a/rlgym/rocket_league/common_values.py b/rlgym/rocket_league/common_values.py index f2b86d9..c4331d8 100644 --- a/rlgym/rocket_league/common_values.py +++ b/rlgym/rocket_league/common_values.py @@ -48,6 +48,7 @@ BLUE_FIELD_BOTTOM_RIGHT = (SIDE_WALL_X, -BACK_WALL_Y, 0) GOAL_THRESHOLD = 5215.5 # uu, magnitude of y position required for ball to be inside goal +GOAL_THRESHOLD_Z_HOOPS = 270 # uu, magnitude of z position for ball to be inside net to count as a goal # Time TICKS_PER_SECOND = 120 @@ -131,3 +132,26 @@ (1792.0, 4184.0, 70.0), (0.0, 4240.0, 70.0), ) + +BOOST_LOCATIONS_HOOPS = ( + (1536.0, -1024.0, 64.0), + (-1280.0, -2304.0, 64.0), + (0.0, -2816.0, 64.0), + (-1536.0, -1024.0, 64.0), + (1280.0, -2304.0, 64.0), + (-512.0, 512.0, 64.0), + (-1536.0, 1024.0, 64.0), + (1536.0, 1024.0, 64.0), + (1280.0, 2304.0, 64.0), + (0.0, 2816.0, 64.0), + (512.0, 512.0, 64.0), + (512.0, -512.0, 64.0), + (-512.0, -512.0, 64.0), + (-1280.0, 2304.0, 64.0), + (-2176.0, 2944.0, 72.0), + (2176.0, -2944.0, 72.0), + (-2176.0, -2944.0, 72.0), + (-2432.0, 0.0, 72.0), + (2432.0, 0.0, 72.0), + (2175.99, 2944.0, 72.0), +) \ No newline at end of file diff --git a/rlgym/rocket_league/rlviser/rlviser_renderer.py b/rlgym/rocket_league/rlviser/rlviser_renderer.py index 1245420..1cd22a3 100644 --- a/rlgym/rocket_league/rlviser/rlviser_renderer.py +++ b/rlgym/rocket_league/rlviser/rlviser_renderer.py @@ -5,7 +5,7 @@ from rlgym.api import Renderer from rlgym.rocket_league.api import Car, GameState -from rlgym.rocket_league.common_values import BOOST_LOCATIONS +from rlgym.rocket_league.common_values import BOOST_LOCATIONS, BOOST_LOCATIONS_HOOPS class RLViserRenderer(Renderer[GameState]): @@ -13,10 +13,16 @@ class RLViserRenderer(Renderer[GameState]): A renderer that uses RLViser to render the game state. """ - def __init__(self, tick_rate=120/8): - rlviser.set_boost_pad_locations(BOOST_LOCATIONS) + def __init__(self, tick_rate=120/8, game_mode: rsim.GameMode = rsim.GameMode.SOCCAR): + if game_mode == rsim.GameMode.SOCCAR: + rlviser.set_boost_pad_locations(BOOST_LOCATIONS) + elif game_mode == rsim.GameMode.HOOPS: + rlviser.set_boost_pad_locations(BOOST_LOCATIONS_HOOPS) + else: + raise ValueError("Unknown game mode") self.tick_rate = tick_rate self.packet_id = 0 + self.game_mode = game_mode def render(self, state: GameState, shared_info: Dict[str, Any]) -> Any: boost_pad_states = [bool(timer == 0) for timer in state.boost_pad_timers] @@ -33,7 +39,7 @@ def render(self, state: GameState, shared_info: Dict[str, Any]) -> Any: car_data.append((idx + 1, car.team_num, rsim.CarConfig(car.hitbox_type), car_state)) self.packet_id += 1 - rlviser.render(tick_count=self.packet_id, tick_rate=self.tick_rate, game_mode=rsim.GameMode.SOCCAR, + rlviser.render(tick_count=self.packet_id, tick_rate=self.tick_rate, game_mode=self.game_mode, boost_pad_states=boost_pad_states, ball=ball, cars=car_data) def close(self): diff --git a/rlgym/rocket_league/sim/rocketsim_engine.py b/rlgym/rocket_league/sim/rocketsim_engine.py index c5b8db0..7b19ba1 100644 --- a/rlgym/rocket_league/sim/rocketsim_engine.py +++ b/rlgym/rocket_league/sim/rocketsim_engine.py @@ -5,7 +5,7 @@ import numpy as np from rlgym.api import TransitionEngine, AgentID from rlgym.rocket_league.api import Car, GameConfig, GameState, PhysicsObject -from rlgym.rocket_league.common_values import BOOST_CONSUMPTION_RATE, GRAVITY, GOAL_THRESHOLD +from rlgym.rocket_league.common_values import BOOST_CONSUMPTION_RATE, GRAVITY, GOAL_THRESHOLD, GOAL_THRESHOLD_Z_HOOPS class RocketSimEngine(TransitionEngine[AgentID, GameState, np.ndarray]): @@ -40,6 +40,13 @@ def __init__(self, rlbot_delay=True, game_mode: rsim.GameMode = rsim.GameMode.SO self._touches: Dict[int, int] = {} self._arena = rsim.Arena(game_mode) self._arena.set_ball_touch_callback(self._ball_touch_callback) + self._game_mode = game_mode + if game_mode == rsim.GameMode.SOCCAR: + self._GOAL_THRESHOLD = GOAL_THRESHOLD + elif game_mode == rsim.GameMode.HOOPS: + self._GOAL_THRESHOLD = GOAL_THRESHOLD_Z_HOOPS + else: + raise ValueError("Unknown game mode") @property def agents(self) -> List[AgentID]: @@ -149,6 +156,28 @@ def set_state(self, desired_state: GameState, shared_info: Dict[str, Any]) -> Ga return self._get_state() + def _get_goal_scored(self, ball_position) -> bool: + if self._game_mode == rsim.GameMode.HOOPS: + # TODO check a simple box around the hoop before more expensive calcs + # should save a bit of time since ball_z <270 happens really often + if ball_position[2] < self._GOAL_THRESHOLD: + # Then check if ball is within the hoop's XY circular area + SCALE_Y = 0.9 + OFFSET_Y = 2770.0 + RADIUS_SQ = 512656 # is 716 * 716 in original code in RocketSim, but hard coded the result + + x = ball_position[0] + y = ball_position[1] + + dy = abs(y) * SCALE_Y - OFFSET_Y + dist_sq = x * x + dy * dy + + # Ball is in hoop if distance is less than radius + return dist_sq < RADIUS_SQ + return False + else: + return abs(ball_position[1]) > self._GOAL_THRESHOLD + def _get_state(self) -> GameState: gs = GameState() gs.tick_count = self._tick_count @@ -161,8 +190,7 @@ def _get_state(self) -> GameState: gs.ball.angular_velocity = ball_state.ang_vel.as_numpy() gs.ball.rotation_mtx = np.ascontiguousarray(ball_state.rot_mat.as_numpy().reshape(3, 3).transpose()) - # Only works for soccar - gs.goal_scored = abs(gs.ball.position[1]) > GOAL_THRESHOLD + gs.goal_scored = self._get_goal_scored(gs.ball.position) gs.cars = {} for agent_id, rsim_car in self._cars.items():