Newer
Older
import argparse
import signal
import subprocess

Fabian Heinrich
committed
import sys
from subprocess import Popen
import requests
from pygame import mixer
from websockets.sync.client import connect
from cooperative_cuisine import ROOT_DIR
from cooperative_cuisine.action import ActionType, InterActionData, Action
from cooperative_cuisine.game_server import (
CreateEnvironmentConfig,
WebsocketMessage,
PlayerRequestType,
)
from cooperative_cuisine.pygame_2d_vis.drawing import Visualizer
from cooperative_cuisine.pygame_2d_vis.game_colors import colors
from cooperative_cuisine.state_representation import StateRepresentation
from cooperative_cuisine.utils import (
url_and_port_arguments,
disable_websocket_logging_arguments,
add_list_of_manager_ids_arguments,

Fabian Heinrich
committed
setup_logging,
class MenuStates(Enum):
Start = "Start"
ControllerTutorial = "ControllerTutorial"
PreGame = "PreGame"
"""The logger for this module."""
"""Set of keyboard keys for controlling a player.
First four keys are for movement. Order: Down, Up, Left, Right.
5th key is for interacting with counters.
6th key ist for picking up things or dropping them.

Fabian Heinrich
committed
def __init__(
self,
move_keys: list[pygame.key],
interact_key: pygame.key,
pickup_key: pygame.key,
switch_key: pygame.key,

Fabian Heinrich
committed
):
"""Creates a player key set which contains information about which keyboard keys control the player.

Fabian Heinrich
committed
Movement keys in the following order: Down, Up, Left, Right
Args:
move_keys: The keys which control this players movement in the following order: Down, Up, Left, Right.
interact_key: The key to interact with objects in the game.
pickup_key: The key to pick items up or put them down.
switch_key: The key for switching through controllable players.
players: The player indices which this keyset can control.
joystick: number of joystick (later check if available)

Fabian Heinrich
committed
"""

Fabian Heinrich
committed
self.move_vectors: list[list[int]] = [[-1, 0], [1, 0], [0, -1], [0, 1]]
self.key_to_movement: dict[pygame.key, list[int]] = {
key: vec for (key, vec) in zip(move_keys, self.move_vectors)

Fabian Heinrich
committed
self.move_keys: list[pygame.key] = move_keys
self.interact_key: pygame.key = interact_key
self.pickup_key: pygame.key = pickup_key
self.switch_key: pygame.key = switch_key
self.controlled_players: list[str] = players
self.current_player: str = players[0] if players else "0"
self.current_idx = 0
self.other_keyset: list[PlayerKeySet] = []
self.joystick = joystick

Fabian Heinrich
committed
def set_controlled_players(self, controlled_players: list[str]) -> None:

Fabian Heinrich
committed
self.controlled_players = controlled_players
self.current_player = self.controlled_players[0]
self.current_idx = 0

Fabian Heinrich
committed
def next_player(self) -> None:
self.current_idx = (self.current_idx + 1) % len(self.controlled_players)
if self.other_keyset:
for ok in self.other_keyset:
if ok.current_idx == self.current_idx:
self.next_player()
return
self.current_player = self.controlled_players[self.current_idx]
"""Visualisation of the overcooked environment and reading keyboard inputs using pygame."""

Fabian Heinrich
committed
def __init__(
study_host: str,
study_port: int,
game_host: str,
game_port: int,

Fabian Heinrich
committed
CONNECT_WITH_STUDY_SERVER: bool,
USE_AAAMBOS_AGENT: bool,

Fabian Heinrich
committed
):

Fabian Heinrich
committed
self.CONNECT_WITH_STUDY_SERVER = CONNECT_WITH_STUDY_SERVER
self.USE_AAAMBOS_AGENT = USE_AAAMBOS_AGENT
pygame.image.load(ROOT_DIR / "pygame_2d_vis" / "images" / "brain_icon.png")

Fabian Heinrich
committed
self.participant_id = uuid.uuid4().hex
self.game_screen: pygame.Surface | None = None
self.running = True
self.key_sets: list[PlayerKeySet] = []
self.websocket_url = f"ws://{game_host}:{game_port}/ws/player/"
self.websockets = {}
if CONNECT_WITH_STUDY_SERVER:
self.request_url = f"http://{study_host}:{study_port}"
else:
self.request_url = f"http://{game_host}:{game_port}"
self.manager_id = random.choice(manager_ids)
with open(ROOT_DIR / "pygame_2d_vis" / "visualization.yaml", "r") as file:
self.visualization_config = yaml.safe_load(file)
self.FPS = self.visualization_config["GameWindow"]["FPS"]
self.screen_margin = self.visualization_config["GameWindow"]["screen_margin"]
self.min_width = self.visualization_config["GameWindow"]["min_width"]
self.min_height = self.visualization_config["GameWindow"]["min_height"]
self.buttons_width = self.visualization_config["GameWindow"]["buttons_width"]
self.buttons_height = self.visualization_config["GameWindow"]["buttons_height"]

Fabian Heinrich
committed
self.order_bar_height = self.visualization_config["GameWindow"][
"order_bar_height"
]
(
self.window_width_fullscreen,
self.window_height_fullscreen,
) = pygame.display.get_desktop_sizes()[0]
if (
self.window_width_fullscreen >= 3840
and self.window_height_fullscreen >= 2160
):
self.window_width_fullscreen /= 2
self.window_height_fullscreen /= 2
self.window_width_windowed = self.min_width
self.window_height_windowed = self.min_height
self.kitchen_width = 1
self.kitchen_height = 1
self.kitchen_aspect_ratio = 1
self.images_path = ROOT_DIR / "pygame_gui" / "images"
self.vis = Visualizer(self.visualization_config)
self.menu_state = MenuStates.Start
self.manager: pygame_gui.UIManager
self.sub_processes = []
self.layout_file_paths = sorted(
(ROOT_DIR / "configs" / "layouts").rglob("*.layout")
self.last_state: StateRepresentation
self.player_info = {"0": {"name": "0"}}
self.level_info = {"name": "Level", "recipe_graphs": []}

Fabian Heinrich
committed
self.beeped_once = False
self.all_completed_meals = []
self.last_completed_meals = []
self.all_recipes_labels = []
self.last_recipes_labels = []
def setup_player_keys(self, players: list[str], number_key_sets=1, disjunct=False):
# First four keys are for movement. Order: Down, Up, Left, Right.
# 5th key is for interacting with counters.
# 6th key ist for picking up things or dropping them.

Fabian Heinrich
committed
if number_key_sets:
key_set1 = PlayerKeySet(
move_keys=[pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s],
interact_key=pygame.K_f,
pickup_key=pygame.K_e,
switch_key=pygame.K_SPACE,
players=players,
)
key_set2 = PlayerKeySet(
move_keys=[pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN],
interact_key=pygame.K_i,
pickup_key=pygame.K_o,
switch_key=pygame.K_p,
players=players,

Fabian Heinrich
committed
)
key_sets = [key_set1, key_set2]
if disjunct:
key_set1.set_controlled_players(players[::2])
key_set2.set_controlled_players(players[1::2])

Fabian Heinrich
committed
elif number_key_sets > 1:
key_set1.set_controlled_players(players)
key_set2.set_controlled_players(players)
key_set1.other_keyset = [key_set2]
key_set2.other_keyset = [key_set1]
key_set2.next_player()

Fabian Heinrich
committed
return key_sets[:number_key_sets]
else:
return []

Fabian Heinrich
committed
def handle_keys(self):
"""Handles keyboard inputs. Sends action for the respective players. When a key is held down, every frame
an action is sent in this function.
"""

Fabian Heinrich
committed

Fabian Heinrich
committed
for key_set in self.key_sets:
current_player_name = str(key_set.current_player)
relevant_keys = [keys[k] for k in key_set.move_keys]
if any(relevant_keys):

Fabian Heinrich
committed
for idx, pressed in enumerate(relevant_keys):
move_vec += key_set.move_vectors[idx]
if np.linalg.norm(move_vec) != 0:
move_vec = move_vec / np.linalg.norm(move_vec)
action = Action(

Fabian Heinrich
committed
current_player_name,
ActionType.MOVEMENT.value,

Fabian Heinrich
committed
move_vec,
self.send_action(action)
def handle_joy_stick_input(self, joysticks):
"""Handles joystick inputs for movement every frame
Args:
joysticks: list of joysticks
# Axis 0: joy stick left: -1 = left, ~0 = center, 1 = right
# Axis 1: joy stick left: -1 = up, ~0 = center, 1 = down
# see control stuff here (at the end of the page): https://www.pygame.org/docs/ref/joystick.html
current_player_name = str(key_set.current_player)
# if a joystick is connected for current player
if key_set.joystick in joysticks:
# Usually axis run in pairs, up/down for one, and left/right for the other. Triggers count as axes.
# You may want to take into account some tolerance to handle jitter, and
# joystick drift may keep the joystick from centering at 0 or using the full range of position values.
tolerance_threshold = 0.2
# axis 0 = joy stick left --> left & right
axis_left_right = joysticks[key_set.joystick].get_axis(0)
axis_up_down = joysticks[key_set.joystick].get_axis(1)
if (
abs(axis_left_right) > tolerance_threshold
or abs(axis_up_down) > tolerance_threshold
):
move_vec = np.zeros(2)
if abs(axis_left_right) > tolerance_threshold:
move_vec[0] += axis_left_right
# axis 1 = joy stick right --> up & down
if abs(axis_up_down) > tolerance_threshold:
move_vec[1] += axis_up_down
# if np.linalg.norm(move_vec) != 0:
# move_vec = move_vec / np.linalg.norm(move_vec)
action = Action(
ActionType.MOVEMENT.value,
)
self.send_action(action)
def handle_key_event(self, event):

Fabian Heinrich
committed
"""Handles key events for the pickup and interaction keys. Pickup is a single action,
for interaction keydown and keyup is necessary, because the player has to be able to hold
the key down.

Fabian Heinrich
committed
event: Pygame event for extracting the key action.

Fabian Heinrich
committed
for key_set in self.key_sets:
current_player_name = str(key_set.current_player)
if event.key == key_set.pickup_key and event.type == pygame.KEYDOWN:
action = Action(current_player_name, ActionType.PICK_UP_DROP, None)
self.send_action(action)

Fabian Heinrich
committed
if event.key == key_set.interact_key:

Fabian Heinrich
committed
if event.type == pygame.KEYDOWN:

Florian Schröder
committed
action = Action(

Fabian Heinrich
committed
current_player_name, ActionType.INTERACT, InterActionData.START

Florian Schröder
committed
)
self.send_action(action)

Fabian Heinrich
committed
elif event.type == pygame.KEYUP:

Florian Schröder
committed
action = Action(

Fabian Heinrich
committed
current_player_name, ActionType.INTERACT, InterActionData.STOP

Florian Schröder
committed
)
self.send_action(action)
if event.key == key_set.switch_key:

Fabian Heinrich
committed
if event.type == pygame.KEYDOWN:
key_set.next_player()
def handle_joy_stick_event(self, event, joysticks):
"""Handles joy stick events for the pickup and interaction keys. Pickup is a single action,
for interaction buttondown and buttonup is necessary, because the player has to be able to hold
the button down.
Args:
event: Pygame event for extracting the button action.
joysticks: list of joysticks
current_player_name = str(key_set.current_player)
# if a joystick is connected for current player
if key_set.joystick in joysticks:
# pickup = Button A <-> 0
if (
joysticks[key_set.joystick].get_button(0)
and event.type == pygame.JOYBUTTONDOWN
):
action = Action(current_player_name, ActionType.PICK_UP_DROP, None)
self.send_action(action)
# interact = Button X <-> 2
if (
joysticks[key_set.joystick].get_button(2)
and event.type == pygame.JOYBUTTONDOWN
):
action = Action(
current_player_name, ActionType.INTERACT, InterActionData.START
)
self.send_action(action)
# stop interaction if last pressed button was X <-> 2
if event.button == 2 and event.type == pygame.JOYBUTTONUP:
action = Action(
current_player_name, ActionType.INTERACT, InterActionData.STOP
)
self.send_action(action)
if joysticks[key_set.joystick].get_button(3):
if event.type == pygame.JOYBUTTONDOWN:
key_set.next_player()
def set_window_size(self):
if self.fullscreen:
flags = pygame.FULLSCREEN
self.window_width = self.window_width_fullscreen
self.window_height = self.window_height_fullscreen
else:
flags = 0
self.window_width = self.window_width_windowed
self.window_height = self.window_height_windowed
self.main_window = pygame.display.set_mode(

Fabian Heinrich
committed
(
self.window_width,
self.window_height,
flags=flags,
def reset_window_size(self):
self.game_width = 0
self.game_height = 0
self.set_window_size()
def set_game_size(self, max_width=None, max_height=None):
if max_width is None:
max_width = self.window_width - (2 * self.screen_margin)
if max_height is None:
max_height = self.window_height - (2 * self.screen_margin)
self.kitchen_aspect_ratio = self.kitchen_height / self.kitchen_width
if self.kitchen_width > self.kitchen_height:
self.game_width = max_width
self.game_height = self.game_width * self.kitchen_aspect_ratio
if self.game_height > max_height:
self.game_height = max_height
self.game_width = self.game_height / self.kitchen_aspect_ratio
else:
self.game_height = max_height
self.game_width = self.game_height / self.kitchen_aspect_ratio
if self.game_width > max_width:
self.game_width = max_width
self.game_height = self.game_width * self.kitchen_aspect_ratio
self.grid_size = int(self.game_width / self.kitchen_width)
self.game_width = max(self.game_width, 100)
self.game_height = max(self.game_height, 100)
self.grid_size = max(self.grid_size, 1)
residual_x = self.game_width - (self.kitchen_width * self.grid_size)
residual_y = self.game_height - (self.kitchen_height * self.grid_size)
self.game_width -= residual_x
self.game_height -= residual_y
self.game_screen = pygame.Surface(
(
self.game_width,
self.game_height,
)
def init_ui_elements(self):
self.manager = pygame_gui.UIManager((self.window_width, self.window_height))
self.manager.get_theme().load_theme(
ROOT_DIR / "pygame_2d_vis" / "gui_theme.json"
)

Fabian Heinrich
committed
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
########################################################################
# All screens
########################################################################
fullscreen_button_rect = pygame.Rect(
(0, 0), (self.buttons_width * 0.7, self.buttons_height)
)
fullscreen_button_rect.topright = (-self.buttons_width, 0)
self.fullscreen_button = pygame_gui.elements.UIButton(
relative_rect=fullscreen_button_rect,
text="Fullscreen",
manager=self.manager,
object_id="#fullscreen_button",
anchors={"right": "right", "top": "top"},
)
rect = pygame.Rect((0, 0), (self.buttons_width, self.buttons_height))
rect.topright = (0, 0)
self.quit_button = pygame_gui.elements.UIButton(
relative_rect=rect,
text="Quit Game",
manager=self.manager,
object_id="#quit_button",
anchors={"right": "right", "top": "top"},
)
########################################################################
# Start screen
########################################################################
self.start_button = pygame_gui.elements.UIButton(
relative_rect=pygame.Rect(

Fabian Heinrich
committed
(0, 0), (self.buttons_width, self.buttons_height)

Fabian Heinrich
committed
anchors={"center": "center"},
ROOT_DIR / "pygame_2d_vis" / "continue.drawio.png"
).convert_alpha()
image_rect = img.get_rect()
image_rect.centery += 80
self.press_a_image = pygame_gui.elements.UIImage(
image_rect,
img,
anchors={"centerx": "centerx", "centery": "centery"},
img_width = self.buttons_width * 1.5
img_height = img_width * (image_rect.height / image_rect.width)
new_dims = (img_width, img_height)
self.press_a_image.set_dimensions(new_dims)

Fabian Heinrich
committed
player_selection_rect = pygame.Rect(
(0, 0),
(
(self.window_height // 4),

Fabian Heinrich
committed
),
)

Fabian Heinrich
committed
self.player_selection_container = pygame_gui.elements.UIPanel(
player_selection_rect,
manager=self.manager,
object_id="#players",
anchors={"bottom": "bottom", "centerx": "centerx"},
)
multiple_keysets_button_rect = pygame.Rect((0, 0), (190, 50))

Fabian Heinrich
committed
self.multiple_keysets_button = pygame_gui.elements.UIButton(
relative_rect=multiple_keysets_button_rect,
manager=self.manager,
container=self.player_selection_container,
text="not set",
anchors={"left": "left", "centery": "centery"},

Fabian Heinrich
committed
)
split_players_button_rect = pygame.Rect((0, 0), (190, 50))

Fabian Heinrich
committed
self.split_players_button = pygame_gui.elements.UIButton(
relative_rect=split_players_button_rect,
manager=self.manager,
container=self.player_selection_container,
text="not set",
anchors={"centerx": "centerx", "centery": "centery"},

Fabian Heinrich
committed
)

Fabian Heinrich
committed
players_container_rect = pygame.Rect(
(0, 0),
(
self.window_width * 0.6,
self.player_selection_container.get_abs_rect().height // 3,
),

Fabian Heinrich
committed
)
self.player_number_container = pygame_gui.elements.UIPanel(

Fabian Heinrich
committed
relative_rect=players_container_rect,
manager=self.manager,
object_id="#players_players",
container=self.player_selection_container,
anchors={"top": "top", "centerx": "centerx"},
)
bot_container_rect = pygame.Rect(
(0, 0),
(
self.window_width * 0.6,
self.player_selection_container.get_abs_rect().height // 3,
),

Fabian Heinrich
committed
)
bot_container_rect.bottom = 0
self.bot_number_container = pygame_gui.elements.UIPanel(

Fabian Heinrich
committed
relative_rect=bot_container_rect,
manager=self.manager,
object_id="#players_bots",
container=self.player_selection_container,
anchors={"bottom": "bottom", "centerx": "centerx"},
)
number_players_rect = pygame.Rect((0, 0), (200, 200))
self.added_players_label = pygame_gui.elements.UILabel(
number_players_rect,
manager=self.manager,
object_id="#number_players_label",
container=self.player_number_container,

Fabian Heinrich
committed
text=f"Humans to be added: -",

Fabian Heinrich
committed
anchors={"center": "center"},
)
number_bots_rect = pygame.Rect((0, 0), (200, 200))
self.added_bots_label = pygame_gui.elements.UILabel(
number_bots_rect,
manager=self.manager,
object_id="#number_bots_label",
container=self.bot_number_container,

Fabian Heinrich
committed
text=f"Bots to be added: -",

Fabian Heinrich
committed
anchors={"center": "center"},
)

Fabian Heinrich
committed
add_player_button_rect = pygame.Rect((0, 0), (size, size))
add_player_button_rect.right = 0
self.add_human_player_button = pygame_gui.elements.UIButton(
relative_rect=add_player_button_rect,
text="+",
manager=self.manager,

Fabian Heinrich
committed
anchors={"right": "right", "centery": "centery"},
)
remove_player_button_rect = pygame.Rect((0, 0), (size, size))
remove_player_button_rect.left = 0
self.remove_human_button = pygame_gui.elements.UIButton(
relative_rect=remove_player_button_rect,
text="-",
manager=self.manager,

Fabian Heinrich
committed
anchors={"left": "left", "centery": "centery"},
)
add_bot_button_rect = pygame.Rect((0, 0), (size, size))
add_bot_button_rect.right = 0
self.add_bot_button = pygame_gui.elements.UIButton(
relative_rect=add_bot_button_rect,
text="+",
manager=self.manager,

Fabian Heinrich
committed
anchors={"right": "right", "centery": "centery"},
)
remove_bot_button_rect = pygame.Rect((0, 0), (size, size))
remove_bot_button_rect.left = 0
self.remove_bot_button = pygame_gui.elements.UIButton(
relative_rect=remove_bot_button_rect,
text="-",
manager=self.manager,

Fabian Heinrich
committed
anchors={"left": "left", "centery": "centery"},
)
########################################################################
# Tutorial screen
########################################################################

Fabian Heinrich
committed
button_rect = pygame.Rect((0, 0), (220, 80))
button_rect.bottom = -20
self.continue_button = pygame_gui.elements.UIButton(
relative_rect=button_rect,
text="Continue",
manager=self.manager,
anchors={"centerx": "centerx", "bottom": "bottom"},
)
ROOT_DIR / "pygame_2d_vis" / "tutorial_files" / "tutorial.drawio.png"
).convert_alpha()
image_rect = image.get_rect()

Fabian Heinrich
committed
img_width = self.window_width * 0.7
img_height = img_width * (image_rect.height / image_rect.width)
new_dims = (img_width, img_height)
image = pygame.transform.scale(image, new_dims)
image_rect = image.get_rect()
# image_rect.topleft = (20, self.buttons_height)
# image_rect.topleft = (0, 0)
image_rect.left = self.window_width * 0.01
self.tutorial_image = pygame_gui.elements.UIImage(
image_rect,
image,
manager=self.manager,

Fabian Heinrich
committed
anchors={"centery": "centery", "left": "left"},

Fabian Heinrich
committed
rect = pygame.Rect(
(0, 0),
(self.window_width * 0.27, self.window_height * 0.3),
)
rect.right = 0
rect.top = self.window_height * 0.1
self.tutorial_recipe_container = pygame_gui.elements.UIPanel(
relative_rect=rect,

Fabian Heinrich
committed
object_id="#graph_container",
anchors={"right": "right", "top_target": self.quit_button},

Fabian Heinrich
committed
self.tutorial_recipe_graph_rect = pygame.Rect(
(0, 0), (self.window_width * 0.25, self.window_height * 0.2)

Fabian Heinrich
committed
# self.tutorial_recipe_graph_rect.bottom = 0
self.tutorial_graph_image = pygame_gui.elements.UIImage(
relative_rect=self.tutorial_recipe_graph_rect,
image_surface=pygame.Surface(self.tutorial_recipe_graph_rect.size),

Fabian Heinrich
committed
object_id="#recipe_graph",
container=self.tutorial_recipe_container,
anchors={"centerx": "centerx", "top": "top"},
)
r = pygame.Rect((0, 0), (self.window_width * 0.25, self.buttons_height))
r.bottom = 0
text = pygame_gui.elements.UILabel(
text="Try making this recipe:",
relative_rect=r,
manager=self.manager,
container=self.tutorial_recipe_container,
anchors={
"centerx": "centerx",
"bottom": "bottom",
},
########################################################################
# PreGame screen
########################################################################
rect = pygame.Rect(
(0, 0),
(self.window_width, 50),
)
rect.top = 20
self.level_name_label = pygame_gui.elements.UILabel(
text=f"not set",
self.text_recipes_label = pygame_gui.elements.UILabel(
text=f"Recipes in this level:",
relative_rect=pygame.Rect(
(0, 0),
),
manager=self.manager,
anchors={"centerx": "centerx", "top_target": self.level_name_label},
)
scroll_height = (
self.continue_button.get_abs_rect().top
- self.text_recipes_label.get_abs_rect().bottom
)
self.scroll_width = self.window_width
self.scroll_space = pygame_gui.elements.UIScrollingContainer(
relative_rect=pygame.Rect((0, 0), (self.scroll_width, scroll_height)),
manager=self.manager,
anchors={"centerx": "centerx", "top_target": self.text_recipes_label},
)
########################################################################
# Game screen
########################################################################
self.orders_label = pygame_gui.elements.UILabel(
text="Orders:",
relative_rect=pygame.Rect(0, 0, self.screen_margin, self.screen_margin),
manager=self.manager,
object_id="#orders_label",
)

Fabian Heinrich
committed
rect = pygame.Rect(
(0, 0),
(self.window_width * 0.2, self.buttons_height),
)
rect.bottomleft = (0, 0)
self.score_label = pygame_gui.elements.UILabel(

Fabian Heinrich
committed
text=f"Score not set",
relative_rect=rect,
manager=self.manager,
object_id="#score_label",

Fabian Heinrich
committed
anchors={"bottom": "bottom", "left": "left"},

Fabian Heinrich
committed
rect = pygame.Rect(
(0, 0),
(self.window_width * 0.4, self.buttons_height),
)
rect.bottom = 0
self.timer_label = pygame_gui.elements.UILabel(

Fabian Heinrich
committed
text="GAMETIME not set",
relative_rect=rect,
manager=self.manager,
object_id="#timer_label",

Fabian Heinrich
committed
anchors={"bottom": "bottom", "centerx": "centerx"},
)
rect = pygame.Rect(
(0, 0),
(self.window_width, self.screen_margin),
)
rect.right = 20
self.wait_players_label = pygame_gui.elements.UILabel(
text="WAITING FOR OTHER PLAYERS",
relative_rect=rect,
manager=self.manager,
object_id="#wait_players_label",
anchors={"centery": "centery", "right": "right"},
########################################################################
# PostGame screen
########################################################################
self.next_game_button = pygame_gui.elements.UIButton(
manager=self.manager,
text="Next game",
anchors={"centerx": "centerx", "bottom": "bottom"},
object_id="#split_players_button",
)
self.finish_study_button = pygame_gui.elements.UIButton(
manager=self.manager,
text="Finish study",
anchors={"centerx": "centerx", "bottom": "bottom"},
object_id="#split_players_button",
)
rect = pygame.Rect(
(0, 0),
(self.window_width, 50),
)
self.score_conclusion = pygame_gui.elements.UILabel(
text=f"not set",
relative_rect=rect,
manager=self.manager,
object_id="#level_name",
anchors={"centerx": "centerx", "top_target": self.level_name_label},
)
self.completed_meals_text_label = pygame_gui.elements.UILabel(
text=f"Completed meals:",
relative_rect=pygame.Rect(
(0, 0),
(self.window_width * 0.7, 50),
),
manager=self.manager,
object_id="#level_name",
anchors={"centerx": "centerx", "top_target": self.score_conclusion},
)
########################################################################
# End screen
########################################################################
rect = pygame.Rect(0, 0, self.window_width * 0.9, self.window_height * 0.4)
final_text_container = pygame_gui.elements.UIPanel(
relative_rect=rect,
manager=self.manager,
object_id="#graph_container",
anchors={"center": "center"},
rect = pygame.Rect((0, 0), (-1, -1))
text1 = pygame_gui.elements.UILabel(
text="Thank you for participanting in this study :)",
relative_rect=rect,
manager=self.manager,
object_id="#score_label",
container=final_text_container,
anchors={"top": "top", "left": "left", "right": "right"},
)
rect = pygame.Rect((0, 0), (-1, -1))
text2 = pygame_gui.elements.UILabel(
text="Please wait for instructions from the study supervisor.",
relative_rect=rect,
manager=self.manager,
object_id="#score_label",
container=final_text_container,
anchors={"top_target": text1, "left": "left", "right": "right"},
########################################################################
self.start_screen_elements = [
self.start_button,
self.quit_button,
self.fullscreen_button,
self.player_selection_container,
]
self.tutorial_screen_elements = [
self.tutorial_image,
self.continue_button,
self.fullscreen_button,

Fabian Heinrich
committed
self.tutorial_recipe_container,
]
self.pregame_screen_elements = [
self.continue_button,
self.quit_button,
self.fullscreen_button,
]
self.game_screen_elements = [
self.orders_label,
self.score_label,
self.timer_label,

Fabian Heinrich
committed
self.wait_players_label,
]

Fabian Heinrich
committed
self.postgame_screen_elements = [
self.scroll_space,
self.next_game_button,
self.finish_study_button,
]

Fabian Heinrich
committed
self.end_screen_elements = [
self.fullscreen_button,
self.quit_button,
final_text_container,
]

Fabian Heinrich
committed
self.rest = [
self.fullscreen_button,
self.quit_button,
]
def show_screen_elements(self, elements: list):
for element in (
self.start_screen_elements
+ self.tutorial_screen_elements
+ self.pregame_screen_elements
+ self.game_screen_elements
+ self.postgame_screen_elements
+ self.end_screen_elements

Fabian Heinrich
committed
+ self.rest
):
element.hide()
for element in elements:
element.show()

Fabian Heinrich
committed
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
def update_tutorial_screen(self):
self.show_screen_elements(self.tutorial_screen_elements)
self.set_game_size(
max_height=self.window_height * 0.4,
max_width=self.window_width * 0.3,
)
self.game_center = (
self.window_width - self.game_width / 2 - (self.window_width * 0.015),
self.window_height - self.game_height / 2 - (self.window_height * 0.015),
)
width, height = self.tutorial_recipe_graph_rect.size
tutorial_graph_surface = pygame.Surface(
self.tutorial_recipe_graph_rect.size, flags=pygame.SRCALPHA
)
self.vis.draw_recipe_image(
tutorial_graph_surface,
self.level_info["recipe_graphs"][0],
width,
height,
grid_size=self.window_height / 16,
)
self.tutorial_graph_image.set_image(tutorial_graph_surface)
# self.tutorial_graph_image.set_dimensions((self.game_width, self.game_height))
def update_screen_elements(self):
match self.menu_state:
case MenuStates.Start:
self.show_screen_elements(self.start_screen_elements)

Fabian Heinrich
committed
if self.CONNECT_WITH_STUDY_SERVER:
self.bot_number_container.hide()
self.update_selection_elements()
case MenuStates.ControllerTutorial:

Fabian Heinrich
committed
self.update_tutorial_screen()
self.show_screen_elements(self.pregame_screen_elements)
self.show_screen_elements(self.game_screen_elements)
self.show_screen_elements(self.postgame_screen_elements)

Fabian Heinrich
committed
if self.last_level:

Fabian Heinrich
committed
self.next_game_button.hide()
self.finish_study_button.show()
else:
self.next_game_button.show()
self.finish_study_button.hide()
self.show_screen_elements(self.end_screen_elements)
def draw_main_window(self):
self.main_window.fill(
colors[self.visualization_config["GameWindow"]["background_color"]]