diff --git a/app.js b/app.js index 9d8fc7e..a419abf 100644 --- a/app.js +++ b/app.js @@ -349,6 +349,40 @@ io.on("connection", (socket) => { } }); + /* ── 1v1: Bereit-System ── */ + if (!io._arenaReady) io._arenaReady = new Map(); // matchId → Set of ready slots + + socket.on("player_ready", (data) => { + const { matchId, slot } = data; + if (!matchId || !slot) return; + + if (!io._arenaReady.has(matchId)) { + io._arenaReady.set(matchId, new Set()); + } + + const readySet = io._arenaReady.get(matchId); + readySet.add(slot); + + // Beide Spieler in der Arena-Room benachrichtigen + io.to("arena_" + matchId).emit("ready_status", { + readyCount: readySet.size, + }); + + console.log(`[1v1] ${slot} ist bereit in Match ${matchId} (${readySet.size}/2)`); + + // Aufräumen wenn beide bereit + if (readySet.size >= 2) { + io._arenaReady.delete(matchId); + } + }); + + socket.on("player_surrender", (data) => { + const { matchId, slot } = data; + console.log(`[1v1] ${slot} hat aufgegeben in Match ${matchId}`); + // Aufgabe-Logik kommt hier rein + io.to("arena_" + matchId).emit("player_surrendered", { slot }); + }); + /* ── 1v1: Spielfeld-Verbindung (beide Spieler im iframe) ── */ // Map: matchId → { player1: socketId, player2: socketId, names: {} } if (!io._arenaRooms) io._arenaRooms = new Map(); diff --git a/public/css/1v1.css b/public/css/1v1.css index dd86183..ba5355f 100644 --- a/public/css/1v1.css +++ b/public/css/1v1.css @@ -474,3 +474,122 @@ body { border-color: rgba(255, 215, 80, 0.8); transform: scale(1.1); } + +/* ── Verbindungs-Overlay ── */ +#connecting-overlay { + position: fixed; + inset: 0; + z-index: 200; + background: rgba(0,0,0,0.85); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-family: "Cinzel", serif; + color: rgba(255,215,80,0.85); + font-size: 18px; + letter-spacing: 3px; +} +#connecting-overlay p { + margin-top: 12px; + font-size: 12px; + color: rgba(255,255,255,0.4); + letter-spacing: 2px; +} +@keyframes spin { + to { transform: rotate(360deg); } +} +#connecting-overlay .spinner { + width: 40px; + height: 40px; + border: 3px solid rgba(255,215,80,0.2); + border-top-color: #ffd750; + border-radius: 50%; + animation: spin 0.8s linear infinite; + margin-bottom: 16px; +} + +/* ── Avatar Name (immer sichtbar) ── */ +.av-name { + position: absolute; + bottom: 8px; + left: 0; + right: 0; + text-align: center; + font-family: "Cinzel", serif; + font-size: 13px; + font-weight: 700; + color: #ffd750; + text-shadow: 0 1px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.7); + letter-spacing: 1px; + pointer-events: none; + z-index: 10; + padding: 0 4px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* ── Top Bar Actions (Buttons-Gruppe) ── */ +.top-bar-actions { + display: flex; + align-items: center; + gap: calc(var(--s) * 10); +} + +/* BEREIT Button */ +.bereit-btn { + background: linear-gradient(135deg, #1a7a1a, #27ae60); + border: 2px solid rgba(100, 255, 100, 0.5); + border-radius: calc(var(--s) * 8); + color: #fff; + font-family: "Cinzel", serif; + font-size: calc(var(--s) * 12); + letter-spacing: calc(var(--s) * 2); + padding: calc(var(--s) * 7) calc(var(--s) * 20); + cursor: pointer; + text-transform: uppercase; + box-shadow: 0 0 calc(var(--s) * 14) rgba(0, 200, 0, 0.4); + transition: all 0.2s; +} +.bereit-btn:hover:not(:disabled) { + background: linear-gradient(135deg, #22992a, #2ecc71); + box-shadow: 0 0 calc(var(--s) * 24) rgba(0, 200, 0, 0.7); +} +.bereit-btn.bereit-clicked { + background: linear-gradient(135deg, #145214, #1e8449); + border-color: rgba(100, 255, 100, 0.3); + opacity: 0.75; + cursor: default; +} + +/* AUFGEBEN Button */ +.aufgeben-btn { + background: linear-gradient(135deg, #2c2c2c, #444); + border: 2px solid rgba(255, 255, 255, 0.35); + border-radius: calc(var(--s) * 8); + color: #fff; + font-family: "Cinzel", serif; + font-size: calc(var(--s) * 12); + letter-spacing: calc(var(--s) * 2); + padding: calc(var(--s) * 7) calc(var(--s) * 20); + cursor: pointer; + text-transform: uppercase; + box-shadow: 0 0 calc(var(--s) * 8) rgba(0, 0, 0, 0.5); + transition: all 0.2s; +} +.aufgeben-btn:hover { + background: linear-gradient(135deg, #3a3a3a, #555); + border-color: rgba(255, 255, 255, 0.7); + box-shadow: 0 0 calc(var(--s) * 16) rgba(255, 255, 255, 0.2); +} + +/* Spielfeld-Sperre */ +#board-lock-overlay { + position: absolute; + inset: 0; + z-index: 50; + background: rgba(0, 0, 0, 0.55); + backdrop-filter: blur(2px); + cursor: not-allowed; +} diff --git a/views/1v1_spielfeld.ejs b/views/1v1_spielfeld.ejs index 6cc2497..fcac459 100644 --- a/views/1v1_spielfeld.ejs +++ b/views/1v1_spielfeld.ejs @@ -11,107 +11,10 @@ /> - -
- - -