Compare commits
3
Commits
c993e80a71
...
dev1
| 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
|
import wx
|
||||||
|
|
||||||
|
from mind_reader.core import GameState
|
||||||
from mind_reader.ui.dialogs import ClientConnectDialog, ServerStartDialog
|
from mind_reader.ui.dialogs import ClientConnectDialog, ServerStartDialog
|
||||||
from mind_reader.ui.menu_bar import AppMenuBar
|
from mind_reader.ui.menu_bar import AppMenuBar
|
||||||
|
from mind_reader.ui.views import LobbyPanel
|
||||||
|
|
||||||
|
|
||||||
class MainFrame(wx.Frame):
|
class MainFrame(wx.Frame):
|
||||||
@@ -13,8 +15,14 @@ class MainFrame(wx.Frame):
|
|||||||
size=wx.Size(700, 500),
|
size=wx.Size(700, 500),
|
||||||
style=wx.DEFAULT_FRAME_STYLE,
|
style=wx.DEFAULT_FRAME_STYLE,
|
||||||
)
|
)
|
||||||
|
self.state: GameState | None = None
|
||||||
|
self.lobby_panel: LobbyPanel | None = None
|
||||||
|
|
||||||
self.Center()
|
self.Center()
|
||||||
|
|
||||||
|
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
self.SetSizer(self.main_sizer)
|
||||||
|
|
||||||
self.menu_bar = AppMenuBar(self)
|
self.menu_bar = AppMenuBar(self)
|
||||||
self.SetMenuBar(self.menu_bar)
|
self.SetMenuBar(self.menu_bar)
|
||||||
|
|
||||||
@@ -32,10 +40,29 @@ class MainFrame(wx.Frame):
|
|||||||
wx.EVT_MENU, self.on_disconnect, self.menu_bar.item_disconnect
|
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):
|
def on_client_connect(self, event):
|
||||||
d = ClientConnectDialog(self)
|
d = ClientConnectDialog(self)
|
||||||
if d.ShowModal() == wx.ID_OK:
|
if d.ShowModal() == wx.ID_OK:
|
||||||
name, ip = d.get_data()
|
name, ip = d.get_data()
|
||||||
|
self.state = GameState(name)
|
||||||
|
|
||||||
|
self._show_lobby()
|
||||||
|
|
||||||
self.menu_bar.set_connected_state(True)
|
self.menu_bar.set_connected_state(True)
|
||||||
self.SetStatusText(f"Подключено к {ip} | Ваше имя {name}")
|
self.SetStatusText(f"Подключено к {ip} | Ваше имя {name}")
|
||||||
d.Destroy()
|
d.Destroy()
|
||||||
@@ -44,10 +71,18 @@ class MainFrame(wx.Frame):
|
|||||||
d = ServerStartDialog(self)
|
d = ServerStartDialog(self)
|
||||||
if d.ShowModal() == wx.ID_OK:
|
if d.ShowModal() == wx.ID_OK:
|
||||||
name, ip = d.get_data()
|
name, ip = d.get_data()
|
||||||
|
self.state = GameState(name)
|
||||||
|
|
||||||
|
self._show_lobby()
|
||||||
|
|
||||||
self.menu_bar.set_connected_state(True)
|
self.menu_bar.set_connected_state(True)
|
||||||
self.SetStatusText(f"Сервер запущен на {ip} | Ваше имя {name}")
|
self.SetStatusText(f"Сервер запущен на {ip} | Ваше имя {name}")
|
||||||
d.Destroy()
|
d.Destroy()
|
||||||
|
|
||||||
def on_disconnect(self, event):
|
def on_disconnect(self, event):
|
||||||
|
self._destroy_lobby()
|
||||||
|
|
||||||
|
self.state = None
|
||||||
|
|
||||||
self.menu_bar.set_connected_state(False)
|
self.menu_bar.set_connected_state(False)
|
||||||
self.SetStatusText("Подключение отсутствует")
|
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