Compare commits
3
Commits
c993e80a71
...
3add50cbbc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3add50cbbc | ||
|
|
e533acd9f1 | ||
|
|
a25997992e |
@@ -0,0 +1,5 @@
|
||||
from mind_reader.core.game_state import GameState
|
||||
|
||||
__all__ = [
|
||||
"GameState",
|
||||
]
|
||||
@@ -0,0 +1,33 @@
|
||||
class GameState:
|
||||
def __init__(self, local_player_name: str):
|
||||
self.local_player_name: str = local_player_name
|
||||
self.remote_player_name: str | None = None
|
||||
self.lobby_players: dict[str, str] = {self.local_player_name: "NONE"}
|
||||
|
||||
def add_remote_player(self, player_name: str):
|
||||
self.remote_player_name = player_name
|
||||
self.lobby_players[self.remote_player_name] = "NONE"
|
||||
|
||||
def delete_remote_player(self):
|
||||
if self.remote_player_name in self.lobby_players:
|
||||
del self.lobby_players[self.remote_player_name]
|
||||
self.remote_player_name = None
|
||||
|
||||
def set_player_role(self, player_name: str, role: str) -> bool:
|
||||
current_role = self.lobby_players.get(player_name)
|
||||
if current_role == role:
|
||||
return False
|
||||
|
||||
if role in ["NONE", "SETTER", "GUESSER"]:
|
||||
self.lobby_players[player_name] = role
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@property
|
||||
def local_player_role(self) -> str:
|
||||
return self.lobby_players[self.local_player_name]
|
||||
|
||||
def is_session_ready(self) -> bool:
|
||||
roles = list(self.lobby_players.values())
|
||||
return ("SETTER" in roles) and ("GUESSER" in roles)
|
||||
@@ -1,7 +1,9 @@
|
||||
import wx
|
||||
|
||||
from mind_reader.core import GameState
|
||||
from mind_reader.ui.dialogs import ClientConnectDialog, ServerStartDialog
|
||||
from mind_reader.ui.menu_bar import AppMenuBar
|
||||
from mind_reader.ui.views import LobbyPanel
|
||||
|
||||
|
||||
class MainFrame(wx.Frame):
|
||||
@@ -13,8 +15,14 @@ class MainFrame(wx.Frame):
|
||||
size=wx.Size(700, 500),
|
||||
style=wx.DEFAULT_FRAME_STYLE,
|
||||
)
|
||||
self.state: GameState | None = None
|
||||
self.lobby_panel: LobbyPanel | None = None
|
||||
|
||||
self.Center()
|
||||
|
||||
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.SetSizer(self.main_sizer)
|
||||
|
||||
self.menu_bar = AppMenuBar(self)
|
||||
self.SetMenuBar(self.menu_bar)
|
||||
|
||||
@@ -32,10 +40,29 @@ class MainFrame(wx.Frame):
|
||||
wx.EVT_MENU, self.on_disconnect, self.menu_bar.item_disconnect
|
||||
)
|
||||
|
||||
def _show_lobby(self):
|
||||
self._destroy_lobby()
|
||||
|
||||
if self.state:
|
||||
self.lobby_panel = LobbyPanel(self, self.state)
|
||||
self.main_sizer.Add(self.lobby_panel, 1, wx.EXPAND)
|
||||
self.Layout()
|
||||
|
||||
def _destroy_lobby(self):
|
||||
if self.lobby_panel:
|
||||
self.main_sizer.Detach(self.lobby_panel)
|
||||
self.lobby_panel.Destroy()
|
||||
self.lobby_panel = None
|
||||
self.Layout()
|
||||
|
||||
def on_client_connect(self, event):
|
||||
d = ClientConnectDialog(self)
|
||||
if d.ShowModal() == wx.ID_OK:
|
||||
name, ip = d.get_data()
|
||||
self.state = GameState(name)
|
||||
|
||||
self._show_lobby()
|
||||
|
||||
self.menu_bar.set_connected_state(True)
|
||||
self.SetStatusText(f"Подключено к {ip} | Ваше имя {name}")
|
||||
d.Destroy()
|
||||
@@ -44,10 +71,18 @@ class MainFrame(wx.Frame):
|
||||
d = ServerStartDialog(self)
|
||||
if d.ShowModal() == wx.ID_OK:
|
||||
name, ip = d.get_data()
|
||||
self.state = GameState(name)
|
||||
|
||||
self._show_lobby()
|
||||
|
||||
self.menu_bar.set_connected_state(True)
|
||||
self.SetStatusText(f"Сервер запущен на {ip} | Ваше имя {name}")
|
||||
d.Destroy()
|
||||
|
||||
def on_disconnect(self, event):
|
||||
self._destroy_lobby()
|
||||
|
||||
self.state = None
|
||||
|
||||
self.menu_bar.set_connected_state(False)
|
||||
self.SetStatusText("Подключение отсутствует")
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from mind_reader.ui.views.lobby_view import LobbyPanel
|
||||
|
||||
__all__ = [
|
||||
"LobbyPanel",
|
||||
]
|
||||
@@ -0,0 +1,106 @@
|
||||
import wx
|
||||
|
||||
from mind_reader.core import GameState
|
||||
|
||||
|
||||
class RoleColumn(wx.Panel):
|
||||
def __init__(self, parent, role_key: str, button_label: str):
|
||||
super().__init__(parent)
|
||||
self.role_key = role_key
|
||||
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
self.button_select = wx.Button(self, label=button_label)
|
||||
sizer.Add(self.button_select, 0, wx.EXPAND | wx.ALL, 5)
|
||||
|
||||
self.list_players = wx.ListBox(self)
|
||||
sizer.Add(self.list_players, 1, wx.EXPAND | wx.ALL, 5)
|
||||
|
||||
self.SetSizer(sizer)
|
||||
|
||||
def set_players(self, players: list[str]):
|
||||
self.list_players.Clear()
|
||||
if players:
|
||||
self.list_players.AppendItems(players)
|
||||
|
||||
def disable_on_role_match(self, role: str):
|
||||
self.button_select.Enable(self.role_key != role)
|
||||
|
||||
|
||||
class LobbyPanel(wx.Panel):
|
||||
def __init__(self, parent, state: GameState):
|
||||
super().__init__(parent)
|
||||
self.state = state
|
||||
|
||||
self._init_ui()
|
||||
|
||||
def _init_ui(self):
|
||||
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
columns_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.column_none = RoleColumn(self, "NONE", "👤 Без роли")
|
||||
self.column_setter = RoleColumn(self, "SETTER", "🧠 Загадывает")
|
||||
self.column_guesser = RoleColumn(self, "GUESSER", "🕵️ Угадывает")
|
||||
|
||||
columns_sizer.Add(self.column_none, 1, wx.EXPAND | wx.ALL, 5)
|
||||
columns_sizer.Add(self.column_setter, 1, wx.EXPAND | wx.ALL, 5)
|
||||
columns_sizer.Add(self.column_guesser, 1, wx.EXPAND | wx.ALL, 5)
|
||||
|
||||
self.column_none.button_select.Bind(
|
||||
wx.EVT_BUTTON, lambda evt: self._on_role_click("NONE")
|
||||
)
|
||||
self.column_setter.button_select.Bind(
|
||||
wx.EVT_BUTTON, lambda evt: self._on_role_click("SETTER")
|
||||
)
|
||||
self.column_guesser.button_select.Bind(
|
||||
wx.EVT_BUTTON, lambda evt: self._on_role_click("GUESSER")
|
||||
)
|
||||
|
||||
self.button_start = wx.Button(self, label="➔ Начать сессию")
|
||||
self.button_start.Bind(wx.EVT_BUTTON, self._on_start_click)
|
||||
|
||||
main_sizer.Add(columns_sizer, 1, wx.EXPAND | wx.ALL, 5)
|
||||
main_sizer.Add(
|
||||
self.button_start, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10
|
||||
)
|
||||
|
||||
self.SetSizer(main_sizer)
|
||||
|
||||
self.refresh_from_state()
|
||||
|
||||
def _on_role_click(self, target_role: str):
|
||||
success = self.state.set_player_role(
|
||||
self.state.local_player_name, target_role
|
||||
)
|
||||
|
||||
if not success:
|
||||
wx.MessageBox(
|
||||
f"Не удалось занять роль «{target_role}».",
|
||||
"Внимание",
|
||||
wx.OK | wx.ICON_WARNING,
|
||||
)
|
||||
return
|
||||
|
||||
self.refresh_from_state()
|
||||
|
||||
def _on_start_click(self, event):
|
||||
wx.MessageBox("Сессия запущена!", "Старт", wx.OK | wx.ICON_INFORMATION)
|
||||
|
||||
def refresh_from_state(self):
|
||||
players_by_role = {"NONE": [], "SETTER": [], "GUESSER": []}
|
||||
|
||||
for player, role in self.state.lobby_players.items():
|
||||
if role in players_by_role:
|
||||
players_by_role[role].append(player)
|
||||
|
||||
self.column_none.set_players(players_by_role["NONE"])
|
||||
self.column_setter.set_players(players_by_role["SETTER"])
|
||||
self.column_guesser.set_players(players_by_role["GUESSER"])
|
||||
|
||||
local_player_role = self.state.local_player_role
|
||||
self.column_none.disable_on_role_match(local_player_role)
|
||||
self.column_setter.disable_on_role_match(local_player_role)
|
||||
self.column_guesser.disable_on_role_match(local_player_role)
|
||||
|
||||
self.button_start.Enable(self.state.is_session_ready())
|
||||
Reference in New Issue
Block a user