From ddbd937a0a0796562a450d8c0a5f6fb933e4cdd2 Mon Sep 17 00:00:00 2001 From: giteaadmin Date: Mon, 4 May 2026 08:47:32 +0000 Subject: [PATCH] minigame 1 add more design 1.3 --- www/html/Game/public/img/QUESTION/README.txt | 8 +- www/html/Game/public/js/play.js | 116 ++++++++++--------- www/html/Game/public/js/version.js | 2 +- www/html/Game/public/play.html | 112 +++++++++++++++++- 4 files changed, 177 insertions(+), 61 deletions(-) diff --git a/www/html/Game/public/img/QUESTION/README.txt b/www/html/Game/public/img/QUESTION/README.txt index 5d41ba8..ffff77a 100644 --- a/www/html/Game/public/img/QUESTION/README.txt +++ b/www/html/Game/public/img/QUESTION/README.txt @@ -6,8 +6,10 @@ QUESTION — รูปสำหรับฉาก / อัปโหลด - **popup-Howto.png** — พื้นหลังหน้า HOWTO / คำแนะนำก่อนเริ่ม - **popup-result.png** — พื้นหลังแผงสรุปคะแนนท้ายเกม - - **hud-time-plaque.png** — (ทางเลือก) แผ่นตกแต่งด้านหลังตัวเลข **TIME** บน Cyber HUD กลางจอ ระหว่างเล่น - - **hud-question-plaque.png** — (ทางเลือก) แผ่นพื้นหลังข้อความคำถามใต้ TIME ตาม mock + - **time.png** — แผ่นตกแต่งกล่อง **TIME** กลางจอ Cyber HUD ระหว่างเล่น (แมป mng8a80o) + - **score-bar.png** — แผ่นตกแต่งแถบ **SCORE** ด้านซ้าย Cyber HUD (แมป mng8a80o) + - **hud-time-plaque.png** — (เก่า / ทางเลือก) ถ้าไม่มี **time.png** โค้ดจะไม่ใช้ไฟล์นี้อีกต่อไปสำหรับ HUD หลัก — ใช้ **time.png** แทน + - **hud-question-plaque.png** — (ไม่บังคับ / ไม่โหลดอัตโนมัติในเกม) ถ้าต้องการใช้รูป plaque ให้อัปโหลดไฟล์นี้แล้วผูกเองใน CSS หรือขยายโค้ด — ค่าเริ่มต้นใช้กรอบจากคลาส `quiz-map-question-panel--question-mission-live` แทน - **score+.png** — เอฟเฟกต์ “+10” กลางโซนคำตอบที่ถูก (SAFE หรือ SCAM) เมื่อมีผู้เล่นตอบถูก · คะแนนต่อข้อ = 10 แต้ม (สอดคล้อง `QUIZ_TF_POINTS_PER_CORRECT` บนเซิร์ฟเวอร์) - **result-Lose_stamp.png** — แสตมป์ทับอวาตาร์ในหน้าสรุปภารกิจ (ฉาก quiz แบบ mission) สำหรับผู้เล่นที่เคยตอบผิดในรอบนั้น · ถ้าไฟล์หายระบบ fallback ไป `/Game/img/gauntlet-assets/result-Lose_stamp.png` - **admin-tab-minigame-1.png** — ไอคอนแท็บ Admin «Minigame-1-จริงหรือไม่» (เครื่องหมายถูก neon เขียวบนพื้นดำ) @@ -15,7 +17,7 @@ QUESTION — รูปสำหรับฉาก / อัปโหลด ถ้าไฟล์หาย ระบบ fallback ไป `/Game/img/gauntlet-assets/` ชื่อเดียวกัน (เฉพาะ popup-*) · แผ่น HUD ถ้าไม่มีไฟล์จะใช้ข้อความล้วน -English: Map **mng8a80o** uses mission UI; place **popup-Howto.png** and **popup-result.png** here. Optional HUD plates: **hud-time-plaque.png**, **hud-question-plaque.png**. For correct-answer FX: **score+.png** (+10 popup over the correct zone). For mission summary wrong-answer stamp on avatars: **result-Lose_stamp.png** (falls back to gauntlet-assets if missing). Admin True/False tab icon: **admin-tab-minigame-1.png**. +English: Map **mng8a80o** uses mission UI; place **popup-Howto.png** and **popup-result.png** here. Cyber HUD plates: **time.png** (center timer), **score-bar.png** (left scoreboard). **hud-question-plaque.png** is not fetched by the client anymore (avoids 404); default question frame uses CSS class `quiz-map-question-panel--question-mission-live` unless you wire a custom image yourself. For correct-answer FX: **score+.png** (+10 popup over the correct zone). For mission summary wrong-answer stamp on avatars: **result-Lose_stamp.png** (falls back to gauntlet-assets if missing). Admin True/False tab icon: **admin-tab-minigame-1.png**. โฟลเดอร์นี้ถูกสร้างจาก repo + สคริปต์ deploy เพื่อหลีกเลี่ยงข้อผิดพลาด FTP: diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index 3d3e327..f9336d5 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -1570,6 +1570,10 @@ if (isQuizCarry() && useCyberPlayHud()) { wrap.classList.add('is-hidden'); } + /* แมป mng8a80o: คะแนนอยู่ที่ cyber SCORE ซ้ายแล้ว — ซ่อนกล่อง "คะแนน" มุมขวาไม่ให้ซ้ำกับ mock */ + if (isQuizQuestionMissionUiMapPlay()) { + wrap.classList.add('is-hidden'); + } } function initPlayLiveQuizScoresZeros() { @@ -1692,6 +1696,11 @@ function clearQuizMapPanelThemeInline(panel, textEl) { if (!panel || !textEl) return; + panel.classList.remove('quiz-map-question-panel--question-mission-live'); + panel.style.removeProperty('background-image'); + panel.style.removeProperty('background-size'); + panel.style.removeProperty('background-position'); + delete panel.dataset.qmPlaqueTry; panel.style.removeProperty('--qmap-bg'); panel.style.removeProperty('--qmap-border'); panel.style.removeProperty('--qmap-border-w'); @@ -2324,29 +2333,17 @@ const startFontPx = quizMapQuestionFontPxLikeCarryPlaques(thFont, zoom); const mnFont = Math.max(8, Math.round(Number(thFont.questionFontMinPx) || 10)); fitQuizMapQuestionFontToPanel(panel, textEl, startFontPx, mnFont); + /* ไม่โหลด hud-question-plaque.png อัตโนมัติ — บนเซิร์ฟมักไม่มีไฟล์ → 404 ใน Network; ใช้คลาส + CSS แทน (อัปโหลด PNG แล้วค่อยผูกทีหลังได้) */ if (isQuiz() && isQuizQuestionMissionUiMapPlay() && quizQuestionMissionPhase === 'live') { - const pqUrl = questionMissionHudAssetUrl('hud-question-plaque.png'); - if (panel.dataset.qmPlaqueTry !== pqUrl) { - panel.dataset.qmPlaqueTry = pqUrl; - const im = new Image(); - im.onload = function () { - panel.style.setProperty('background-image', 'linear-gradient(180deg, rgba(8,10,22,0.25), rgba(8,10,22,0.45)), url(' + pqUrl + ')', 'important'); - panel.style.setProperty('background-size', 'cover, cover', 'important'); - panel.style.setProperty('background-position', 'center, center', 'important'); - }; - im.onerror = function () { - panel.style.removeProperty('background-image'); - panel.style.removeProperty('background-size'); - panel.style.removeProperty('background-position'); - delete panel.dataset.qmPlaqueTry; - }; - im.src = pqUrl; + panel.classList.add('quiz-map-question-panel--question-mission-live'); + } else { + panel.classList.remove('quiz-map-question-panel--question-mission-live'); + if (panel.dataset.qmPlaqueTry) { + panel.style.removeProperty('background-image'); + panel.style.removeProperty('background-size'); + panel.style.removeProperty('background-position'); + delete panel.dataset.qmPlaqueTry; } - } else if (panel.dataset.qmPlaqueTry) { - panel.style.removeProperty('background-image'); - panel.style.removeProperty('background-size'); - panel.style.removeProperty('background-position'); - delete panel.dataset.qmPlaqueTry; } } @@ -13329,7 +13326,7 @@ } } if (tb) { - const tUrl = questionMissionHudAssetUrl('hud-time-plaque.png'); + const tUrl = questionMissionHudAssetUrl('time.png'); if (on) { if (tb.dataset.qmTimeSrc !== tUrl) { tb.dataset.qmTimeSrc = tUrl; @@ -13369,11 +13366,13 @@ if (root) { root.classList.toggle('is-hidden', !on); root.setAttribute('aria-hidden', on ? 'false' : 'true'); + if (!on) root.classList.remove('play-cyber-hud--question-mission'); } if (stackEl) stackEl.classList.toggle('play-cyber-vignette', !!on); const gw = document.querySelector('.game-wrap'); if (gw) gw.classList.toggle('play-cyber-active', !!on); if (!on || !root) return; + root.classList.toggle('play-cyber-hud--question-mission', !!isQuizQuestionMissionHudActivePlay()); const timeLabelEl = root.querySelector('.play-cyber-time-label'); if (timeLabelEl) timeLabelEl.style.display = isQuizCarry() ? 'none' : ''; const timeVal = document.getElementById('play-cyber-time-val'); @@ -13652,7 +13651,8 @@ for (let r = 0; r < Math.min(cap, rows.length); r++) { const row = rows[r]; const li = document.createElement('li'); - li.className = 'play-cyber-score-row' + (row.isMe ? ' is-me' : '') + (row.eliminated ? ' is-out' : ''); + li.className = 'play-cyber-score-row' + (row.isMe ? ' is-me' : '') + (row.eliminated ? ' is-out' : '') + + (quizMissionHud ? ' play-cyber-score-row--scores-only' : ''); const av = document.createElement('img'); av.className = 'play-cyber-score-av'; av.alt = ''; @@ -13663,32 +13663,6 @@ const im = getCharacterImg(cid, 'down'); if (im && im.src) av.src = im.src; } - const mid = document.createElement('div'); - mid.className = 'play-cyber-score-mid'; - const name = document.createElement('span'); - name.className = 'play-cyber-score-name'; - if (row.id === leaderId && leaderId != null) { - const crown = document.createElement('span'); - crown.className = 'play-cyber-lead-crown'; - crown.textContent = '♔'; - crown.title = 'Leader'; - name.appendChild(crown); - } - name.appendChild(document.createTextNode(String(row.nickname || '').slice(0, 14))); - const st = document.createElement('span'); - st.className = 'play-cyber-score-state'; - st.textContent = (isQuizCarry() || quizMissionHud) - ? '' - : (row.eliminated - ? (isBalloonBoss() ? 'OUT' : (isGauntletCrownHeistMapPlay() ? 'เสียชีวิต' : 'OFFLINE')) - : (isBalloonBoss() - ? ('♥' + Math.max(0, row.isMe ? (me.balloonBossBalloons | 0) : ((() => { - const ox = others.get(row.id); - return ox ? (ox.balloonBossBalloons | 0) : 0; - })()))) - : 'LINK_OK')); - mid.appendChild(name); - mid.appendChild(st); const sc = document.createElement('span'); sc.className = 'play-cyber-score-val'; if (isGauntlet() || isSpaceShooter() || isBalloonBoss() || isQuizCarry() || jumpMissionHud || quizMissionHud || stackMissionHud) { @@ -13696,9 +13670,47 @@ } else { sc.textContent = row.eliminated ? '—' : String(r + 1); } - li.appendChild(av); - li.appendChild(mid); - li.appendChild(sc); + if (quizMissionHud) { + if (row.id === leaderId && leaderId != null) { + const crown = document.createElement('span'); + crown.className = 'play-cyber-lead-crown'; + crown.textContent = '♔'; + crown.title = 'Leader'; + sc.insertBefore(crown, sc.firstChild); + } + li.appendChild(av); + li.appendChild(sc); + } else { + const mid = document.createElement('div'); + mid.className = 'play-cyber-score-mid'; + const name = document.createElement('span'); + name.className = 'play-cyber-score-name'; + if (row.id === leaderId && leaderId != null) { + const crown = document.createElement('span'); + crown.className = 'play-cyber-lead-crown'; + crown.textContent = '♔'; + crown.title = 'Leader'; + name.appendChild(crown); + } + name.appendChild(document.createTextNode(String(row.nickname || '').slice(0, 14))); + const st = document.createElement('span'); + st.className = 'play-cyber-score-state'; + st.textContent = (isQuizCarry() || quizMissionHud) + ? '' + : (row.eliminated + ? (isBalloonBoss() ? 'OUT' : (isGauntletCrownHeistMapPlay() ? 'เสียชีวิต' : 'OFFLINE')) + : (isBalloonBoss() + ? ('♥' + Math.max(0, row.isMe ? (me.balloonBossBalloons | 0) : ((() => { + const ox = others.get(row.id); + return ox ? (ox.balloonBossBalloons | 0) : 0; + })()))) + : 'LINK_OK')); + mid.appendChild(name); + mid.appendChild(st); + li.appendChild(av); + li.appendChild(mid); + li.appendChild(sc); + } ul.appendChild(li); } } diff --git a/www/html/Game/public/js/version.js b/www/html/Game/public/js/version.js index 5a29e61..16ac369 100644 --- a/www/html/Game/public/js/version.js +++ b/www/html/Game/public/js/version.js @@ -1,6 +1,6 @@ // ทุกครั้งที่มีการเพิ่มหรือเปลี่ยน ให้เพิ่ม v +0.0001 // หลังแก้ค่าแล้วต้อง copy ไป path ที่ Nginx ชี้ (หรือรัน copy-frogger-files-only.sh) ถึงจะเห็นบนเว็บ -window.APP_VERSION = '0.0195'; +window.APP_VERSION = '0.0203'; document.addEventListener('DOMContentLoaded', function () { var t = document.querySelector('.version-tag'); if (t) t.textContent = 'v ' + window.APP_VERSION; diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index 8e996f4..1cc7134 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -228,6 +228,18 @@ #quiz-map-question-panel.quiz-map-question-panel--true-false { justify-content: center; } + /* แมปภารกิจคำถาม (mng8a80o) ช่วงเล่น — กรอบแบบ mock โดยไม่ต้องมี hud-question-plaque.png */ + #quiz-map-question-panel.quiz-map-question-panel--question-mission-live { + background: + linear-gradient(180deg, rgba(14, 24, 44, 0.5), rgba(8, 12, 26, 0.82)), + linear-gradient(90deg, rgba(0, 255, 230, 0.07), transparent 38%, transparent 62%, rgba(255, 100, 70, 0.06)), + var(--qmap-bg, rgba(12, 14, 28, 0.92)); + border-color: rgba(255, 224, 130, 0.5); + box-shadow: + var(--qmap-shadow, 0 8px 28px rgba(0, 0, 0, 0.55)), + inset 0 0 0 1px rgba(0, 255, 240, 0.14), + 0 0 32px rgba(0, 200, 255, 0.1); + } #quiz-map-question-panel.is-hidden { display: none !important; } #quiz-map-question-panel::-webkit-scrollbar { display: none; @@ -1404,6 +1416,84 @@ font-family: 'Share Tech Mono', ui-monospace, monospace; } .play-cyber-hud.is-hidden { display: none !important; } + /* mng8a80o ช่วงเล่น — แผง SCORE / TIME ใช้รูปจาก /Game/img/QUESTION (อัปโหลด score-bar.png · time.png) */ + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-scoreboard { + width: min(118px, 35vw); + background: url(/Game/img/QUESTION/score-bar.png) left center / auto min(96%, 360px) no-repeat; + border: none; + box-shadow: none; + padding: clamp(1.85rem, 6.5vmin, 3.05rem) clamp(6px, 1.5vw, 11px) clamp(8px, 1.6vw, 12px) clamp(4px, 1vw, 8px); + min-height: min(46vh, 320px); + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-panel-title { + border-bottom: none; + margin-bottom: 0.15rem; + padding-bottom: 0; + color: #b8f6ff; + text-shadow: 0 0 10px rgba(0, 0, 0, 0.95), 0 0 18px rgba(0, 200, 255, 0.35); + display: none; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row { + border-bottom-color: rgba(0, 255, 240, 0.1); + } + /* คะแนนชิดรูป — ห้ามใช้ 1fr + justify-end (ดันตัวเลขไปขวาสุดของแผง) */ + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--scores-only { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 0.32rem; + width: auto; + max-width: 100%; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--scores-only .play-cyber-score-val { + justify-self: unset; + text-align: left; + min-width: unset; + flex: 0 0 auto; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-sub { + margin-top: 0.32rem; + opacity: 0.52; + font-size: 0.52rem; + max-width: min(88vw, 420px); + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-head { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: baseline; + justify-content: center; + column-gap: 0.08rem; + row-gap: 0.12rem; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-colon { + display: inline; + font-family: 'Orbitron', sans-serif; + font-size: clamp(0.88rem, 2.6vw, 1.15rem); + font-weight: 700; + color: rgba(232, 248, 255, 0.96); + text-shadow: 0 0 14px rgba(0, 255, 220, 0.42), 0 1px 10px rgba(0, 0, 0, 0.88); + margin: 0 0.1rem 0 0.06rem; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-label { + margin-bottom: 0; + font-size: clamp(0.88rem, 2.6vw, 1.12rem); + letter-spacing: 0.12em; + color: rgba(232, 248, 255, 0.96); + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-val { + filter: drop-shadow(0 2px 10px rgba(0, 0, 0, 0.85)); + color: #7af8ff; + text-shadow: + 0 0 18px rgba(122, 248, 255, 0.55), + 0 0 36px rgba(0, 200, 255, 0.28), + 0 2px 12px rgba(0, 0, 0, 0.9); + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-label, + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-sub { + text-shadow: 0 1px 8px rgba(0, 0, 0, 0.9), 0 0 12px rgba(0, 0, 0, 0.65); + } .game-wrap.play-cyber-active .game-header { background: linear-gradient(180deg, rgba(6, 10, 22, 0.94), rgba(12, 18, 36, 0.88)); border-bottom: 1px solid rgba(0, 255, 240, 0.22); @@ -1535,6 +1625,15 @@ text-align: center; min-width: 120px; } + .play-cyber-time-head { + display: flex; + flex-direction: column; + align-items: center; + } + .play-cyber-time-colon { + display: none; + line-height: 1; + } .play-cyber-quiz-mission-q-band { position: relative; width: min(92vw, 680px); @@ -1884,14 +1983,17 @@