Init
This commit is contained in:
675
Assets/UnityTestClient/UnityTestClient.cs
Normal file
675
Assets/UnityTestClient/UnityTestClient.cs
Normal file
@@ -0,0 +1,675 @@
|
||||
/*
|
||||
╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ GEOSUS UNITY TEST CLIENT - KOMPLETNÍ PRŮVODCE ║
|
||||
║ ║
|
||||
║ Tento soubor je součástí testovacího klienta pro hru GeoSus - multiplayer GPS hru inspirovanou ║
|
||||
║ hrou Among Us. Tento klient slouží jako referenční implementace pro studenty, kteří chtějí ║
|
||||
║ postavit vlastní hru na základě GeoSus serveru. ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 📚 OBSAH DOKUMENTACE: ║
|
||||
║ ═══════════════════ ║
|
||||
║ ║
|
||||
║ 1. ARCHITEKTURA APLIKACE ║
|
||||
║ 2. SÍŤOVÁ KOMUNIKACE ║
|
||||
║ 3. HERNÍ LOGIKA ║
|
||||
║ 4. UŽIVATELSKÉ ROZHRANÍ ║
|
||||
║ 5. VYKRESLOVÁNÍ MAPY ║
|
||||
║ 6. STATISTIKY HRÁČŮ ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 📁 STRUKTURA SOUBORŮ: ║
|
||||
║ ═════════════════════ ║
|
||||
║ ║
|
||||
║ UnityTestClient_Main.cs - Hlavní třída, inicializace, herní smyčka ║
|
||||
║ UnityTestClient_Network.cs - Síťová komunikace, zpracování zpráv ║
|
||||
║ UnityTestClient_UI.cs - Veškeré uživatelské rozhraní (IMGUI) ║
|
||||
║ UnityTestClient_Map.cs - Vykreslování mapy pomocí 3D objektů ║
|
||||
║ UnityTestClient_Game.cs - Herní mechaniky (pohyb, tasky, sabotáže) ║
|
||||
║ UnityTestClient_Stats.cs - HTTP API pro statistiky hráčů ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 🎮 1. ARCHITEKTURA APLIKACE ║
|
||||
║ ═══════════════════════════ ║
|
||||
║ ║
|
||||
║ Aplikace používá PARTIAL CLASS pattern - všechny soubory definují stejnou třídu ║
|
||||
║ UnityTestClient, která dědí z MonoBehaviour. Unity je automaticky spojí dohromady. ║
|
||||
║ ║
|
||||
║ Hlavní herní stavy (AppState): ║
|
||||
║ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ║
|
||||
║ │ MainMenu │───▶│ Lobby │───▶│ Loading │───▶│ InGame │ ║
|
||||
║ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ ║
|
||||
║ │ │ │ ║
|
||||
║ │ │ ▼ ║
|
||||
║ │ │ ┌─────────────┐ ║
|
||||
║ │ │ │ Meeting │ ║
|
||||
║ │ │ └─────────────┘ ║
|
||||
║ │ │ │ ║
|
||||
║ ▼ ▼ ▼ ║
|
||||
║ ┌─────────────────────────────────────────────────────────────────────┐ ║
|
||||
║ │ GameEnded │ ║
|
||||
║ └─────────────────────────────────────────────────────────────────────┘ ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 🌐 2. SÍŤOVÁ KOMUNIKACE ║
|
||||
║ ═══════════════════════ ║
|
||||
║ ║
|
||||
║ Komunikace probíhá přes TCP socket s AES-256 šifrováním. ║
|
||||
║ ║
|
||||
║ Handshake proces: ║
|
||||
║ 1. Klient posílá ClientHello s UUID a jménem ║
|
||||
║ 2. Server odpovídá ServerHello s RSA veřejným klíčem ║
|
||||
║ 3. Klient generuje AES klíč, zašifruje ho RSA a pošle KeyExchange ║
|
||||
║ 4. Server potvrdí KeyExchangeAck - od teď je vše šifrované AES ║
|
||||
║ ║
|
||||
║ Formát zpráv: ║
|
||||
║ ┌────────────┬──────────────────────────────────────────┐ ║
|
||||
║ │ 4 bajty │ N bajtů │ ║
|
||||
║ │ (délka) │ (JSON data, po handshake šifrovaná AES) │ ║
|
||||
║ └────────────┴──────────────────────────────────────────┘ ║
|
||||
║ ║
|
||||
║ Důležité typy zpráv: ║
|
||||
║ • CreateLobby/JoinLobby - vytvoření/připojení do lobby ║
|
||||
║ • StartGame - spuštění hry (pouze owner) ║
|
||||
║ • UpdatePosition - aktualizace pozice hráče ║
|
||||
║ • KillAttempt - pokus o zabití (pouze impostor) ║
|
||||
║ • ReportBody/CallEmergencyMeeting - svolání schůze ║
|
||||
║ • CastVote - hlasování ║
|
||||
║ • CompleteTask - dokončení úkolu (server validuje pozici) ║
|
||||
║ • StartSabotage - spuštění sabotáže (pouze impostor) ║
|
||||
║ • ActivateRepairStation - oprava sabotáže ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 🎯 3. HERNÍ LOGIKA ║
|
||||
║ ═════════════════ ║
|
||||
║ ║
|
||||
║ Role hráčů: ║
|
||||
║ • Crew (posádka) - plní úkoly, hlasuje, reportuje těla ║
|
||||
║ • Impostor - zabíjí, sabotuje, předstírá plnění úkolů ║
|
||||
║ ║
|
||||
║ Herní fáze (GamePhase): ║
|
||||
║ • Lobby - čekání na hráče, nastavení hry ║
|
||||
║ • Loading - načítání mapových dat z Overpass API ║
|
||||
║ • Playing - hlavní herní fáze ║
|
||||
║ • Meeting - diskuze před hlasováním ║
|
||||
║ • Voting - hlasování o vyloučení ║
|
||||
║ • Ended - konec hry ║
|
||||
║ ║
|
||||
║ Typy úkolů: ║
|
||||
║ • Všechny úkoly jsou INSTANT - stačí přijít na místo a stisknout USE ║
|
||||
║ • Server validuje pozici hráče (musí být do 5m od úkolu) ║
|
||||
║ • Duchové (mrtví crew) mohou také plnit úkoly ║
|
||||
║ ║
|
||||
║ Sabotáže (SabotageType): ║
|
||||
║ • CommsBlackout - blokuje reporty a emergency meetings, 1 opravná stanice ║
|
||||
║ • CriticalMeltdown - časový limit, 2 stanice musí opravovat současně ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 🖥️ 4. UŽIVATELSKÉ ROZHRANÍ ║
|
||||
║ ═══════════════════════════ ║
|
||||
║ ║
|
||||
║ UI používá Unity IMGUI (OnGUI) pro jednoduchost a přenositelnost. ║
|
||||
║ Pro produkční hru doporučujeme použít Unity UI (Canvas) nebo UI Toolkit. ║
|
||||
║ ║
|
||||
║ Škálování UI: ║
|
||||
║ • Používáme relativní jednotky (procenta obrazovky) ║
|
||||
║ • GUI.matrix pro globální škálování ║
|
||||
║ • Responzivní layout pomocí GUILayout ║
|
||||
║ ║
|
||||
║ Hlavní obrazovky: ║
|
||||
║ • MainMenu - připojení, vytvoření lobby, statistiky ║
|
||||
║ • Lobby - seznam hráčů, nastavení, chat ║
|
||||
║ • HUD - role, úkoly, minimap, sabotáže ║
|
||||
║ • Meeting - hlasovací panel, timer ║
|
||||
║ • GameEnd - výsledky, statistiky ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 🗺️ 5. VYKRESLOVÁNÍ MAPY ║
|
||||
║ ═══════════════════════ ║
|
||||
║ ║
|
||||
║ Mapa se vykresluje pomocí 3D GameObjects v prostoru Unity: ║
|
||||
║ ║
|
||||
║ Převod GPS → Unity souřadnice: ║
|
||||
║ • Střed mapy (playAreaCenter) = Vector3(0, 0, 0) ║
|
||||
║ • 1 metr reálně = 1 Unity jednotka ║
|
||||
║ • Latitude → Z osa, Longitude → X osa ║
|
||||
║ ║
|
||||
║ Vrstvy mapy (od spodu): ║
|
||||
║ 1. Podklad (zelená plocha) - Y = 0 ║
|
||||
║ 2. Oblasti (parky, voda) - Y = 0.01 ║
|
||||
║ 3. Cesty - Y = 0.02 ║
|
||||
║ 4. Budovy - Y = 0 až výška budovy ║
|
||||
║ 5. POI markery - Y = 0.5 ║
|
||||
║ 6. Hráči - Y = 1 ║
|
||||
║ 7. Markery (úkoly, těla) - Y = 0.3 ║
|
||||
║ ║
|
||||
║ Dynamické objekty: ║
|
||||
║ • Hráči - capsule s barvou podle stavu ║
|
||||
║ • Těla - ležící kapsle ║
|
||||
║ • Úkoly - žluté diamanty ║
|
||||
║ • Opravné stanice - červené/zelené krychle ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 📊 6. STATISTIKY HRÁČŮ ║
|
||||
║ ═══════════════════════ ║
|
||||
║ ║
|
||||
║ Server poskytuje HTTP REST API na portu 8088: ║
|
||||
║ ║
|
||||
║ GET /stats/{playerId} - statistiky konkrétního hráče ║
|
||||
║ GET /leaderboard - žebříček hráčů ║
|
||||
║ GET /health - stav serveru ║
|
||||
║ ║
|
||||
║ Statistiky zahrnují: ║
|
||||
║ • Počet her, výher, proher ║
|
||||
║ • Zabití, smrti, K/D ratio ║
|
||||
║ • Dokončené úkoly ║
|
||||
║ • Win rate jako impostor/crew ║
|
||||
║ • Přesnost hlasování ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 🚀 JAK ZAČÍT: ║
|
||||
║ ═════════════ ║
|
||||
║ ║
|
||||
║ 1. Přidejte VŠECHNY soubory UnityTestClient_*.cs do Unity projektu ║
|
||||
║ 2. Přidejte ClientSDK (Protocol.cs, Encryption.cs, EventDispatcher.cs, GameClient.cs) ║
|
||||
║ 3. Vytvořte prázdný GameObject a přidejte komponentu UnityTestClient ║
|
||||
║ 4. Nastavte v Inspectoru serverHost a serverPort ║
|
||||
║ 5. Spusťte server (dotnet run v Server/) ║
|
||||
║ 6. Spusťte hru v Unity ║
|
||||
║ ║
|
||||
║ Pro vlastní hru: ║
|
||||
║ • Nahraďte IMGUI za Unity UI Canvas ║
|
||||
║ • Přidejte vlastní 3D modely místo primitivních tvarů ║
|
||||
║ • Implementujte GPS pohyb místo WASD (Input.location) ║
|
||||
║ • Přidejte zvuky, particle efekty, animace ║
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ ⚠️ DŮLEŽITÉ POZNÁMKY: ║
|
||||
║ ═════════════════════ ║
|
||||
║ ║
|
||||
║ • GameClient.Update() MUSÍ být volán každý frame pro zpracování síťových událostí ║
|
||||
║ • Pozice hráče se odesílá automaticky každých 100ms ║
|
||||
║ • Server má anti-cheat - příliš rychlý pohyb způsobí varování/kick ║
|
||||
║ • Všechny herní akce (zabití, hlasování) validuje server ║
|
||||
║ • MapData může být null pokud Overpass API není dostupné ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GeoSus.Client;
|
||||
|
||||
/// <summary>
|
||||
/// Hlavní třída Unity testovacího klienta pro GeoSus.
|
||||
/// Tato partial třída obsahuje inicializaci, herní smyčku a správu stavů.
|
||||
///
|
||||
/// POUŽITÍ:
|
||||
/// 1. Přidejte tento skript na prázdný GameObject
|
||||
/// 2. Nastavte serverHost a serverPort v Inspectoru
|
||||
/// 3. Spusťte hru
|
||||
/// </summary>
|
||||
public partial class UnityTestClient : MonoBehaviour
|
||||
{
|
||||
#region ═══════════════════════════════════════════════════════════════════
|
||||
// KONFIGURACE SERVERU
|
||||
// ════════════════════════════════════════════════════════════════════════
|
||||
// Tyto hodnoty nastavte v Unity Inspectoru nebo zde přímo v kódu.
|
||||
// ServerHost je IP adresa nebo hostname serveru.
|
||||
// ServerPort je TCP port pro herní komunikaci (výchozí 7777).
|
||||
// HttpPort je port pro REST API statistik (výchozí 8088).
|
||||
#endregion
|
||||
|
||||
[Header("Nastavení serveru")]
|
||||
[Tooltip("IP adresa nebo hostname GeoSus serveru")]
|
||||
public string serverHost = "127.0.0.1";
|
||||
|
||||
[Tooltip("TCP port pro herní komunikaci")]
|
||||
public int serverPort = 7777;
|
||||
|
||||
[Tooltip("HTTP port pro statistiky API (ignorováno pokud useHttps=true)")]
|
||||
public int httpPort = 8088;
|
||||
|
||||
[Tooltip("Použít HTTPS pro Stats API (pro produkční server)")]
|
||||
public bool useHttps = false;
|
||||
|
||||
#region ═══════════════════════════════════════════════════════════════════
|
||||
// HERNÍ STAVY
|
||||
// ════════════════════════════════════════════════════════════════════════
|
||||
// AppState určuje, která obrazovka se zobrazuje a jaká logika běží.
|
||||
// Toto je KLIENTSKÝ stav, nezaměňovat s GamePhase ze serveru.
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Stav aplikace určující aktuální obrazovku.
|
||||
/// MainMenu -> Lobby -> Loading -> InGame -> GameEnded
|
||||
/// </summary>
|
||||
public enum AppState
|
||||
{
|
||||
/// <summary>Hlavní menu - připojení, vytvoření/vstup do lobby</summary>
|
||||
MainMenu,
|
||||
/// <summary>V lobby - čekání na hráče, nastavení hry</summary>
|
||||
Lobby,
|
||||
/// <summary>Načítání - stahování mapových dat</summary>
|
||||
Loading,
|
||||
/// <summary>Ve hře - hlavní gameplay</summary>
|
||||
InGame,
|
||||
/// <summary>Konec hry - zobrazení výsledků</summary>
|
||||
GameEnded
|
||||
}
|
||||
|
||||
#region ═══════════════════════════════════════════════════════════════════
|
||||
// HLAVNÍ PROMĚNNÉ
|
||||
// ════════════════════════════════════════════════════════════════════════
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Aktuální stav aplikace (která obrazovka je aktivní)
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
public AppState currentState = AppState.MainMenu;
|
||||
|
||||
/// <summary>
|
||||
/// Instance herního klienta z ClientSDK.
|
||||
/// Obsahuje veškerou síťovou logiku a herní data.
|
||||
/// </summary>
|
||||
protected GameClient client;
|
||||
|
||||
/// <summary>
|
||||
/// Unikátní ID tohoto klienta (generuje se při startu)
|
||||
/// </summary>
|
||||
protected string clientUuid;
|
||||
|
||||
/// <summary>
|
||||
/// Zobrazované jméno hráče
|
||||
/// </summary>
|
||||
protected string displayName = "Hráč";
|
||||
|
||||
/// <summary>
|
||||
/// Fronta notifikací k zobrazení na obrazovce
|
||||
/// </summary>
|
||||
protected Queue<NotificationData> notifications = new Queue<NotificationData>();
|
||||
|
||||
/// <summary>
|
||||
/// Aktuálně zobrazená notifikace (null = žádná)
|
||||
/// </summary>
|
||||
protected NotificationData currentNotification;
|
||||
|
||||
/// <summary>
|
||||
/// Čas konce zobrazení aktuální notifikace
|
||||
/// </summary>
|
||||
protected float notificationEndTime;
|
||||
|
||||
/// <summary>
|
||||
/// Chybová zpráva k zobrazení (null = žádná chyba)
|
||||
/// </summary>
|
||||
protected string errorMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Čas zmizení chybové zprávy
|
||||
/// </summary>
|
||||
protected float errorMessageEndTime;
|
||||
|
||||
/// <summary>
|
||||
/// Hlavní herní kamera
|
||||
/// </summary>
|
||||
protected Camera playerCamera;
|
||||
|
||||
/// <summary>
|
||||
/// Výška kamery nad mapou
|
||||
/// </summary>
|
||||
protected float cameraHeight = 100f;
|
||||
|
||||
#region ═══════════════════════════════════════════════════════════════════
|
||||
// DATOVÉ STRUKTURY
|
||||
// ════════════════════════════════════════════════════════════════════════
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Struktura pro notifikaci na obrazovce
|
||||
/// </summary>
|
||||
protected struct NotificationData
|
||||
{
|
||||
/// <summary>Text notifikace</summary>
|
||||
public string message;
|
||||
/// <summary>Barva pozadí</summary>
|
||||
public Color color;
|
||||
/// <summary>Doba zobrazení v sekundách</summary>
|
||||
public float duration;
|
||||
/// <summary>Ikona (emoji nebo text)</summary>
|
||||
public string icon;
|
||||
}
|
||||
|
||||
#region ═══════════════════════════════════════════════════════════════════
|
||||
// UNITY LIFECYCLE
|
||||
// ════════════════════════════════════════════════════════════════════════
|
||||
// Unity volá tyto metody automaticky:
|
||||
// Awake() - při vytvoření objektu (před Start)
|
||||
// Start() - před prvním Update
|
||||
// Update() - každý frame
|
||||
// OnDestroy() - při zničení objektu
|
||||
// OnGUI() - pro vykreslení IMGUI (může být vícekrát za frame)
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Inicializace při vytvoření objektu.
|
||||
/// Generujeme unikátní UUID pro tohoto klienta.
|
||||
/// </summary>
|
||||
void Awake()
|
||||
{
|
||||
// Generujeme unikátní ID klienta
|
||||
// V produkční hře byste toto ukládali do PlayerPrefs
|
||||
clientUuid = Guid.NewGuid().ToString("N").Substring(0, 8);
|
||||
|
||||
// Načteme uložené jméno hráče (pokud existuje)
|
||||
displayName = PlayerPrefs.GetString("PlayerName", "Hráč" + UnityEngine.Random.Range(1, 999));
|
||||
|
||||
Debug.Log($"[GeoSus] Klient inicializován s UUID: {clientUuid}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inicializace před prvním frame.
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
// Nastavení kamery pro top-down pohled
|
||||
SetupCamera();
|
||||
|
||||
Debug.Log("[GeoSus] Test klient připraven");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hlavní herní smyčka - volá se každý frame.
|
||||
/// DŮLEŽITÉ: Zde musíme volat client.Update() pro zpracování síťových událostí!
|
||||
/// </summary>
|
||||
void Update()
|
||||
{
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// KRITICKÉ: Zpracování síťových událostí
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// GameClient používá EventDispatcher pro thread-safe přenos událostí
|
||||
// ze síťového vlákna do hlavního Unity vlákna.
|
||||
// BEZ TOHOTO VOLÁNÍ nebudete dostávat žádné události ze serveru!
|
||||
if (client != null)
|
||||
{
|
||||
client.Update();
|
||||
}
|
||||
|
||||
// Zpracování vstupu podle aktuálního stavu
|
||||
switch (currentState)
|
||||
{
|
||||
case AppState.InGame:
|
||||
// Herní logika - pohyb, akce
|
||||
HandlePlayerInput();
|
||||
UpdateGameLogic();
|
||||
break;
|
||||
}
|
||||
|
||||
// Aktualizace notifikací
|
||||
UpdateNotifications();
|
||||
|
||||
// Aktualizace herních objektů na mapě
|
||||
if (currentState == AppState.InGame || currentState == AppState.Loading)
|
||||
{
|
||||
UpdateMapObjects();
|
||||
}
|
||||
|
||||
// Automatické obnovování statistik
|
||||
UpdateStatsAutoRefresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Úklid při zničení objektu.
|
||||
/// DŮLEŽITÉ: Vždy se odpojte od serveru při ukončení!
|
||||
/// </summary>
|
||||
void OnDestroy()
|
||||
{
|
||||
// Odpojení od serveru
|
||||
if (client != null)
|
||||
{
|
||||
client.Disconnect("Aplikace ukončena");
|
||||
client.Dispose();
|
||||
client = null;
|
||||
}
|
||||
|
||||
// Úklid mapových objektů
|
||||
CleanupMapObjects();
|
||||
|
||||
Debug.Log("[GeoSus] Klient ukončen");
|
||||
}
|
||||
|
||||
/// <summary>Příznak, zda jsou GUI styly inicializované</summary>
|
||||
private bool stylesInitialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Vykreslení IMGUI - volá se každý frame (může i vícekrát).
|
||||
/// Veškeré UI se vykresluje zde.
|
||||
/// </summary>
|
||||
void OnGUI()
|
||||
{
|
||||
// Inicializace stylů při prvním volání OnGUI
|
||||
if (!stylesInitialized)
|
||||
{
|
||||
InitializeUIStyles();
|
||||
stylesInitialized = true;
|
||||
}
|
||||
|
||||
// Aplikace škálování UI pro různé rozlišení
|
||||
ApplyUIScaling();
|
||||
|
||||
// Vykreslení UI podle aktuálního stavu
|
||||
switch (currentState)
|
||||
{
|
||||
case AppState.MainMenu:
|
||||
DrawMainMenu();
|
||||
break;
|
||||
case AppState.Lobby:
|
||||
DrawLobbyScreen();
|
||||
break;
|
||||
case AppState.Loading:
|
||||
DrawLoadingScreen();
|
||||
break;
|
||||
case AppState.InGame:
|
||||
DrawGameHUD();
|
||||
DrawMeetingPanel(); // Zobrazí se jen pokud je meeting aktivní
|
||||
break;
|
||||
case AppState.GameEnded:
|
||||
DrawGameEndScreen();
|
||||
break;
|
||||
}
|
||||
|
||||
// Overlay prvky (notifikace, chyby) - vždy navrchu
|
||||
DrawNotifications();
|
||||
DrawErrorMessage();
|
||||
|
||||
// Debug panel (pouze v editoru)
|
||||
#if UNITY_EDITOR
|
||||
DrawDebugPanel();
|
||||
#endif
|
||||
}
|
||||
|
||||
#region ═══════════════════════════════════════════════════════════════════
|
||||
// POMOCNÉ METODY
|
||||
// ════════════════════════════════════════════════════════════════════════
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Zobrazí notifikaci na obrazovce.
|
||||
/// Notifikace se řadí do fronty a zobrazují postupně.
|
||||
/// </summary>
|
||||
/// <param name="message">Text zprávy</param>
|
||||
/// <param name="color">Barva pozadí</param>
|
||||
/// <param name="icon">Ikona/emoji (volitelné)</param>
|
||||
protected void ShowNotification(string message, Color color, string icon)
|
||||
{
|
||||
ShowNotification(message, color, 3f, icon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zobrazí notifikaci na obrazovce.
|
||||
/// Notifikace se řadí do fronty a zobrazují postupně.
|
||||
/// </summary>
|
||||
/// <param name="message">Text zprávy</param>
|
||||
/// <param name="color">Barva pozadí</param>
|
||||
/// <param name="duration">Doba zobrazení v sekundách</param>
|
||||
/// <param name="icon">Ikona/emoji (volitelné)</param>
|
||||
protected void ShowNotification(string message, Color color, float duration = 3f, string icon = "")
|
||||
{
|
||||
notifications.Enqueue(new NotificationData
|
||||
{
|
||||
message = message,
|
||||
color = color,
|
||||
duration = duration,
|
||||
icon = icon
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aktualizace fronty notifikací
|
||||
/// </summary>
|
||||
private void UpdateNotifications()
|
||||
{
|
||||
// Pokud aktuální notifikace vypršela, zobrazíme další
|
||||
if (currentNotification.message != null && Time.time > notificationEndTime)
|
||||
{
|
||||
currentNotification = default;
|
||||
}
|
||||
|
||||
// Pokud není žádná notifikace a fronta není prázdná, zobrazíme další
|
||||
if (currentNotification.message == null && notifications.Count > 0)
|
||||
{
|
||||
currentNotification = notifications.Dequeue();
|
||||
notificationEndTime = Time.time + currentNotification.duration;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zobrazí chybovou zprávu
|
||||
/// </summary>
|
||||
/// <param name="message">Text chyby</param>
|
||||
/// <param name="duration">Doba zobrazení</param>
|
||||
protected void ShowError(string message, float duration = 5f)
|
||||
{
|
||||
errorMessage = message;
|
||||
errorMessageEndTime = Time.time + duration;
|
||||
Debug.LogError($"[GeoSus] {message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nastavení kamery pro top-down pohled
|
||||
/// </summary>
|
||||
private void SetupCamera()
|
||||
{
|
||||
// Najdeme nebo vytvoříme hlavní kameru
|
||||
playerCamera = Camera.main;
|
||||
if (playerCamera == null)
|
||||
{
|
||||
GameObject camObj = new GameObject("MainCamera");
|
||||
playerCamera = camObj.AddComponent<Camera>();
|
||||
camObj.tag = "MainCamera";
|
||||
}
|
||||
|
||||
// Nastavení pro top-down pohled
|
||||
playerCamera.orthographic = true;
|
||||
playerCamera.orthographicSize = 50f; // Výchozí zoom (50 metrů od středu)
|
||||
playerCamera.transform.position = new Vector3(0, cameraHeight, 0);
|
||||
playerCamera.transform.rotation = Quaternion.Euler(90, 0, 0);
|
||||
playerCamera.backgroundColor = new Color(0.2f, 0.3f, 0.2f); // Tmavě zelená
|
||||
playerCamera.clearFlags = CameraClearFlags.SolidColor;
|
||||
|
||||
// Přidáme naši komponentu pro ovládání kamery
|
||||
if (playerCamera.GetComponent<CameraController>() == null)
|
||||
{
|
||||
playerCamera.gameObject.AddComponent<CameraController>();
|
||||
}
|
||||
}
|
||||
|
||||
#region ═══════════════════════════════════════════════════════════════════
|
||||
// DEBUG PANEL
|
||||
// ════════════════════════════════════════════════════════════════════════
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Debug panel - zobrazuje interní stav klienta
|
||||
/// Pouze v Unity Editoru
|
||||
/// </summary>
|
||||
private void DrawDebugPanel()
|
||||
{
|
||||
GUILayout.BeginArea(new Rect(10, Screen.height - 150, 300, 140));
|
||||
GUI.Box(new Rect(0, 0, 300, 140), "");
|
||||
|
||||
GUILayout.Label($"<color=yellow><b>DEBUG</b></color>", richTextStyle);
|
||||
GUILayout.Label($"State: {currentState}");
|
||||
GUILayout.Label($"Connected: {client?.IsConnected ?? false}");
|
||||
GUILayout.Label($"LobbyId: {client?.LobbyId ?? "null"}");
|
||||
GUILayout.Label($"Phase: {client?.CurrentLobbyState?.Phase.ToString() ?? "null"}");
|
||||
GUILayout.Label($"Role: {client?.MyRole?.ToString() ?? "null"}");
|
||||
GUILayout.Label($"Ping: {client?.Ping ?? 0}ms");
|
||||
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Jednoduchý kontroler kamery pro top-down pohled.
|
||||
/// Umožňuje pohyb pomocí WASD/šipek a zoom pomocí kolečka myši.
|
||||
///
|
||||
/// POZNÁMKA: V produkční hře byste toto pravděpodobně spojili
|
||||
/// s pohybem hráče - kamera sleduje hráče.
|
||||
/// </summary>
|
||||
public class CameraController : MonoBehaviour
|
||||
{
|
||||
[Header("Nastavení kamery")]
|
||||
[Tooltip("Rychlost pohybu kamery")]
|
||||
public float moveSpeed = 50f;
|
||||
|
||||
[Tooltip("Rychlost zoomu")]
|
||||
public float zoomSpeed = 10f;
|
||||
|
||||
[Tooltip("Minimální zoom (orthographic size)")]
|
||||
public float minZoom = 10f;
|
||||
|
||||
[Tooltip("Maximální zoom (orthographic size)")]
|
||||
public float maxZoom = 200f;
|
||||
|
||||
private Camera cam;
|
||||
|
||||
void Start()
|
||||
{
|
||||
cam = GetComponent<Camera>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Pohyb kamery - WASD nebo šipky
|
||||
// POZNÁMKA: V plné hře se kamera obvykle pohybuje s hráčem
|
||||
float h = Input.GetAxis("Horizontal");
|
||||
float v = Input.GetAxis("Vertical");
|
||||
|
||||
Vector3 movement = new Vector3(h, 0, v) * moveSpeed * Time.deltaTime;
|
||||
transform.position += movement;
|
||||
|
||||
// Zoom - kolečko myši
|
||||
float scroll = Input.GetAxis("Mouse ScrollWheel");
|
||||
if (scroll != 0 && cam.orthographic)
|
||||
{
|
||||
cam.orthographicSize = Mathf.Clamp(
|
||||
cam.orthographicSize - scroll * zoomSpeed,
|
||||
minZoom,
|
||||
maxZoom
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user