Toggle Navigation
Hatchery
Eggs
CityControlTest
lobby.py
Users
Badges
Login
Register
lobby.py
raw
Content
import display import custom_shapes import utils import easydraw import buttons import game import uasyncio import buttons import main import mch22 import sys import errno from backend import GameClient class Lobby: def __init__(self, code, player_uid, game_info): self.code = code self.game_info = game_info self.player_index = -1 self.player_uid = player_uid self.is_host = False self.player_count = game_info["players"] self.can_start = False # If host, nobody joined yet. If joined, only host can start for i, slot in enumerate(game_info["slots"]): if slot is not None and slot["uid"] == player_uid: print("Found ourselves in slot[%s]:" % i, slot) self.is_host = slot["host"] self.player_index = i def update_game_info(self, game_info): self.game_info = game_info self.player_count = game_info["players"] self.can_start = self.is_host and self.player_count > 1 def draw_lobby(self): player_id = self.player_index utils.draw_background(wifi_indicator=True, logo=False) if self.can_start: easydraw.lineCentered(25, "PRESS START", utils.ARCADE_FONT[12], utils.TEXT_MAIN) easydraw.lineCentered(45, "TO PLAY", utils.ARCADE_FONT[12], utils.TEXT_MAIN) elif self.is_host: easydraw.lineCentered(25, "WAITING FOR", utils.ARCADE_FONT[12], utils.TEXT_MAIN) easydraw.lineCentered(45, "PLAYERS TO JOIN...", utils.ARCADE_FONT[12], utils.TEXT_MAIN) else: easydraw.lineCentered(25, "WAITING FOR", utils.ARCADE_FONT[12], utils.TEXT_MAIN) easydraw.lineCentered(45, "HOST TO PRESS START", utils.ARCADE_FONT[12], utils.TEXT_MAIN) display.drawRect(50, 65, 220, 50, False, utils.HIGHLIGHT) for i, action in enumerate(self.code): self.draw_sign(action, i) if player_id == 0: display.drawRect(25, 125, 60, 60, False, utils.COLOR_SECONDARY) display.drawPng(25, 125, utils.DOWNTOWN) display.drawText(27, 190, "DOWNTOWN", self.get_text_color(0, player_id), utils.ARCADE_FONT[6]) if player_id == 1: display.drawRect(95, 125, 60, 60, False, utils.COLOR_SECONDARY) display.drawPng(95, 125, utils.SCIENCE_PARK if self.player_count >= 2 else utils.SCIENCE_PARK_OFF) display.drawText(100, 190, "SCIENCE", self.get_text_color(1, player_id), utils.ARCADE_FONT[6]) display.drawText(111, 197, "PARK", self.get_text_color(1, player_id), utils.ARCADE_FONT[6]) if player_id == 2: display.drawRect(165, 125, 60, 60, False, utils.COLOR_SECONDARY) display.drawPng(165, 125, utils.COMMERCIAL_AVENUE if self.player_count >= 3 else utils.COMMERCIAL_AVENUE_OFF) display.drawText(160, 190, "COMMERCIAL", self.get_text_color(2, player_id), utils.ARCADE_FONT[6]) display.drawText(174, 197, "AVENUE", self.get_text_color(2, player_id), utils.ARCADE_FONT[6]) if player_id == 3: display.drawRect(235, 125, 60, 60, False, utils.COLOR_SECONDARY) display.drawPng(235, 125, utils.HACKY_HARBOUR if self.player_count >= 4 else utils.HACKY_HARBOUR_OFF) display.drawText(247, 190, "HACKY", self.get_text_color(3, player_id), utils.ARCADE_FONT[6]) display.drawText(240, 197, "HARBOUR", self.get_text_color(3, player_id), utils.ARCADE_FONT[6]) display.flush() def get_text_color(self, district_id, player_id): if district_id == player_id: return utils.TEXT_HIGHLIGHT elif self.player_count > district_id: return utils.TEXT_MAIN else: return utils.TEXT_GRAY def draw_sign(self, action, i): _code_x_start = 68 _code_x_delta = 36 _code_y = 90 if action == "A" or action == "B": display.drawText( _code_x_start + (_code_x_delta * i) - 5, _code_y - 5, action, utils.TEXT_HIGHLIGHT, utils.ARCADE_FONT[18], ) else: custom_shapes.draw_code_arrow( _code_x_start + (_code_x_delta * i), _code_y, action ) def create_lobby(): """ Display create lobby screen when nobody has joined Params: """ if not utils.connect_wifi(): utils.draw_background() easydraw.lineCentered( 180, "WiFi is required to play", utils.ARCADE_FONT[9], utils.TEXT_MAIN ) utils.draw_lines( "Press MENU to return to the main menu", y_start=195, vertical_padding=3, width=display.width() - 50, font=utils.ARCADE_FONT[8], ) display.flush() return if not utils.check_version(): return utils.draw_background() easydraw.lineCentered(180, "Creating game...", utils.ARCADE_FONT[12], utils.TEXT_MAIN) display.flush() loop = uasyncio.get_event_loop() try: game_client = GameClient(loop, create_game=True, namespace="/") except OSError: connection_failed_screen(joining=False) return loop.create_task(connect_game_client(game_client, joining=False)) loop.create_task(buttons_helper_task(game_client)) loop.run_forever() def join_lobby(code): """ Placeholder as this needs to contact the server """ utils.draw_background() easydraw.lineCentered(180, "Joining game...", utils.ARCADE_FONT[12], utils.TEXT_MAIN) display.flush() loop = uasyncio.get_event_loop() try: game_client = GameClient(loop, create_game=False, namespace="/", game_code=utils.code_to_code_string(code)) except OSError: connection_failed_screen(joining=True) return game_client.joining_game = True loop.create_task(connect_game_client(game_client, joining=True)) loop.create_task(buttons_helper_task(game_client)) loop.run_forever() async def connect_game_client(game_client, joining): try: await game_client.connect() except Exception: # Probably one of: [errno.ECONNRESET, errno.ENOTCONN, errno.ECONNABORTED]: connection_failed_screen(joining) def connection_failed_screen(joining): action = "Joining" if joining else "Creating" print("Exception when %s game received:" % action.lower()) utils.draw_background() easydraw.lineCentered(160, action + " Game failed,", utils.ARCADE_FONT[12], utils.TEXT_MAIN) easydraw.lineCentered(180, "Please try again.", utils.ARCADE_FONT[12], utils.TEXT_MAIN) utils.draw_lines( "Press MENU to return to the main menu", y_start=195, vertical_padding=3, width=display.width() - 50, font=utils.ARCADE_FONT[8], ) display.flush() async def buttons_helper_task(game_client): # Somehow, the "await" on the socketio is still blocking for # the button callbacks. So we use this async old-school button # press loop instead. # We start by disabling the default mch22 button handler, # This prevents uPy scheduler warnings on button presses. mch22.set_handler(None) game_button_states = { buttons.BTN_A: False, buttons.BTN_B: False, buttons.BTN_UP: False, buttons.BTN_DOWN: False, buttons.BTN_LEFT: False, buttons.BTN_RIGHT: False, } start_debounce = False while True: if buttons.value(buttons.BTN_HOME): print("Home Button Pressed, rebooting to launcher") await game_client.exit_game() mch22.exit_python() break if buttons.value(buttons.BTN_MENU): print("Menu Button Pressed, ending game") await game_client.exit_game() mch22.set_handler(buttons.hwButtons.__callback) main.main_menu() break if not start_debounce and game_client.lobby and game_client.lobby.can_start and buttons.value(buttons.BTN_START): print("Starting Game") start_debounce = True await game_client.start_game() elif not start_debounce and game_client.instruction_task and buttons.value(buttons.BTN_START): print("Skipping instructions") start_debounce = True game_client.instruction_task.cancel() game_client.instruction_task = None elif start_debounce: if not buttons.value(buttons.BTN_START): start_debounce = False if game_client.game_in_progress: for game_button in game_button_states: # Only consider button presses after the button was previously released pressed = buttons.value(game_button) value = game_button_states[game_button] if not value and pressed: game_button_states[game_button] = True try: await game_client.game_button_pressed(game_button) except Exception as exception: print("Exception on key %d press:" % game_button) sys.print_exception(exception) await game_client.report_exception(exception) except OSError as oserror: if oserror.errno in [errno.ECONNRESET, errno.ENOTCONN, errno.ECONNABORTED]: print("OSError on key %d press:" % game_button) sys.print_exception(oserror) game_client.player_disconnected() elif value and not pressed: game_button_states[game_button] = False await uasyncio.sleep_ms(10)