Skip to content
Snippets Groups Projects
Commit a7e624c1 authored by Fabian Heinrich's avatar Fabian Heinrich
Browse files

Merge branch '44-fov-of-the-players-fog-of-war-like-vision' into 'main'

Resolve "FOV of the players, fog-of-war like vision"

Closes #44

See merge request scs/cocosy/overcooked-simulator!42
parents 7011f0e6 50e2f2c1
No related branches found
No related tags found
1 merge request!42Resolve "FOV of the players, fog-of-war like vision"
Pipeline #45624 passed
......@@ -87,7 +87,8 @@ player_config:
radius: 0.4
player_speed_units_per_seconds: 6
interaction_range: 1.6
restricted_view: False
view_angle: 95
effect_manager:
FireManager:
......
......@@ -238,7 +238,7 @@ class EnvironmentHandler:
):
return self.envs[
self.player_data[player_hash].env_id
].environment.get_json_state()
].environment.get_json_state(self.player_data[player_hash].player_id)
if player_hash not in self.player_data:
return 1
if self.player_data[player_hash].env_id not in self.envs:
......
......@@ -146,6 +146,39 @@ class Visualizer:
grid_size,
)
if "view_restriction" in state and state["view_restriction"]:
# rotate direction vector in both direction with the angel
# draw 2 large rect which are rotated so that one edge is the viewing border
direction = pygame.math.Vector2(state["view_restriction"]["direction"])
pos = pygame.math.Vector2(state["view_restriction"]["position"])
angle = state["view_restriction"]["angle"] / 2
pos = pos * grid_size + pygame.math.Vector2([grid_size / 2, grid_size / 2])
rect_scale = max(width, height)
left_beam = pos + (direction.rotate(angle) * rect_scale * 2)
right_beam = pos + (direction.rotate(-angle) * rect_scale * 2)
pygame.draw.polygon(
screen,
colors["black"],
(
pos - (direction * grid_size * 0.6),
left_beam - (direction * grid_size * 0.6),
left_beam + (direction.rotate(90) * rect_scale),
pos
- (direction * rect_scale * 2)
+ (direction.rotate(90) * rect_scale),
pos
- (direction * rect_scale * 2)
+ (direction.rotate(-90) * rect_scale),
right_beam + (direction.rotate(-90) * rect_scale),
right_beam - (direction * grid_size * 0.6),
),
)
def draw_background(
self, surface: pygame.Surface, width: int, height: int, grid_size: int
):
......
......@@ -28,7 +28,6 @@ from overcooked_simulator.utils import (
url_and_port_arguments,
disable_websocket_logging_arguments,
add_list_of_manager_ids_arguments,
setup_logging,
)
......@@ -936,7 +935,7 @@ class PyGameGUI:
json.dumps(
{
"type": "get_state",
"player_hash": self.player_info[self.state_player_id][
"player_hash": self.player_info[str(self.key_sets[0].current_idx)][
"player_hash"
],
}
......
......@@ -55,6 +55,8 @@ from overcooked_simulator.utils import create_init_env_time, get_closest
log = logging.getLogger(__name__)
FOG_OF_WAR = True
PREVENT_SQUEEZING_INTO_OTHER_PLAYERS = False
......@@ -158,6 +160,14 @@ class Environment:
)
"""The config of the environment. All environment specific attributes is configured here."""
self.player_view_restricted = self.environment_config["player_config"][
"restricted_view"
]
if self.player_view_restricted:
self.player_view_angle = self.environment_config["player_config"][
"view_angle"
]
self.extra_setup_functions()
self.layout_config = layout_config
......@@ -750,25 +760,35 @@ class Environment:
"remaining_time": max(self.env_time_end - self.env_time, timedelta(0)),
}
def get_json_state(self, player_id: str = None):
self.hook(PRE_STATE, player_id=player_id)
state = {
"players": [p.to_dict() for p in self.players.values()],
"counters": [c.to_dict() for c in self.counters],
"kitchen": {"width": self.kitchen_width, "height": self.kitchen_height},
"score": self.order_and_score.score,
"orders": self.order_and_score.order_state(),
"ended": self.game_ended,
"env_time": self.env_time.isoformat(),
"remaining_time": max(
self.env_time_end - self.env_time, timedelta(0)
).total_seconds(),
}
self.hook(STATE_DICT, state=state, player_id=player_id)
json_data = json.dumps(state)
self.hook(JSON_STATE, json_data=json_data, player_id=player_id)
assert StateRepresentation.model_validate_json(json_data=json_data)
return json_data
def get_json_state(self, player_id: str = None) -> str:
if player_id in self.players:
self.hook(PRE_STATE, player_id=player_id)
state = {
"players": [p.to_dict() for p in self.players.values()],
"counters": [c.to_dict() for c in self.counters],
"kitchen": {"width": self.kitchen_width, "height": self.kitchen_height},
"score": self.order_and_score.score,
"orders": self.order_and_score.order_state(),
"ended": self.game_ended,
"env_time": self.env_time.isoformat(),
"remaining_time": max(
self.env_time_end - self.env_time, timedelta(0)
).total_seconds(),
"view_restriction": {
"direction": self.players[player_id].facing_direction.tolist(),
"position": self.players[player_id].pos.tolist(),
"angle": self.player_view_angle,
"counter_mask": None,
}
if self.player_view_restricted
else None,
}
self.hook(STATE_DICT, state=state, player_id=player_id)
json_data = json.dumps(state)
self.hook(JSON_STATE, json_data=json_data, player_id=player_id)
assert StateRepresentation.model_validate_json(json_data=json_data)
return json_data
raise ValueError(f"No valid {player_id=}")
def reset_env_time(self):
"""Reset the env time to the initial time, defined by `create_init_env_time`."""
......
......@@ -33,7 +33,10 @@ class PlayerConfig:
"""The move distance/speed of the player per action call."""
interaction_range: float = 1.6
"""How far player can interact with counters."""
restricted_view: bool = False
"""Whether or not the player can see the entire map at once or just a view frustrum."""
view_angle: int | None = None
"""Angle of the players view if restricted."""
class Player:
"""Class representing a player in the game environment. A player consists of a name, their position and what
......
......@@ -66,6 +66,13 @@ class KitchenInfo(BaseModel):
height: float
class ViewRestriction(BaseModel):
direction: list[float]
position: list[float]
angle: int # degrees
counter_mask: None | list[bool]
class StateRepresentation(BaseModel):
"""The format of the returned state representation."""
......@@ -77,6 +84,7 @@ class StateRepresentation(BaseModel):
ended: bool
env_time: datetime # isoformat str
remaining_time: float
view_restriction: None | ViewRestriction
def create_json_schema():
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment