update design game1

This commit is contained in:
2026-05-29 11:07:58 +00:00
parent 9c77c8405d
commit fefdee0cee
56 changed files with 3009 additions and 98 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+445 -83
View File
@@ -7047,6 +7047,18 @@
}
function applyQuizQuestionMissionPanelImages() {
/* ติดคลาส scope ให้ overlay howto (popup HOW TO PLAY) ใช้สไตล์ mockup เฉพาะ mng8a80o */
const howtoOv = document.getElementById('gauntlet-crown-howto-overlay');
if (howtoOv) {
const tfHowto = isQuizQuestionMissionUiMapPlay();
howtoOv.classList.toggle('gch-quiz-tf-mock', tfHowto);
if (tfHowto) {
ensureQuizTfScaleResizeListener();
updateGchTfMockScale(howtoOv);
} else {
howtoOv.style.removeProperty('--gch-tf-scale');
}
}
const howtoBg = document.querySelector('#gauntlet-crown-howto-overlay .gch-bg');
if (howtoBg) {
howtoBg.src = questionMissionAssetUrl('popup-Howto.png');
@@ -11252,6 +11264,34 @@
disp = balloonBossMergePreviewBotsMission(disp) || disp;
}
if (!disp || !Array.isArray(disp.ranked)) return;
/* mng8a80o เท่านั้น — สรุปผลภารกิจตาม mockup Minigame-1 (06-summary) */
const tfMockSummary = mission.uiSkin === 'question_mission' && isQuizQuestionMissionUiMapPlay();
ov.classList.toggle('gcm-quiz-tf-mock', tfMockSummary);
/* mng8a80o: ใช้ popup-result.png ของ QUESTION (เหมือน mockup) — แมปอื่นคง popup ของ gauntlet */
const gcmBgImg = ov.querySelector('.gcm-bg');
if (gcmBgImg) {
const gcmBgSrc = tfMockSummary
? questionMissionAssetUrl('popup-result.png')
: (BASE + '/img/gauntlet-assets/popup-result.png');
if (gcmBgImg.getAttribute('src') !== gcmBgSrc) gcmBgImg.setAttribute('src', gcmBgSrc);
}
if (tfMockSummary) {
ensureMePlayTintFromLobbyStorage();
ensureQuizTfScaleResizeListener();
updateGcmTfMockScale(ov);
/* preload tint ทุกคนก่อนวาด avatar — กันรูปว่าง/สีเดียว */
disp.ranked.forEach(function (r) {
const cid = resolveRankedCharacterIdPlay(r);
if (!cid) return;
preloadPlayTintForAvatar(cid, resolveCyberHudAvatarTintPlay({
id: r.id,
characterId: cid,
isMe: myId != null && r.id != null && String(r.id) === String(myId),
}));
});
} else {
ov.style.removeProperty('--gcm-tf-scale');
}
rowEl.innerHTML = '';
disp.ranked.forEach((r) => {
const cell = document.createElement('div');
@@ -11259,7 +11299,17 @@
const tag = document.createElement('div');
tag.className = 'gcm-rank-tag';
const rk = Math.floor(Number(r.rank)) || 0;
if (rk >= 1 && rk <= 3) {
if (tfMockSummary) {
/* mockup: ทุกอันดับเป็นภาพ (result-1st/2nd/3rd, txt-1=4, txt-2=5+) */
const badge = rk === 1 ? 'result-1st.png' : rk === 2 ? 'result-2nd.png'
: rk === 3 ? 'result-3rd.png' : rk === 4 ? 'result-txt-1.png' : 'result-txt-2.png';
const tagImg = document.createElement('img');
tagImg.src = questionMissionAssetUrl(badge);
tagImg.alt = '[' + String(r.rankLabel || rk) + ']';
tagImg.style.maxWidth = '100%';
tagImg.style.height = 'auto';
tag.appendChild(tagImg);
} else if (rk >= 1 && rk <= 3) {
const tagImg = document.createElement('img');
tagImg.src = gcmRankBadgeUrl(rk);
tagImg.alt = '[' + String(r.rankLabel || rk) + ']';
@@ -11274,22 +11324,43 @@
const img = document.createElement('img');
img.className = 'gcm-av';
img.alt = '';
const cid = r.characterId ? String(r.characterId) : '';
if (cid) {
setCyberHudScoreAvatarImg(img, {
const cid = resolveRankedCharacterIdPlay(r);
const avRow = {
id: r.id,
characterId: cid,
isMe: myId != null && r.id != null && String(r.id) === String(myId),
playTint: resolveCyberHudAvatarTintPlay({
id: r.id,
characterId: cid,
isMe: myId != null && r.id != null && String(r.id) === String(myId),
});
}),
};
if (cid) {
applyCyberHudScoreAvatarImgWithRetry(img, avRow, 0);
} else {
img.src = defaultAvatarImg.src;
}
img.onerror = function () {
this.onerror = null;
this.src = defaultAvatarImg.src;
applyCyberHudScoreAvatarImgWithRetry(this, avRow, 3);
};
frame.appendChild(img);
if (tfMockSummary) {
/* mng8a80o: portrait อยู่ใต้ player-frame.png (mockup .portrait + .frame z-index 3) */
const avClip = document.createElement('div');
avClip.className = 'gcm-av-clip';
avClip.appendChild(img);
frame.appendChild(avClip);
const frameImg = document.createElement('img');
frameImg.className = 'gcm-frame-img';
frameImg.src = questionMissionAssetUrl('player-frame.png');
frameImg.alt = '';
frameImg.decoding = 'async';
frame.appendChild(frameImg);
} else {
frame.appendChild(img);
}
const qMissionLose = mission && mission.uiSkin === 'question_mission' && r.hadQuizWrong;
if (tfMockSummary && (r.eliminated || qMissionLose)) cell.classList.add('gcm-cell--out');
if (r.eliminated || qMissionLose) {
const st = document.createElement('img');
st.className = 'gcm-stamp';
@@ -11347,8 +11418,12 @@
const pc = Math.max(0, Math.floor(Number(disp.participantCount) || 0));
totalEl.innerHTML = 'คะแนนรวม <span class="gcm-total-nums">(' + parts.join('+') + ') = ' + sum + '</span> · รอดชีวิต ' + sc + '/' + pc + ' → เกรด';
} else if (questionMissionSkin) {
const pc = Math.max(0, Math.floor(Number(disp.participantCount) || 0));
totalEl.innerHTML = 'คะแนนตอบคำถาม <span class="gcm-total-nums">(' + parts.join('+') + ') = ' + sum + '</span> · ผู้เล่น ' + pc + ' → เกรด';
if (tfMockSummary) {
totalEl.innerHTML = 'คะแนนรวม (' + parts.join('+') + ') =<span class="gcm-total-nums">' + sum + '</span>';
} else {
const pc = Math.max(0, Math.floor(Number(disp.participantCount) || 0));
totalEl.innerHTML = 'คะแนนตอบคำถาม <span class="gcm-total-nums">(' + parts.join('+') + ') = ' + sum + '</span> · ผู้เล่น ' + pc + ' → เกรด';
}
} else if (mission && mission.uiSkin === 'stack_tower') {
const pc = Math.max(0, Math.floor(Number(disp.participantCount) || 0));
totalEl.innerHTML = 'คะแนนรวม <span class="gcm-total-nums">(' + parts.join('+') + ') = ' + sum + '</span> · ผู้เล่น ' + pc + ' → เกรด';
@@ -11370,6 +11445,7 @@
const missionOk = gLetter !== 'F';
if (missionOk) {
const row = document.createElement('div');
row.className = 'gcm-bonus-okrow';
row.style.display = 'flex';
row.style.alignItems = 'center';
row.style.gap = '8px';
@@ -11384,14 +11460,25 @@
this.src = BASE + '/img/gauntlet-assets/result-check.png';
};
}
chk.width = 26;
chk.height = 26;
const sp = document.createElement('span');
sp.style.color = '#9ece6a';
sp.style.fontWeight = '700';
sp.textContent = 'ภารกิจสำเร็จ';
row.appendChild(chk);
row.appendChild(sp);
if (tfMockSummary) {
/* mockup: ใช้ป้าย "ภารกิจสำเร็จ" สำเร็จรูป mission-complete-select.png เท่านั้น */
chk.src = questionMissionAssetUrl('mission-complete-select.png');
chk.alt = 'ภารกิจสำเร็จ';
chk.onerror = function () {
this.onerror = null;
this.src = BASE + '/img/gauntlet-assets/result-check.png';
};
row.appendChild(chk);
} else {
chk.width = 26;
chk.height = 26;
const sp = document.createElement('span');
sp.style.color = '#9ece6a';
sp.style.fontWeight = '700';
sp.textContent = 'ภารกิจสำเร็จ';
row.appendChild(chk);
row.appendChild(sp);
}
bonusEl.appendChild(row);
}
const rc = disp.rewardCard;
@@ -11415,6 +11502,14 @@
else gcmHead.classList.remove('sr-only');
}
ov.classList.remove('is-hidden');
if (tfMockSummary) {
requestAnimationFrame(function () {
refreshGcmTfMockAvatarsPlay(rowEl, disp.ranked);
});
setTimeout(function () { refreshGcmTfMockAvatarsPlay(rowEl, disp.ranked); }, 200);
setTimeout(function () { refreshGcmTfMockAvatarsPlay(rowEl, disp.ranked); }, 550);
setTimeout(function () { refreshGcmTfMockAvatarsPlay(rowEl, disp.ranked); }, 1200);
}
function goLobby() {
ov.classList.add('is-hidden');
if (gcmHead) gcmHead.classList.remove('sr-only');
@@ -17093,62 +17188,219 @@
.replace(/"/g, '&quot;');
}
/** แถบ Cyber SCORE — ใช้ tint เดียวกับในเกม (ไม่ใช้ PNG รวมซิลูเอตขาวจาก getCharacterImg อย่างเดียว) */
function resolveCyberHudAvatarTintPlay(row) {
if (row && row.playTint && row.playTint.head) return row.playTint;
const peerId = row && row.id != null ? row.id : '';
if (row && row.isMe) {
return me.playTint || resolvePlayTintForPeer(String(myId != null ? myId : 'me'));
}
const sid = peerId !== '' ? String(peerId) : '';
const ox = sid ? (others.get(peerId) || others.get(sid)) : null;
if (ox && ox.playTint) return ox.playTint;
return resolvePlayTintForPeer(sid);
}
function resolveRankedCharacterIdPlay(rankedRow) {
if (!rankedRow) return '';
if (rankedRow.characterId) return String(rankedRow.characterId);
const id = rankedRow.id;
if (id == null) return '';
const ox = others.get(id) || others.get(String(id));
if (ox && ox.characterId) return String(ox.characterId);
if (myId != null && String(id) === String(myId)) {
return String(me.characterId || getPlayCharacterId() || '');
}
return '';
}
/** กัน cache/แสดง canvas ว่าง (ทำให้ช่องอันดับ 1 หายรูป แต่ retry หยุดเพราะ naturalWidth > 0) */
function playCanvasHasOpaquePixels(canvas) {
if (!canvas || canvas.width < 2 || canvas.height < 2) return false;
try {
const ctx = canvas.getContext('2d', { willReadFrequently: true });
if (!ctx) return false;
const data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (let i = 3; i < data.length; i += 16) {
if (data[i] > 12) return true;
}
} catch (e) { /* ignore */ }
return false;
}
function ensureMePlayTintFromLobbyStorage() {
if (me.playTint && me.playTint.head && me.playTint.body) return;
const t = loadPlayTintFromLobbyPlayerStorage();
if (t) me.playTint = t;
}
function cyberHudScoreAvatarCacheKey(row) {
const cid = row.characterId ? String(row.characterId) : '';
const tint = resolveCyberHudAvatarTintPlay(row);
return [row.isMe ? 'me' : String(row.id), cid, tint.head, tint.hair, tint.body, 'faceV2'].join('|');
}
function findPlayCyberHudScoreAvatarSrcForPeer(peerId) {
if (peerId == null) return '';
const sid = String(peerId).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
const ul = document.getElementById('play-cyber-score-list');
if (!ul) return '';
const row = ul.querySelector('.play-cyber-score-row[data-peer-id="' + sid + '"]');
if (!row) return '';
const av = row.querySelector('img.play-cyber-score-av');
if (!av || !av.src || av.src === defaultAvatarImg.src) return '';
if (!av.complete || av.naturalWidth < 8) return '';
return av.src;
}
/** crop หน้า idle ลง (down) + tint — ใช้ทั้ง HUD และหน้าสรุปผล ให้ตรงสีในเกม */
function composeCyberHudFacePortraitDataUrl(cid, tint) {
if (!cid || !tint) return '';
const dir = 'down';
const nowT = Date.now();
preloadPlayTintForAvatar(cid, tint);
ensurePlayLayerProbesAllDirections(cid);
const raw = getCharacterFrame(cid, dir, nowT, false) || getCharacterImg(cid, dir);
if (!raw) return '';
let srcCanvas = null;
if (raw.complete && raw.naturalWidth > 0 && raw.naturalHeight > 0) {
const composeFrame = isUploadedCharAssetId(cid) ? 0 : idleAnimPhaseIndex(nowT);
const packIdle = tryComposePlayLayersFromFiles(raw, cid, dir, composeFrame, tint, { idle: true });
if (packIdle && packIdle.canvas && playCanvasHasOpaquePixels(packIdle.canvas)) {
srcCanvas = packIdle.canvas;
}
if (!srcCanvas) {
const tinted = getPlayTintedAvatarSource(raw, cid, dir, nowT, false, tint);
if (tinted && tinted.tagName === 'CANVAS' && tinted.width > 0 && playCanvasHasOpaquePixels(tinted)) {
srcCanvas = tinted;
}
}
}
/* ตัวละครที่ไม่มีไฟล์เลเยอร์สี (เช่น defaultChar) — compose คืน Image ดิบ → crop หน้าจากรูปดิบตรง ๆ กันช่องว่าง */
let drawSrc = srcCanvas;
if (!drawSrc && raw && raw.complete && raw.naturalWidth > 0 && raw.naturalHeight > 0) {
drawSrc = raw;
}
if (!drawSrc) return '';
const face = document.createElement('canvas');
face.width = 120;
face.height = 120;
const ctx = face.getContext('2d');
if (!ctx) return '';
const sw = drawSrc.naturalWidth || drawSrc.width;
const sh = drawSrc.naturalHeight || drawSrc.height;
if (!sw || !sh) return '';
const sx = sw * 0.1;
const sy = sh * 0.02;
const sw2 = sw * 0.8;
const sh2 = sh * 0.5;
ctx.clearRect(0, 0, 120, 120);
try {
ctx.drawImage(drawSrc, sx, sy, sw2, sh2, 0, 0, 120, 120);
} catch (e) {
return '';
}
if (!playCanvasHasOpaquePixels(face)) return '';
try {
return face.toDataURL('image/png');
} catch (e) {
return '';
}
}
function cyberHudScoreAvatarImgLooksReady(img) {
return !!(img && img.src && img.src !== defaultAvatarImg.src && img.complete && img.naturalWidth > 8 && img.naturalHeight > 8);
}
/** แถบ Cyber SCORE + สรุปผล — หน้า idle down + tint ต่อผู้เล่น */
function setCyberHudScoreAvatarImg(avImg, row) {
const cid = row.characterId ? String(row.characterId) : '';
if (!cid) {
avImg.src = defaultAvatarImg.src;
return;
}
const dir = 'down';
const nowT = Date.now();
const walk = false;
const peerId = row.id;
const tint = row.isMe
? (me.playTint || resolvePlayTintForPeer(String(myId != null ? myId : 'me')))
: (() => {
const ox = others.get(peerId);
return ox ? (ox.playTint || resolvePlayTintForPeer(String(peerId))) : resolvePlayTintForPeer(String(peerId));
})();
const cacheKey = cyberHudScoreAvatarCacheKey(row);
const cached = cyberHudScoreAvatarUrlCache.get(cacheKey);
if (cached) {
avImg.src = cached;
return;
}
const hudSrc = findPlayCyberHudScoreAvatarSrcForPeer(row.id);
if (hudSrc) {
avImg.src = hudSrc;
cyberHudScoreAvatarUrlCache.set(cacheKey, hudSrc);
return;
}
const tint = resolveCyberHudAvatarTintPlay(row);
/* ย้อมสีตาม tint ปัจจุบันก่อนเสมอ (รวมตัวเรา) — อย่าใช้ lobby idle ต่อ characterId เพราะสีไม่ตรงที่เลือกใน lobby */
const faceUrl = composeCyberHudFacePortraitDataUrl(cid, tint);
if (faceUrl) {
avImg.src = faceUrl;
if (cyberHudScoreAvatarUrlCache.size >= CYBER_HUD_AV_URL_CACHE_CAP) {
const first = cyberHudScoreAvatarUrlCache.keys().next();
if (!first.done) cyberHudScoreAvatarUrlCache.delete(first.value);
}
cyberHudScoreAvatarUrlCache.set(cacheKey, faceUrl);
return;
}
if (row.isMe) {
const lobbySrc = playLobbyIdleAvatarSrcForCharacter(cid);
if (lobbySrc) {
avImg.src = lobbySrc;
cyberHudScoreAvatarUrlCache.set(cacheKey, lobbySrc);
return;
}
}
const cacheKey = [row.isMe ? 'me' : String(peerId), cid, tint.head, tint.hair, tint.body, 'lobbyV3'].join('|');
const comp = resolvePlayDrawCharSource(cid, dir, nowT, walk, tint, !!row.isMe);
if (comp && comp.tagName === 'CANVAS' && comp.width > 0) {
let dataUrl = cyberHudScoreAvatarUrlCache.get(cacheKey);
if (!dataUrl) {
try {
dataUrl = comp.toDataURL('image/png');
} catch (e) {
dataUrl = '';
}
if (dataUrl) {
if (cyberHudScoreAvatarUrlCache.size >= CYBER_HUD_AV_URL_CACHE_CAP) {
const first = cyberHudScoreAvatarUrlCache.keys().next();
if (!first.done) cyberHudScoreAvatarUrlCache.delete(first.value);
}
cyberHudScoreAvatarUrlCache.set(cacheKey, dataUrl);
}
}
if (dataUrl) {
avImg.src = dataUrl;
const dir = 'down';
const nowT = Date.now();
const frameIm = getCharacterFrame(cid, dir, nowT, false) || getCharacterImg(cid, dir);
if (frameIm && frameIm.src) {
if (!frameIm.complete || !frameIm.naturalWidth) {
avImg.src = frameIm.src;
frameIm.addEventListener('load', function onHudAvFrame() {
frameIm.removeEventListener('load', onHudAvFrame);
setCyberHudScoreAvatarImg(avImg, row);
}, { once: true });
return;
}
const im = getCharacterImg(cid, dir);
avImg.src = im && im.src ? im.src : defaultAvatarImg.src;
return;
}
if (comp && comp.src) {
avImg.src = comp.src;
} else {
const im = getCharacterImg(cid, dir);
avImg.src = im && im.src ? im.src : defaultAvatarImg.src;
}
avImg.src = defaultAvatarImg.src;
}
/** ลองโหลด avatar ซ้ำจน sprite/tint พร้อม (กันรูปหายตอนเปิด overlay) */
function applyCyberHudScoreAvatarImgWithRetry(avImg, row, attempt) {
attempt = attempt || 0;
setCyberHudScoreAvatarImg(avImg, row);
const ok = cyberHudScoreAvatarImgLooksReady(avImg)
&& (avImg.src.indexOf('data:image/') === 0 || (row.isMe && avImg.src.indexOf('/img/') >= 0));
if (ok) return;
if (attempt >= 16) return;
const cid = row.characterId ? String(row.characterId) : '';
const delay = 40 + attempt * 90;
setTimeout(function () {
if (cid) preloadPlayTintForAvatar(cid, resolveCyberHudAvatarTintPlay(row));
applyCyberHudScoreAvatarImgWithRetry(avImg, row, attempt + 1);
}, delay);
}
function refreshGcmTfMockAvatarsPlay(rowEl, ranked) {
if (!rowEl || !Array.isArray(ranked)) return;
const imgs = rowEl.querySelectorAll('img.gcm-av');
ranked.forEach(function (r, idx) {
const img = imgs[idx];
if (!img) return;
const cid = resolveRankedCharacterIdPlay(r);
const avRow = {
id: r.id,
characterId: cid,
isMe: myId != null && r.id != null && String(r.id) === String(myId),
playTint: resolveCyberHudAvatarTintPlay({
id: r.id,
characterId: cid,
isMe: myId != null && r.id != null && String(r.id) === String(myId),
}),
};
applyCyberHudScoreAvatarImgWithRetry(img, avRow, 0);
});
}
function quizQuestionMissionJoystickResetVisual() {
@@ -17205,6 +17457,68 @@
}
}
/* mng8a80o: scale HUD (fix 1920×1080) container 16:9 scale.js mockup Minigame-1
สำค: คำนวณเฉพาะตอนเขาโหมด/resize เทาน (ามอาน layout กเฟรมใน draw loop กระต) */
let _quizTfScaleLast = 0;
let _quizTfMockActivePrev = false;
function updateQuizTfMockScale(root) {
root = root || document.getElementById('play-cyber-hud');
if (!root) return;
let cw;
let ch;
if (document.documentElement.classList.contains('play-preview-editor-embed')) {
const host = root.offsetParent || root.parentElement || document.querySelector('.game-wrap');
cw = (host && host.clientWidth) || window.innerWidth;
ch = (host && host.clientHeight) || window.innerHeight;
} else {
cw = window.innerWidth;
ch = window.innerHeight;
}
const s = Math.min(cw / 1920, ch / 1080);
if (!(s > 0 && isFinite(s))) return;
/* เขียนเฉพาะเมื่อค่าต่างจริง (กันการเขียน style ซ้ำ → invalidate ทุกเฟรม) */
if (Math.abs(s - _quizTfScaleLast) < 0.0005) return;
_quizTfScaleLast = s;
root.style.setProperty('--qtf-scale', String(s));
}
/* mng8a80o: สรุปผลภารกิจ (06-summary) — scale popup 1451×851 ตามสูตรเดียวกับ HUD (min vw/1920, vh/1080) */
function updateGcmTfMockScale(ov) {
ov = ov || document.getElementById('gauntlet-crown-mission-overlay');
if (!ov) return;
const s = Math.min(window.innerWidth / 1920, window.innerHeight / 1080);
if (s > 0 && isFinite(s)) ov.style.setProperty('--gcm-tf-scale', String(s));
}
/* mng8a80o: popup HOW TO PLAY (01-howto) — scale stage 1920×1080 ตามสูตรเดียวกัน */
function updateGchTfMockScale(ov) {
ov = ov || document.getElementById('gauntlet-crown-howto-overlay');
if (!ov) return;
const s = Math.min(window.innerWidth / 1920, window.innerHeight / 1080);
if (s > 0 && isFinite(s)) ov.style.setProperty('--gch-tf-scale', String(s));
}
let _quizTfScaleObserversBound = false;
function ensureQuizTfScaleResizeListener() {
if (_quizTfScaleObserversBound) return;
_quizTfScaleObserversBound = true;
const recompute = function () {
const r = document.getElementById('play-cyber-hud');
if (r && r.classList.contains('play-cyber-hud--quiz-tf-mock')) updateQuizTfMockScale(r);
const ov = document.getElementById('gauntlet-crown-mission-overlay');
if (ov && ov.classList.contains('gcm-quiz-tf-mock') && !ov.classList.contains('is-hidden')) updateGcmTfMockScale(ov);
const hv = document.getElementById('gauntlet-crown-howto-overlay');
if (hv && hv.classList.contains('gch-quiz-tf-mock') && !hv.classList.contains('is-hidden')) updateGchTfMockScale(hv);
};
window.addEventListener('resize', recompute);
window.addEventListener('orientationchange', recompute);
/* ResizeObserver จับ container ที่เปลี่ยนขนาดโดยไม่มี window resize (เช่น ลากแบ่งจอ editor) */
if (typeof ResizeObserver === 'function') {
try {
const ro = new ResizeObserver(recompute);
const host = document.querySelector('.game-wrap') || document.documentElement;
if (host) ro.observe(host);
} catch (e) { /* ignore */ }
}
}
function syncPlayCyberHud() {
const root = document.getElementById('play-cyber-hud');
const stackEl = document.getElementById('play-canvas-stack');
@@ -17224,11 +17538,31 @@
const gw = document.querySelector('.game-wrap');
if (gw) gw.classList.toggle('play-cyber-active', !!on);
if (!on || !root) return;
ensureMePlayTintFromLobbyStorage();
root.classList.toggle(
'play-cyber-hud--question-mission',
!!(isQuizQuestionMissionHudActivePlay() || isStackTowerMissionHudActivePlay() || isJumpSurviveMissionHudActivePlay()
|| isSpaceShooterMissionHudActivePlay()),
);
/* mng8a80o เท่านั้น — สไตล์ HUD ตาม mockup Minigame-1 (score-bar.png / Avartar.png / time.png) แยกจากคลาสร่วม */
root.classList.toggle('play-cyber-hud--quiz-tf-mock', !!isQuizQuestionMissionUiMapPlay());
const tfMockOn = root.classList.contains('play-cyber-hud--quiz-tf-mock');
if (tfMockOn) {
/* คำนวณ scale เฉพาะตอนเพิ่งเข้าโหมด — ไม่อ่าน layout ทุกเฟรม (กันกระตุก); ที่เหลือพึ่ง resize/ResizeObserver */
if (!_quizTfMockActivePrev) {
ensureQuizTfScaleResizeListener();
updateQuizTfMockScale(root);
/* เฟรมถัดไป layout นิ่งแล้ว วัดอีกครั้งให้แม่น */
requestAnimationFrame(function () {
const r = document.getElementById('play-cyber-hud');
if (r && r.classList.contains('play-cyber-hud--quiz-tf-mock')) updateQuizTfMockScale(r);
});
}
} else if (_quizTfMockActivePrev) {
root.style.removeProperty('--qtf-scale');
_quizTfScaleLast = 0;
}
_quizTfMockActivePrev = tfMockOn;
root.classList.toggle(
'play-cyber-hud--stack-tower-canvas-hud',
!!(playBotsEnabled() && stackMini && isStack() && isStackTowerMissionUiMapPlay()),
@@ -17381,27 +17715,12 @@
if (portrait) {
const cid = me.characterId || getPlayCharacterId();
const dir = isSpaceShooter()
? 'down'
: (isGauntletFaceRightMapMno9kb07() ? 'right' : (me.direction || 'down'));
const nowT = Date.now();
const walk = !!me.isWalking;
const rawImg = getAvatarImg(cid, dir, nowT, walk);
const tint = me.playTint || resolvePlayTintForPeer(String(myId != null ? myId : 'me'));
const comp = rawImg && cid && tint
? getPlayTintedAvatarSource(rawImg, cid, dir, nowT, walk, tint)
: rawImg;
if (comp && comp.tagName === 'CANVAS' && comp.width > 0) {
try {
portrait.src = comp.toDataURL('image/png');
} catch (e) {
if (rawImg && rawImg.src) portrait.src = rawImg.src;
}
} else if (comp && comp.src) {
portrait.src = comp.src;
} else if (rawImg && rawImg.src) {
portrait.src = rawImg.src;
}
setCyberHudScoreAvatarImg(portrait, {
id: myId,
characterId: cid,
isMe: true,
playTint: me.playTint || resolvePlayTintForPeer(String(myId != null ? myId : 'me')),
});
}
if (statusEl) {
if (isSpaceShooterMissionHudActivePlay()) {
@@ -17524,6 +17843,7 @@
/* mnptfts2 — ไม่แสดงแผง SCORE (เหลือ TIME + โปรไฟล์) */
if (isJumpSurviveMissionUiMapPlay()) {
ul.innerHTML = '';
ul.dataset.cyberSig = '';
const boardSkip = ul.closest('.play-cyber-scoreboard');
if (boardSkip) boardSkip.classList.remove('play-cyber-scoreboard--crown-strip');
ul.classList.remove('play-cyber-score-list--crown-strip');
@@ -17567,12 +17887,15 @@
const spaceMissionLiveHud = isSpaceShooterMissionHudActivePlay();
/** แถบ SCORE แบบ mock mng8a80o (แนวนอน อวาตาร์+ชื่อ | คะแนน) — ภารกิจคำถาม + Stack Tower + Jumper mnptfts2 + Space mnpz6rkp */
const cyberQmMockHud = quizMissionHud || stackMissionHud || jumpMissionLiveHud || spaceMissionLiveHud;
/** mng8a80o เท่านั้น — layout แถวแบบ mockup: [avatar | ชื่อบน/คะแนนล่าง] (ใช้ meta column) */
const tfMockHud = isQuizQuestionMissionUiMapPlay();
const stackTeamPts = Math.max(0, Number(stackMini && stackMini.score) || 0);
const rows = [];
rows.push({
id: myId,
nickname: me.nickname || nick,
characterId: me.characterId || getPlayCharacterId(),
playTint: me.playTint || resolvePlayTintForPeer(String(myId != null ? myId : (nick || 'local'))),
score: (isQuizCarry() || quizMissionHud) ? cyberHudQuizCarryPeerScore(myId)
: (stackMissionHud
? (playBotsEnabled() ? (me.stackPreviewHumanPts || 0) : stackTeamPts)
@@ -17590,6 +17913,7 @@
id,
nickname: o.nickname || id.slice(0, 8),
characterId: o.characterId,
playTint: o.playTint || resolvePlayTintForPeer(id),
score: (isQuizCarry() || quizMissionHud) ? cyberHudQuizCarryPeerScore(id)
: (stackMissionHud
? (playBotsEnabled() && isPreviewBotId(id) ? (o.stackBotScore || 0) : stackTeamPts)
@@ -17632,7 +17956,6 @@
return a.y - b.y;
});
ul.innerHTML = '';
const cap = stripScoreHud ? (isQuizCarry() ? 8 : 6) : 8;
let hudRows = rows.slice(0, Math.min(cap, rows.length));
if (stripScoreHud) {
@@ -17642,12 +17965,33 @@
hudRows.push(mine);
}
}
/* กันกระตุก: rebuild DOM เฉพาะตอนเนื้อหา (id/score/order/สี/ตกรอบ) เปลี่ยน — ไม่ลบ-สร้างทุกเฟรม */
const listSig = [
cyberQmMockHud ? 'qm' : '', stripScoreHud ? 'strip' : '', leaderId == null ? '' : String(leaderId),
hudRows.map(function (rw) {
const t = rw.playTint || {};
return String(rw.id) + ':' + String(rw.score) + ':' + (rw.eliminated ? 1 : 0)
+ ':' + String(rw.characterId || '') + ':' + String(t.body || '') + ':' + String(t.head || '');
}).join(','),
].join('|');
if (ul.dataset.cyberSig === listSig) {
const existImgs = ul.querySelectorAll('img.play-cyber-score-av');
if (existImgs.length === hudRows.length) {
for (let i = 0; i < existImgs.length; i++) {
if (!cyberHudScoreAvatarImgLooksReady(existImgs[i])) setCyberHudScoreAvatarImg(existImgs[i], hudRows[i]);
}
return;
}
}
ul.dataset.cyberSig = listSig;
ul.innerHTML = '';
for (let r = 0; r < hudRows.length; r++) {
const row = hudRows[r];
const li = document.createElement('li');
li.className = 'play-cyber-score-row' + (row.isMe ? ' is-me' : '') + (row.eliminated ? ' is-out' : '')
+ (cyberQmMockHud ? ' play-cyber-score-row--qm-mock' : '')
+ (stripScoreHud ? ' play-cyber-score-row--crown-strip' : '');
if (row.id != null) li.setAttribute('data-peer-id', String(row.id));
const av = document.createElement('img');
av.className = 'play-cyber-score-av' + (cyberQmMockHud ? ' play-cyber-score-av--qm' : '')
+ (stripScoreHud ? ' play-cyber-score-av--crown-strip' : '');
@@ -17673,14 +18017,32 @@
qmLeft.className = 'play-cyber-qm-left';
const avWrap = document.createElement('span');
avWrap.className = 'play-cyber-qm-av-wrap';
avWrap.appendChild(av);
if (tfMockHud) {
/* mng8a80o: หน้าตัวละครต้องอยู่ "บน" กรอบ (กรอบกลางทึบ) + clip ให้อยู่ในขอบ */
const avClip = document.createElement('span');
avClip.className = 'play-cyber-qm-av-clip';
avClip.appendChild(av);
avWrap.appendChild(avClip);
} else {
avWrap.appendChild(av);
}
const qmName = document.createElement('span');
qmName.className = 'play-cyber-qm-name';
qmName.textContent = String(row.nickname || '').trim().slice(0, 28);
qmLeft.appendChild(avWrap);
qmLeft.appendChild(qmName);
li.appendChild(qmLeft);
li.appendChild(sc);
if (tfMockHud) {
/* mockup Minigame-1: avatar ซ้าย | (ชื่อบน / คะแนนล่าง) ในคอลัมน์ meta */
const qmMeta = document.createElement('div');
qmMeta.className = 'play-cyber-qm-meta';
qmMeta.appendChild(qmName);
qmMeta.appendChild(sc);
qmLeft.appendChild(qmMeta);
li.appendChild(qmLeft);
} else {
qmLeft.appendChild(qmName);
li.appendChild(qmLeft);
li.appendChild(sc);
}
} else if (stripScoreHud) {
const cell = document.createElement('div');
cell.className = 'play-cyber-crown-strip-cell';
+630 -2
View File
@@ -2812,6 +2812,10 @@
0 0 24px rgba(0, 200, 255, 0.2),
inset 0 0 20px rgba(0, 255, 240, 0.06);
}
/* wrapper โปร่ง (display:contents) — เกมอื่นไม่เปลี่ยน; เฉพาะ quiz-tf-mock จะใช้เป็นกล่อง clip หน้า */
.play-cyber-portrait-clip {
display: contents;
}
.play-cyber-self-frame img {
display: block;
width: 72px;
@@ -2904,6 +2908,628 @@
border-radius: inherit;
}
/* =========================================================
mng8a80o เท่านั้น — HUD สไตล์ mockup Minigame-1 "จริงหรือไม่"
scope: #play-cyber-hud.play-cyber-hud--quiz-tf-mock
+ #gauntlet-crown-howto-overlay.gch-quiz-tf-mock
responsive-faithful: สัดส่วนเหมือน mockup บนจอ 16:9 แต่ยังเล่นมือถือได้
(ไม่กระทบ Stack/Jumper/Space ที่ใช้ --question-mission ร่วมกัน)
========================================================= */
/* ====== fix layout 1920×1080 แล้ว scale ทั้งก้อน (เทียบ scale.js ของ mockup) ======
--qtf-scale ตั้งจาก JS = min(W/1920, H/1080) → ทุกชิ้นเป็น px คงที่ ตรง mockup เป๊ะบนจอ 16:9
selector มี html + .play-cyber-hud ซ้ำ เพื่อชนะ rule editor-embed (position:absolute; inset:0) */
html #play-cyber-hud.play-cyber-hud.play-cyber-hud--quiz-tf-mock {
width: 1920px;
height: 1080px;
inset: auto;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) scale(var(--qtf-scale, 1));
transform-origin: center center;
}
/* ---- SCORE panel: score-bar.png 156×433 @ (2,16) (เหมือน mockup) ---- */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-scoreboard {
position: absolute;
left: 2px;
top: 16px;
width: 156px;
height: 433px;
aspect-ratio: auto;
padding: 0;
background: url('/Game/img/QUESTION/score-bar.png') no-repeat left top / 156px 433px;
border: none;
border-radius: 0;
box-shadow: none;
overflow: hidden;
}
/* หัว SCORE อยู่ในภาพ score-bar.png แล้ว — ซ่อน title text กันซ้ำ */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-panel-title {
display: none !important;
}
/* list @ (16,60) width136 — rows แบ่งพื้นที่เท่ากัน (5 คน ≈ 70px ตาม mockup, 6 คนหดพอดี ไม่ล้น) */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-score-list {
position: absolute;
left: 16px;
top: 60px;
width: 136px;
height: 357px;
max-height: none;
padding: 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
gap: 5px;
overflow: hidden;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-score-row--qm-mock {
display: flex;
flex-direction: row;
align-items: center;
padding: 0;
border-bottom: none;
flex: 1 1 0;
min-height: 0;
max-height: 70px;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-qm-left {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
flex: 1 1 auto;
min-width: 0;
height: 100%;
}
/* avatar (≈70px) : กรอบ score-avartar.png กลางทึบ navy → ใช้เป็น "พื้นหลัง", หน้าตัวละครวาง "ทับบน" + clip ในขอบ
(มองไม่เห็นถ้าวางหน้าใต้กรอบ เพราะกลางกรอบทึบ — ต่างจาก mockup ที่ <img> ว่าง) */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-qm-av-wrap {
position: relative;
height: 100%;
aspect-ratio: 1 / 1;
width: auto;
flex: 0 0 auto;
border: none;
border-radius: 0;
overflow: visible;
background: url('/Game/img/QUESTION/score-avartar.png') no-repeat center / 100% 100%;
}
/* clip = ช่อง navy ในกรอบ (เว้นขอบ cyan ~4px/70≈6%) — หน้าตัวละครถูก crop ในนี้ วางทับ navy */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-qm-av-clip {
position: absolute;
inset: 7%;
overflow: hidden;
border-radius: 12%;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-score-row--qm-mock .play-cyber-score-av--qm {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center center;
border: none;
border-radius: 0;
transform: none;
background: transparent;
}
/* meta: ชื่อบน / คะแนนล่าง (ตาม mockup .meta) */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-qm-meta {
display: flex;
flex-direction: column;
justify-content: center;
gap: 1px;
min-width: 0;
flex: 1 1 auto;
line-height: 1.05;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-qm-name {
font-family: 'NotoSansThai', 'Kanit', sans-serif;
font-weight: 700;
font-size: 11px;
letter-spacing: 0.2px;
text-transform: uppercase;
color: #e8f4ff;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-qm-score {
font-family: 'NotoSansThai', 'Orbitron', sans-serif;
font-weight: 900;
font-size: 22px;
line-height: 1;
color: #ffffff;
text-align: left;
min-width: 0;
text-shadow: 0 0 8px rgba(120, 220, 255, 0.6);
}
/* ---- TIME @ center top:23 — time.png 131×71 + เลข 42px (mockup .mg-time) ---- */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-center-stack {
top: 23px;
left: 50%;
transform: translateX(-50%);
gap: 0;
max-width: none;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-time-head--qm-plaque {
flex-direction: row;
align-items: center;
gap: 10px;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-time-head--qm-plaque .play-cyber-time-plaque-img {
height: 71px;
width: auto;
max-width: none;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-time-val {
font-family: 'NotoSansThai', sans-serif;
font-weight: 900;
font-size: 42px;
height: 71px;
line-height: 71px;
letter-spacing: 1px;
color: #e6f6ff;
text-shadow:
0 0 10px rgba(120, 220, 255, 0.85),
0 0 22px rgba(80, 180, 240, 0.55);
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-time-sub {
display: none !important;
}
/* ---- Host @ (1729,21) 201×201 + face window 104×104@(49,49) + mic 121@(1796,205) (mockup) ---- */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-self {
position: absolute;
left: 1729px;
top: 21px;
right: auto;
width: 201px;
height: 201px;
display: block;
gap: 0;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-self-frame {
position: absolute;
inset: 0;
padding: 0;
border: none;
border-radius: 0;
box-shadow: none;
background: url('/Game/img/QUESTION/Avartar.png') no-repeat center / 201px 201px;
width: 201px;
height: 201px;
overflow: visible;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-portrait-clip {
display: block;
position: absolute;
left: 49px;
top: 49px;
width: 104px;
height: 104px;
overflow: hidden;
border-radius: 8px;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-self-frame img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 26%;
transform: scale(1.32);
transform-origin: center 32%;
border-radius: 0;
background: transparent;
}
/* mockup มุมขวาบนมีแค่กรอบ + mic — ซ่อน status/op widgets ให้สะอาด */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-self-status,
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-op-widgets {
display: none !important;
}
/* mic 121px @ (1796,205) → relative to host (1729,21) = (67,184) */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-self::after {
content: '';
position: absolute;
left: 67px;
top: 184px;
width: 121px;
height: 121px;
background: url('/Game/img/QUESTION/btn-mic_on.png') no-repeat center / contain;
filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.5));
pointer-events: none;
}
/* ====== Popup HOW TO PLAY (mng8a80o) — fix stage 1920×1080 แล้ว scale ทั้งก้อนตาม mockup 01-howto ======
scope: #gauntlet-crown-howto-overlay.gch-quiz-tf-mock · --gch-tf-scale = min(W/1920,H/1080) */
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-shell {
width: 1920px !important;
height: 1080px !important;
min-width: 1920px !important;
max-width: none !important;
min-height: 1080px !important;
max-height: none !important;
flex: none !important;
padding: 0 !important;
border-radius: 0;
display: block;
transform: scale(var(--gch-tf-scale, 0.62));
transform-origin: center center;
}
/* popup-Howto.png 1451×851 → mockup โชว์ 1500×880 @ (50%, 50px) */
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-bg {
position: absolute;
left: 50%;
top: 50px;
transform: translateX(-50%);
width: 1500px;
height: 880px;
max-height: none;
object-fit: fill;
filter: none;
}
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art {
position: absolute;
inset: 0;
width: 1920px;
height: 1080px;
transform: none;
padding: 0;
}
/* footer คลุมเต็ม stage — วาง status/ปุ่ม ด้วยพิกัด mockup */
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .gch-art-footer {
position: absolute;
left: 0;
top: 0;
right: auto;
bottom: auto;
width: 1920px;
height: 1080px;
transform: none;
display: block;
gap: 0;
}
/* status "Ready Status : x/y" @ (50%, 808px) สีชมพู 22px (mockup .howto-status) */
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .gch-status {
position: absolute;
left: 0;
right: 0;
top: 808px;
transform: none;
width: -moz-fit-content;
width: fit-content;
max-width: 100%;
margin: 0 auto;
text-align: center;
white-space: nowrap;
font-family: 'NotoSansThai', sans-serif;
font-weight: 700;
font-size: 22px;
letter-spacing: 0.5px;
color: #f067e8;
text-shadow:
0 0 10px rgba(240, 103, 232, 0.6),
0 0 22px rgba(237, 86, 224, 0.35);
}
/* ปุ่ม READY/START — btn 299×120 (height 120, aspect 2.49) center @ (957, 885) */
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready {
position: absolute;
left: 0;
right: 0;
top: 825px;
transform: none;
width: 299px;
height: 120px;
margin: 0 auto;
background-image: url('/Game/img/QUESTION/btn-ready.png');
background-repeat: no-repeat;
background-position: center;
background-size: contain;
filter: drop-shadow(0 0 18px rgba(120, 220, 255, 0.65));
font-size: 0;
color: transparent;
text-indent: -9999px;
overflow: hidden;
border: none;
}
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready.is-start-phase {
background-image: url('/Game/img/QUESTION/btn-start.png');
}
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready:hover {
transform: translateY(-3px);
filter: drop-shadow(0 0 28px rgba(120, 220, 255, 0.95));
}
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready:active {
transform: translateY(2px);
}
/* ====== หน้าสรุปผลภารกิจ (mng8a80o) — fix popup 1451×851 แล้ว scale ทั้งก้อนตาม mockup 06-summary ======
scope: #gauntlet-crown-mission-overlay.gcm-quiz-tf-mock
พิกัด px = sm-content ของ mockup (อิง popup origin) · --gcm-tf-scale ตั้งจาก JS = min(W/1920,H/1080) */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-shell {
width: 1451px;
height: 851px;
max-width: none;
max-height: none;
padding: 0;
border-radius: 0;
transform: scale(var(--gcm-tf-scale, 0.62));
transform-origin: center center;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bg {
width: 1451px;
height: 851px;
max-height: none;
object-fit: fill;
filter: none;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-inner {
left: 0;
top: 0;
transform: none;
width: 1451px;
height: 851px;
max-height: none;
overflow: hidden;
padding: 0;
border-radius: 0;
}
/* heading "สรุปผลภารกิจ" อยู่ในภาพ popup-result.png แล้ว (play.js ใส่ sr-only) — กันเผื่อ */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-header-tab {
display: none !important;
}
/* ranks: 5 ช่อง ×137 gap30 @ (323,168) width805 (mockup .sm-ranks) */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-rank-row {
position: absolute;
left: 323px;
top: 168px;
width: 805px;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: center;
gap: 30px;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-cell {
flex: 0 0 137px;
width: 137px;
min-width: 137px;
text-align: center;
position: relative;
margin: 0;
padding: 0;
display: block;
}
/* badge อันดับ (result-1st/2nd/3rd / txt-1/2) — .pos 41×21 */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-rank-tag {
color: transparent;
margin: 0 auto 6px;
min-height: 0;
height: 21px;
display: block;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-rank-tag img {
display: block;
width: 41px;
height: 21px;
margin: 0 auto;
object-fit: contain;
}
/* กรอบ avatar — mockup: portrait z2 ใต้ frame img z3 (137×137) */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-frame {
position: relative;
width: 137px;
height: 137px;
margin: 0 auto 4px;
border: none;
box-shadow: none;
border-radius: 0;
background: transparent;
overflow: visible;
flex: none;
aspect-ratio: auto;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-av-clip {
position: absolute;
inset: 10px;
z-index: 4;
overflow: hidden;
border-radius: 14%;
background: transparent;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-frame img.gcm-av {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 18%;
transform: none;
border-radius: 0;
image-rendering: auto;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-frame img.gcm-frame-img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 3;
pointer-events: none;
object-fit: contain;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-cell--out .gcm-av-clip,
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-cell--out .gcm-frame img.gcm-av,
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-cell--out .gcm-frame img.gcm-frame-img {
filter: opacity(0.5);
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-frame img.gcm-stamp {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(-8deg);
width: 114px;
height: auto;
z-index: 5;
pointer-events: none;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-nick {
display: block;
flex: none;
min-height: 0;
width: 100%;
font-family: 'NotoSansThai', 'Kanit', sans-serif;
font-weight: 900;
font-size: 15px;
color: #fff;
letter-spacing: 0.3px;
line-height: 1.2;
height: 19px;
margin: 0 0 2px;
padding: 0 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-sc {
display: block;
flex: none;
width: 100%;
margin: 0;
padding: 0;
text-align: center;
font-family: 'NotoSansThai', sans-serif;
font-weight: 900;
font-size: 26px;
color: #fff;
line-height: 1;
font-variant-numeric: normal;
text-shadow: 0 0 10px rgba(120, 220, 255, 0.4);
}
/* คะแนนรวม @ top394 กว้าง 938 กลาง + เส้น Line1 บน/ล่าง (mockup .sm-total + .sm-line) */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-total {
position: absolute;
left: 50%;
top: 394px;
width: 938px;
transform: translateX(-50%);
margin: 0;
padding: 6px 0;
text-align: center;
font-family: 'NotoSansThai', sans-serif;
font-weight: 700;
font-size: 24px;
color: #ffd047;
letter-spacing: 0.3px;
line-height: 1.2;
border-width: 3px 0;
border-style: solid;
border-image: url('/Game/img/QUESTION/popup-result-Line1.png') 3 stretch;
text-shadow: 0 0 10px rgba(255, 200, 80, 0.45), 0 2px 4px rgba(0, 0, 0, 0.6);
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-total-nums {
font-weight: 900;
font-size: 40px;
color: #fff;
margin-left: 6px;
text-shadow: 0 0 14px rgba(120, 220, 255, 0.55);
}
/* โซนล่าง @ (72,460) สูง 270: เกรด | เส้น Line2 | โบนัส (mockup .sm-bottom) */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bottom {
position: absolute;
left: 72px;
right: 72px;
top: 460px;
height: 270px;
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 0;
align-items: start;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bottom > div:first-child {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
margin-top: 41px;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bottom > div:last-child {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
padding-left: 40px;
padding-top: 42px;
border-left: 4px solid;
border-image: url('/Game/img/QUESTION/popup-result-Line2.png') 4 stretch;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bottom > div:last-child .gcm-h {
width: 100%;
text-align: left;
padding-left: 23px;
margin-bottom: 8px;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-h {
font-family: 'NotoSansThai', sans-serif;
font-weight: 700;
font-size: 40px;
color: #fff;
margin: 0 0 12px;
line-height: 1.2;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-grade {
color: #fff !important;
font-family: 'NotoSansThai', sans-serif;
font-weight: 900;
font-size: 96px;
line-height: 0.95;
text-shadow:
0 0 16px rgba(120, 220, 255, 0.65),
0 0 32px rgba(80, 180, 240, 0.4) !important;
}
/* โบนัส: mission-complete-select.png (271×90) แทน check+ข้อความ + ซ่อน plaque (ตรง mockup) */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bonus {
display: block;
width: 271px;
padding-left: 23px;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bonus .gcm-bonus-okrow {
display: block !important;
gap: 0 !important;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bonus .gcm-bonus-okrow span {
display: none !important;
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-bonus img {
width: 271px !important;
height: 90px !important;
max-width: none;
max-height: none;
object-fit: contain;
filter: drop-shadow(0 0 10px rgba(91, 255, 141, 0.45));
}
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .gcm-plaque {
display: none !important;
}
/* ปุ่มรับหลักฐาน @ (550,704) 351×141 (mockup .sm-btn-done) */
#gauntlet-crown-mission-overlay.gcm-quiz-tf-mock .btn-gcm-done {
position: absolute;
left: 550px;
top: 704px;
width: 351px;
height: 141px;
margin: 0;
background-image: url('/Game/img/QUESTION/btn-done.png');
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
/* Quiz Battle — MCQ โดม (กด E) */
#quiz-battle-mcq-overlay {
position: fixed;
@@ -3052,7 +3678,9 @@
</div>
<div class="play-cyber-self">
<div class="play-cyber-self-frame">
<img id="play-cyber-portrait-img" alt="" width="72" height="72" />
<span class="play-cyber-portrait-clip">
<img id="play-cyber-portrait-img" alt="" width="72" height="72" />
</span>
</div>
<div id="play-cyber-self-status" class="play-cyber-self-status"></div>
<div id="play-cyber-op-widgets" class="play-cyber-op-widgets" aria-hidden="true">
@@ -3214,7 +3842,7 @@
<script src="/app-base.js?v=2"></script>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0306"></script>
<script src="js/play.js?v=0.0475"></script>
<script src="js/play.js?v=0.0498"></script>
<div class="version-tag">v —</div>
</body>
</html>
@@ -60,8 +60,8 @@
</div>
<!-- ===== TIME : 0 (top-center) ===== -->
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">0</span>
</div>
@@ -29,8 +29,8 @@
</div>
<!-- ===== TIME ===== -->
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">10</span></div>
<!-- ===== Host avatar + mic ===== -->
@@ -27,8 +27,8 @@
</div>
</div>
<div class="layer mg-time is-warning">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<div class="layer mg-time is-warning">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">0</span></div>
<div class="layer mg-host">
@@ -27,8 +27,8 @@
</div>
</div>
<div class="layer mg-time is-warning">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<div class="layer mg-time is-warning">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">5</span></div>
<div class="layer mg-host">
@@ -27,8 +27,8 @@
</div>
</div>
<div class="layer mg-time is-warning">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<div class="layer mg-time is-warning">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">0</span></div>
<div class="layer mg-host">
@@ -0,0 +1,186 @@
/* =========================================================
runner.css หน้า 0206 (Countdown / Gameplay / Finish / Game Over / Complete)
อ้างอิง Mockup/0206.png
========================================================= */
/* ---------- Countdown "3" (Mockup/02) ---------- */
.rn-countdown {
left: 50%;
top: 420px;
transform: translate(-50%, -50%);
font-family: "NotoSansThai", sans-serif;
font-weight: 900;
font-size: 220px;
line-height: 1;
color: #ffd93d;
-webkit-text-stroke: 6px #1a1208;
text-shadow:
0 0 24px rgba(255, 210, 60, 0.85),
0 6px 0 #c89400;
z-index: 6;
pointer-events: none;
}
/* เส้นเลเซอร์แดง (obstacles-1.png 50×850) */
.rn-laser {
left: 958px;
top: 230px;
width: 50px;
height: 850px;
z-index: 5;
}
.rn-laser img {
width: 100%;
height: 100%;
object-fit: fill;
}
/* ---------- สิ่งกีดขวาง (Mockup/03) ---------- */
.rn-obstacles {
left: 1550px;
top: 230px;
width: 103px;
height: 850px;
z-index: 4;
pointer-events: none;
}
.rn-obstacles img {
position: absolute;
left: 0;
width: 103px;
height: 132px;
object-fit: contain;
}
.rn-obstacles .obs-1 { top: 0; }
.rn-obstacles .obs-2 { top: 178px; }
.rn-obstacles .obs-3 { top: 356px; }
.rn-obstacles .obs-4 { top: 534px; }
.rn-obstacles .obs-5 { top: 712px; }
/* ---------- ตัวละครวิ่ง (placeholder chibi) ---------- */
.rn-runners {
left: 0;
top: 230px;
width: 1920px;
height: 850px;
z-index: 5;
pointer-events: none;
}
.rn-runner {
position: absolute;
width: 86px;
height: 92px;
}
.rn-runner .ch-body {
position: absolute;
left: 50%;
bottom: 0;
width: 86px;
height: 52px;
transform: translateX(-50%);
border-radius: 50%;
background: var(--body, #6a6f96);
box-shadow: inset 0 6px 8px rgba(255, 255, 255, 0.2);
}
.rn-runner .ch-head {
position: absolute;
left: 50%;
bottom: 34px;
width: 54px;
height: 54px;
transform: translateX(-50%);
border-radius: 50%;
background: var(--skin, #f5d6b3);
z-index: 2;
}
.rn-runner .ch-hair {
position: absolute;
left: 50%;
bottom: 52px;
width: 62px;
height: 36px;
transform: translateX(-50%);
border-radius: 50% 50% 16px 16px / 80% 80% 28% 28%;
background: var(--hair, #2a2a2a);
z-index: 3;
}
.rn-runner.is-jump {
animation: rn-jump 0.55s ease-out;
}
@keyframes rn-jump {
0%, 100% { transform: translateY(0); }
45% { transform: translateY(-72px); }
}
/* ตำแหน่ง lane บนพรมแดง (y จาก top ของ rn-runners) */
.rn-runner.lane-1 { top: 42px; }
.rn-runner.lane-2 { top: 212px; }
.rn-runner.lane-3 { top: 382px; }
.rn-runner.lane-4 { top: 552px; }
.rn-runner.lane-5 { top: 722px; }
/* หน้า countdown — เรียงที่ START */
.rn-page-countdown .rn-runner.lane-1 { left: 120px; }
.rn-page-countdown .rn-runner.lane-2 { left: 120px; }
.rn-page-countdown .rn-runner.lane-3 { left: 120px; }
.rn-page-countdown .rn-runner.lane-4 { left: 120px; }
.rn-page-countdown .rn-runner.lane-5 { left: 120px; }
/* หน้า gameplay */
.rn-page-gameplay .rn-runner.lane-1 { left: 380px; }
.rn-page-gameplay .rn-runner.lane-2 { left: 520px; }
.rn-page-gameplay .rn-runner.lane-3 { left: 280px; }
.rn-page-gameplay .rn-runner.lane-4 { left: 640px; }
.rn-page-gameplay .rn-runner.lane-5 { left: 760px; }
.rn-page-gameplay .rn-runner.lane-1.is-jump { top: 12px; }
/* หน้า finish */
.rn-page-finish .rn-runner.lane-1 { left: 900px; }
.rn-page-finish .rn-runner.lane-2 { left: 900px; }
.rn-page-finish .rn-runner.lane-3 { left: 900px; }
.rn-page-finish .rn-runner.lane-4 { left: 900px; }
.rn-page-finish .rn-runner.lane-5 { left: 200px; }
/* ---------- คะแนนหัก -10 (Mockup/03) ---------- */
.rn-penalty {
left: 560px;
top: 400px;
width: 144px;
height: 124px;
z-index: 7;
pointer-events: none;
}
.rn-penalty img {
width: 100%;
height: 100%;
object-fit: contain;
filter: drop-shadow(0 0 12px rgba(255, 80, 80, 0.65));
}
/* ---------- GAME OVER / MISSION COMPLETE overlay ---------- */
.rn-result-msg {
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 1001px;
height: 361px;
z-index: 6;
pointer-events: none;
}
.rn-result-msg img {
width: 100%;
height: 100%;
object-fit: contain;
}
@@ -0,0 +1,434 @@
/* =========================================================
summary.css – หน้า 06 สรุปผลภารกิจ
อ้างอิง Mockup/06.png + ขนาด asset จริง (1920×1080)
popup-result.png 1451×851 @ 234,114
popup-result-Line1 938×3
popup-result-Line2 4×270
player-frame.png 137×137
mission-complete-select 271×90
btn-done.png 351×141
card-5 (Bail Coin) 287×383
========================================================= */
.sm-overlay {
left: 0;
top: 0;
width: 1920px;
height: 1080px;
background: rgba(4, 6, 18, 0.45);
z-index: 9;
}
/* ---------- popup-result.png ---------- */
.sm-popup {
left: 234px;
top: 114px;
width: 1451px;
height: 851px;
z-index: 10;
}
.sm-popup img {
width: 100%;
height: 100%;
display: block;
}
/* ---------- content layer (พิกัดเดียวกับ popup) ---------- */
.sm-content {
left: 234px;
top: 114px;
width: 1451px;
height: 851px;
z-index: 11;
overflow: hidden;
}
/* =========================================================
แถวอันดับ 5 คน
mockup: 5 ช่อง × 137px + gap 30px กึ่งกลาง (ไม่ space-between)
รวมความกว้าง = 5×137 + 4×30 = 805px
========================================================= */
.sm-ranks {
position: absolute;
left: 323px;
top: 168px;
display: flex;
align-items: flex-start;
gap: 30px;
width: 805px;
}
.sm-rank {
flex: 0 0 137px;
width: 137px;
min-width: 137px;
text-align: center;
position: relative;
}
.sm-rank .pos {
display: block;
width: 41px;
height: 21px;
margin: 0 auto 6px;
object-fit: contain;
}
/* กรอบ avatar = player-frame.png เท่านั้น (สีตัวละครอยู่ใน portrait) */
.sm-rank .av {
position: relative;
width: 137px;
height: 137px;
margin: 0 auto 8px;
background: transparent;
overflow: visible;
}
.sm-rank .portrait {
position: absolute;
inset: 10px;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: transparent;
}
/* ตัวละคร placeholder — จัดกึ่งกลางในกรอบ 117×117 */
.sm-rank .chibi {
position: relative;
width: 86px;
height: 92px;
flex-shrink: 0;
}
.sm-rank .ch-body {
position: absolute;
left: 50%;
bottom: 0;
width: 86px;
height: 52px;
transform: translateX(-50%);
border-radius: 50%;
background: var(--body, #6a6f96);
box-shadow: inset 0 6px 8px rgba(255, 255, 255, 0.2);
}
.sm-rank .ch-head {
position: absolute;
left: 50%;
bottom: 34px;
width: 54px;
height: 54px;
transform: translateX(-50%);
border-radius: 50%;
background: var(--skin, #f5d6b3);
z-index: 2;
}
.sm-rank .ch-hair {
position: absolute;
left: 50%;
bottom: 52px;
width: 62px;
height: 36px;
transform: translateX(-50%);
border-radius: 50% 50% 16px 16px / 80% 80% 28% 28%;
background: var(--hair, #2a2a2a);
z-index: 3;
}
/* ทุกอันดับใช้ player-frame.png ตรง asset — ไม่ hue-rotate */
.sm-rank .av .frame {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 3;
pointer-events: none;
object-fit: contain;
}
/* ผู้เสียสละ — จางลง + stamp */
.sm-rank.is-out .av,
.sm-rank.is-out .portrait,
.sm-rank.is-out .chibi,
.sm-rank.is-out .ch-body,
.sm-rank.is-out .ch-head,
.sm-rank.is-out .ch-hair,
.sm-rank.is-out .av .frame {
filter: opacity(0.5);
}
.sm-rank .nm {
font-family: "NotoSansThai", sans-serif;
font-weight: 900;
font-size: 17px;
color: #ffffff;
letter-spacing: 0.6px;
line-height: 1.1;
margin-bottom: 2px;
}
.sm-rank .sc {
font-family: "NotoSansThai", sans-serif;
font-weight: 900;
font-size: 30px;
color: #ffffff;
text-shadow: 0 0 10px rgba(120, 220, 255, 0.4);
line-height: 1;
}
.sm-rank .sc .bonus {
font-size: 18px;
color: #ffd047;
margin-left: 2px;
text-shadow: 0 0 8px rgba(255, 200, 80, 0.45);
}
.sm-rank .av .stamp {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(-8deg);
width: 114px;
height: auto;
z-index: 5;
pointer-events: none;
}
/* =========================================================
คะแนนรวม
========================================================= */
.sm-total {
position: absolute;
left: 5px;
right: 0;
top: 398px;
z-index: 4;
text-align: center;
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 24px;
color: #ffd047;
text-shadow:
0 0 10px rgba(255, 200, 80, 0.45),
0 2px 4px rgba(0, 0, 0, 0.6);
letter-spacing: 0.3px;
line-height: 1.2;
}
.sm-total .num {
font-weight: 900;
font-size: 40px;
color: #ffffff;
text-shadow: 0 0 14px rgba(120, 220, 255, 0.55);
margin-left: 6px;
}
/* เส้นแนวนอน บน + ล่าง "คะแนนรวม" (popup-result-Line1.png 938×3) */
.sm-line-1 {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 938px;
height: 3px;
display: block;
object-fit: fill;
z-index: 4;
pointer-events: none;
}
.sm-line-above {
top: 394px;
}
.sm-line-below {
top: 452px;
}
/* =========================================================
โซนล่าง — ระดับความสำเร็จ | โบนัสพิเศษ (Mockup/06)
grid 3 คอลัมน์: 1fr | เส้น 4px | 1fr ภายใน padding 72px
========================================================= */
.sm-bottom {
position: absolute;
left: 72px;
right: 72px;
top: 460px;
height: 270px;
display: grid;
grid-template-columns: 1fr 4px 1fr;
align-items: start;
column-gap: 0;
pointer-events: none;
}
.sm-bottom > * {
pointer-events: auto;
}
.sm-col {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
text-align: center;
min-width: 0;
}
.sm-col-grade {
margin-left: 173px;
margin-right: 14px;
margin-top: 41px;
height: 174px;
vertical-align: top;
}
.sm-col .head {
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 1.2;
color: #ffffff;
margin: 0 0 12px;
padding: 0;
letter-spacing: 0.3px;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.sm-col-grade .head {
height: 40px;
font-size: 40px;
}
.sm-grade {
margin: 0;
padding: 7px 6px;
font-family: "NotoSansThai", sans-serif;
font-weight: 900;
font-size: 96px;
color: #ffffff;
text-shadow:
0 0 16px rgba(120, 220, 255, 0.65),
0 0 32px rgba(80, 180, 240, 0.4);
line-height: 0.95;
}
/* เส้นแบ่งแนวตั้ง (popup-result-Line2.png 4×270) */
.sm-vrule {
display: flex;
justify-content: center;
align-self: stretch;
height: 270px;
}
.sm-line-2 {
width: 4px;
height: 270px;
display: block;
object-fit: fill;
}
/* โบนัส: ซ้าย = หัวข้อ + ภารกิจสำเร็จ | ขวา = Bail Coin สูงเท่ากลุ่มซ้าย */
.sm-col-bonus {
align-items: center;
width: 486px;
}
.sm-bonus {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: center;
gap: 14px;
width: auto;
max-width: 100%;
margin-left: 0;
margin-right: 0;
}
.sm-bonus-left {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
gap: 8px;
width: 271px;
height: 272px;
flex-shrink: 0;
font-size: 15px;
padding-top: 42px;
padding-bottom: 42px;
vertical-align: middle;
}
.sm-bonus-left .head {
width: 100%;
height: 53px;
margin: 0;
text-align: left;
font-size: 40px;
line-height: 1.2;
padding-left: 23px;
padding-right: 23px;
}
.sm-bonus .complete {
display: block;
width: 271px;
height: 90px;
flex-shrink: 0;
object-fit: contain;
filter: drop-shadow(0 0 10px rgba(91, 255, 141, 0.45));
}
.sm-bonus-right {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
height: 258px;
}
.sm-bonus .bail-card {
display: block;
width: auto;
height: 258px;
max-width: 152px;
flex-shrink: 0;
object-fit: contain;
object-position: center center;
filter: drop-shadow(0 0 14px rgba(120, 220, 255, 0.55));
}
/* =========================================================
ปุ่ม "รับหลักฐาน" – กึ่งกลางจอ ทับขอบล่าง popup
========================================================= */
.sm-btn-done {
left: 784px;
top: 818px;
width: 351px;
height: 141px;
z-index: 12;
}
.sm-btn-done img {
width: 100%;
height: 100%;
display: block;
object-fit: contain;
filter: drop-shadow(0 0 14px rgba(120, 220, 255, 0.45));
}
.sm-btn-done.btn:hover {
transform: none;
filter: brightness(1.12) drop-shadow(0 0 18px rgba(120, 220, 255, 0.6));
}
.sm-btn-done.btn:active {
transform: none;
filter: brightness(0.95);
}
@@ -0,0 +1,26 @@
/**
* scale.js - ปรับขนาด .stage (1920x1080) ให้พอดี viewport
* รักษาอัตราส่วน 16:9 เสมอ (letterbox ถ้าจำเป็น)
*/
(function () {
const BASE_W = 1920;
const BASE_H = 1080;
function fit() {
const stage = document.querySelector(".stage");
if (!stage) return;
const vw = window.innerWidth;
const vh = window.innerHeight;
const scale = Math.min(vw / BASE_W, vh / BASE_H);
const scaledW = BASE_W * scale;
const scaledH = BASE_H * scale;
const tx = (vw - scaledW) / 2;
const ty = (vh - scaledH) / 2;
stage.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;
}
window.addEventListener("resize", fit);
window.addEventListener("orientationchange", fit);
document.addEventListener("DOMContentLoaded", fit);
window.addEventListener("load", fit);
})();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>05 Game Over · Minigame 2</title>
<meta name="viewport" content="width=1920, initial-scale=1">
<link rel="stylesheet" href="../assets/css/base.css">
<link rel="stylesheet" href="../assets/css/game-hud.css">
<link rel="stylesheet" href="../assets/css/runner.css">
</head>
<body>
<div class="stage-wrap">
<div class="stage mg-stage">
<div class="layer mg-bg">
<img src="../cut/BG-02-loop.png" alt="bg">
</div>
<div class="layer mg2-score-bar">
<img class="mg2-score-label" src="../cut/score.png" alt="SCORE :">
<div class="mg2-players">
<div class="mg2-player is-zero"><div class="nm">Mone</div><div class="av"></div><div class="sc">0</div></div>
<div class="mg2-player is-zero"><div class="nm">Jackson</div><div class="av"></div><div class="sc">0</div></div>
<div class="mg2-player is-zero"><div class="nm">Micky</div><div class="av"></div><div class="sc">0</div></div>
<div class="mg2-player is-zero"><div class="nm">Rainy</div><div class="av"></div><div class="sc">0</div></div>
<div class="mg2-player is-zero"><div class="nm">Jame</div><div class="av"></div><div class="sc">0</div></div>
</div>
</div>
<div class="layer mg-host">
<img class="mg-host-frame" src="../cut/Avartar.png" alt="">
<img class="mg-host-face" src="" alt="">
</div>
<div class="layer mg-mic"><img src="../cut/btn-mic_on.png" alt="mic"></div>
<div class="layer mg2-jump btn"><img src="../cut/btn-jump.png" alt="JUMP"></div>
<div class="layer rn-result-msg">
<img src="../cut/result-gameover.png" alt="GAME OVER">
</div>
</div>
</div>
<script src="../assets/js/scale.js"></script>
</body>
</html>
@@ -0,0 +1,176 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>07 สรุปผลภารกิจ · Minigame 2</title>
<meta name="viewport" content="width=1920, initial-scale=1">
<link rel="stylesheet" href="../assets/css/base.css">
<link rel="stylesheet" href="../assets/css/game-hud.css">
<link rel="stylesheet" href="../assets/css/summary.css">
</head>
<body>
<div class="stage-wrap">
<div class="stage mg-stage">
<div class="layer mg-bg">
<img src="../cut/BG-05-finish.png" alt="bg">
</div>
<div class="layer mg2-score-bar">
<img class="mg2-score-label" src="../cut/score.png" alt="SCORE :">
<div class="mg2-players">
<div class="mg2-player"><div class="nm">Mone</div><div class="av"></div><div class="sc">80</div></div>
<div class="mg2-player is-zero"><div class="nm">Jackson</div><div class="av"></div><div class="sc">0</div></div>
<div class="mg2-player is-zero"><div class="nm">Micky</div><div class="av"></div><div class="sc">0</div></div>
<div class="mg2-player"><div class="nm">Rainy</div><div class="av"></div><div class="sc">80</div></div>
<div class="mg2-player"><div class="nm">Jame</div><div class="av"></div><div class="sc">60</div></div>
</div>
</div>
<div class="layer mg-host">
<img class="mg-host-frame" src="../cut/Avartar.png" alt="">
<img class="mg-host-face" src="" alt="">
</div>
<div class="layer mg-mic"><img src="../cut/btn-mic_on.png" alt="mic"></div>
<div class="layer mg2-jump btn"><img src="../cut/btn-jump.png" alt="JUMP"></div>
<div class="layer sm-overlay"></div>
<div class="layer sm-popup">
<img src="../cut/popup-result.png" alt="สรุปผลภารกิจ">
</div>
<div class="layer sm-content">
<div class="sm-ranks">
<div class="sm-rank is-1st" style="--bg:#ffd96b; --hair:#3a2210; --body:#e09f2a; --skin:#f5d6b3;">
<img class="pos" src="../cut/result-1st.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">JACKSON</div>
<div class="sc">80<span class="bonus">(+100)</span></div>
</div>
<div class="sm-rank is-2nd" style="--bg:#f5b9c8; --hair:#ec5fa0; --body:#ffffff; --skin:#f7d8c2;">
<img class="pos" src="../cut/result-2nd.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">MONE</div>
<div class="sc">80<span class="bonus">(+100)</span></div>
</div>
<div class="sm-rank is-3rd" style="--bg:#ff7b7b; --hair:#c8252a; --body:#9b1f23; --skin:#f5cba7;">
<img class="pos" src="../cut/result-3rd.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">RAINY</div>
<div class="sc">120</div>
</div>
<div class="sm-rank is-out" style="--bg:#7e84d1; --hair:#2a3580; --body:#3848a8; --skin:#f5d6b3;">
<img class="pos" src="../cut/result-txt-1.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
<img class="stamp" src="../cut/result-Lose_stamp.png" alt="">
</div>
<div class="nm">MICKY</div>
<div class="sc">0</div>
</div>
<div class="sm-rank is-out" style="--bg:#85d28a; --hair:#216a2c; --body:#2f8a4a; --skin:#f5d6b3;">
<img class="pos" src="../cut/result-txt-2.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
<img class="stamp" src="../cut/result-Lose_stamp.png" alt="">
</div>
<div class="nm">JAME</div>
<div class="sc">0</div>
</div>
</div>
<img class="sm-line sm-line-1 sm-line-above" src="../cut/popup-result-Line1.png" alt="">
<div class="sm-total">
คะแนนรวม (180+180+120+0+0) =<span class="num">480</span>
</div>
<img class="sm-line sm-line-1 sm-line-below" src="../cut/popup-result-Line1.png" alt="">
<div class="sm-bottom">
<section class="sm-col sm-col-grade">
<h3 class="head">ระดับความสำเร็จ</h3>
<p class="sm-grade" aria-label="เกรด B">B</p>
</section>
<div class="sm-vrule" aria-hidden="true">
<img class="sm-line-2" src="../cut/popup-result-Line2.png" alt="">
</div>
<section class="sm-col sm-col-bonus">
<div class="sm-bonus">
<div class="sm-bonus-left">
<h3 class="head">โบนัสพิเศษ</h3>
<img class="complete" src="../cut/mission-complete-select.png" alt="ภารกิจสำเร็จ">
</div>
<div class="sm-bonus-right">
<img class="bail-card" src="../../cut/10-Game-1-result/card-5.png" alt="Bail Coin">
</div>
</div>
</section>
</div>
</div>
<div class="layer sm-btn-done btn" id="smBtnDone">
<img src="../cut/btn-done.png" alt="รับหลักฐาน">
</div>
</div>
</div>
<script src="../assets/js/scale.js"></script>
<script>
document.getElementById('smBtnDone')?.addEventListener('click', () => {
alert('รับหลักฐาน (mockup)');
});
</script>
</body>
</html>
@@ -0,0 +1,103 @@
/* =========================================================
Base CSS Minigame-3
Base resolution : 1920 x 1080 (16:9)
========================================================= */
@font-face {
font-family: "NotoSansThai";
src: url("../../Fonts/NotoSansThai-Medium.ttf") format("truetype");
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "NotoSansThai";
src: url("../../Fonts/NotoSansThai-Bold.ttf") format("truetype");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "NotoSansThai";
src: url("../../Fonts/NotoSansThai-Black.ttf") format("truetype");
font-weight: 900;
font-style: normal;
font-display: swap;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
width: 100%;
height: 100%;
background: #050813;
color: #ffffff;
font-family: "NotoSansThai", "Segoe UI", sans-serif;
overflow: hidden;
user-select: none;
-webkit-font-smoothing: antialiased;
}
img {
display: block;
pointer-events: none;
-webkit-user-drag: none;
}
/* ---------- 1920x1080 Stage ---------- */
.stage-wrap {
position: fixed;
inset: 0;
background: #050813;
overflow: hidden;
}
.stage {
position: absolute;
left: 0;
top: 0;
width: 1920px;
height: 1080px;
transform-origin: 0 0;
transform: scale(0.5);
}
/* ทุก element ภายใน stage ใช้พิกัด/ขนาดเป็น px ของ 1920x1080 */
.layer {
position: absolute;
}
/* placeholder กรอบกำกับช่องที่ยังไม่มี PNG */
.placeholder {
position: absolute;
border: 2px dashed rgba(255, 255, 255, 0.2);
border-radius: 10px;
color: rgba(255, 255, 255, 0.4);
font-size: 14px;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
background: rgba(255, 255, 255, 0.03);
pointer-events: none;
}
/* ปุ่มคลิกได้ */
.btn {
cursor: pointer;
transition: transform 0.15s ease, filter 0.15s ease;
}
.btn:hover {
filter: brightness(1.18) drop-shadow(0 0 14px rgba(120, 220, 255, 0.55));
transform: translateY(-2px);
}
.btn:active {
transform: translateY(1px);
filter: brightness(0.95);
}
@@ -0,0 +1,433 @@
/* =========================================================
game-hud.css Shared HUD สำหรับทุกหน้า in-game
• Top-left : SCORE panel (score-bar.png + 5 players)
• Top-center: TIME counter
• Top-right : Host avatar frame + mic button
• Background: BG.png (1920x1080)
========================================================= */
.mg-stage {
background: #04050d;
}
/* ---------------- พื้นหลัง BG เต็มจอ ---------------- */
.mg-bg {
left: 0;
top: 0;
width: 1920px;
height: 1080px;
z-index: 1;
}
.mg-bg img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* =========================================================
มุมซ้ายบน : SCORE Panel (score-bar.png + 5 players)
========================================================= */
.mg-score-panel {
left: 2px;
top: 16px;
width: 156px;
height: 433px;
padding: 0;
overflow: hidden;
background: url("../../cut/score-bar.png") no-repeat left top / 156px 433px;
border: none;
border-radius: 0;
box-shadow: none;
z-index: 8;
}
.mg-score-title {
/* ข้อความ SCORE อยู่ใน score-bar.png แล้ว */
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.mg-score-list {
position: absolute;
left: 16px;
top: 60px;
width: 136px;
display: flex;
flex-direction: column;
gap: 5px;
}
.mg-score-row {
display: flex;
align-items: center;
gap: 10px;
height: 70px;
}
.mg-score-row .av {
position: relative;
width: 70px;
height: 70px;
flex: 0 0 70px;
border-radius: 0;
overflow: visible;
background: transparent;
}
.mg-score-row .av::after {
content: "";
position: absolute;
inset: 0;
background: url("../../cut/score-avartar.png") no-repeat center / contain;
pointer-events: none;
z-index: 2;
}
.mg-score-row .av img {
position: absolute;
inset: 4px;
width: calc(100% - 8px);
height: calc(100% - 8px);
object-fit: cover;
border-radius: 6px;
z-index: 1;
}
/* ไม่ใช้ placeholder สี — แสดงเฉพาะกรอบ score-avartar.png (หรือรูปใน <img>) */
.mg-score-row .av .ph {
display: none;
}
.mg-score-row .meta {
display: flex;
flex-direction: column;
gap: 1px;
line-height: 1.05;
flex: 1;
min-width: 0;
}
.mg-score-row .nm {
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 11px;
color: #e8f4ff;
letter-spacing: 0.2px;
text-transform: uppercase;
white-space: nowrap;
}
.mg-score-row .sc {
font-family: "NotoSansThai", sans-serif;
font-weight: 900;
font-size: 22px;
color: #ffffff;
line-height: 1;
text-shadow: 0 0 8px rgba(120, 220, 255, 0.6);
}
/* =========================================================
ตรงกลางบน : TIME : XX
========================================================= */
.mg-time {
left: 50%;
top: 23px;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 10px;
z-index: 8;
}
.mg-time-label {
width: 131px;
height: 71px;
flex: 0 0 131px;
}
.mg-time .num {
font-family: "NotoSansThai", sans-serif;
font-weight: 900;
font-size: 42px;
height: 71px;
line-height: 71px;
color: #e6f6ff;
letter-spacing: 1px;
font-variant-numeric: tabular-nums;
text-shadow:
0 0 10px rgba(120, 220, 255, 0.85),
0 0 22px rgba(80, 180, 240, 0.55);
}
.mg-time.is-warning .num {
color: #ff7a7a;
text-shadow:
0 0 12px rgba(255, 90, 90, 0.85),
0 0 24px rgba(255, 60, 60, 0.5);
}
.mg-time.is-warning {
animation: mg-pulse 0.9s ease-in-out infinite;
}
@keyframes mg-pulse {
0%, 100% { transform: translateX(-50%) scale(1); }
50% { transform: translateX(-50%) scale(1.08); }
}
/* =========================================================
มุมขวาบน : Host avatar (Avartar.png) + mic
========================================================= */
.mg-host {
left: 1729px;
top: 21px;
width: 201px;
height: 201px;
z-index: 8;
}
.mg-host-frame {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 2;
pointer-events: none;
}
.mg-host-face {
position: absolute;
left: 49px;
top: 49px;
width: 104px;
height: 104px;
border-radius: 8px;
object-fit: cover;
z-index: 1;
}
.mg-host-face:not([src]),
.mg-host-face[src=""] {
display: none;
}
.mg-host .host-ph {
display: none;
}
.mg-mic {
left: 1796px;
top: 205px;
width: 121px;
height: 121px;
z-index: 8;
}
.mg-mic img {
width: 100%;
height: 100%;
}
@@ -0,0 +1,120 @@
.pg-result { left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 6; pointer-events: none; }
.pg-result img { max-width: 1001px; width: 100%; height: auto; }
.pg-countdown { left: 50%; top: 420px; transform: translate(-50%, -50%); font-weight: 900; font-size: 220px; color: #ffd93d; -webkit-text-stroke: 6px #1a1208; text-shadow: 0 0 24px rgba(255,210,60,.85); z-index: 6; }
.sm-overlay { left: 0; top: 0; width: 1920px; height: 1080px; background: rgba(4,6,18,.45); z-index: 9; }
.sm-popup { left: 234px; top: 114px; width: 1451px; height: 851px; z-index: 10; }
.sm-popup img { width: 100%; height: 100%; }
.sm-btn-done { left: 784px; top: 818px; width: 351px; height: 141px; z-index: 12; }
.sm-btn-done img { width: 100%; height: 100%; }
.mg3-drop { left: 1648px; top: 818px; width: 231px; height: 231px; z-index: 8; }
.mg3-drop img { width: 100%; height: 100%; }
.mg3-life {
left: 1410px;
top: 63px;
width: 341px;
height: 111px;
z-index: 8;
}
.mg3-life .life-bar {
width: 341px;
height: 111px;
display: block;
}
.mg3-life .life-hearts {
position: absolute;
left: 83px;
top: 56px;
display: flex;
align-items: center;
gap: 10px;
height: 52px;
}
.mg3-life .life-hearts img {
width: 52px;
height: 52px;
display: block;
flex: 0 0 52px;
}
.mg3-progress {
left: 43px;
bottom: 40px;
width: 418px;
height: 151px;
z-index: 8;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 0px;
vertical-align: bottom;
text-align: left;
}
.mg3-progress .progress-heading {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
flex: 0 0 75%;
gap: 3px;
}
.mg3-progress .progress-label {
width: auto;
height: 58px;
display: block;
flex: 0 0 auto;
vertical-align: middle;
}
.mg3-progress .progress-pct {
font-family: "NotoSansThai", monospace, sans-serif;
font-weight: 700;
font-size: 28px;
line-height: 44px;
color: #8fe8ff;
letter-spacing: 0.5px;
white-space: nowrap;
text-shadow: 0 0 8px rgba(120, 220, 255, 0.6);
}
.mg3-progress .progress-bar {
position: relative;
width: 100%;
flex: 0 0 100%;
}
.mg3-progress .progress-track {
width: 100%;
height: auto;
display: block;
}
.mg3-progress .progress-fill {
position: absolute;
left: 30px;
top: 30px;
/* height: 100%; */
/* width: 50px; */
height: 50px;
object-fit: cover;
object-position: left center;
}
.mg3-progress img:not(.progress-label):not(.progress-track):not(.progress-fill) {
width: 100%;
height: auto;
}
.mg3-terminal { left: 40px; bottom: 170px; width: 420px; z-index: 5; }
.mg3-terminal img { width: 100%; height: auto; }
.mg3-sling { display: none; width: 800px; z-index: 4; }
.mg3-sling img { width: 100%; height: auto; }
.mg3-fx { position: absolute; z-index: 7; pointer-events: none; }
.mg3-fx.score20 { left: 55%; top: 35%; width: 120px; }
.mg3-fx.scorex2 { left: 62%; top: 30%; width: 100px; }
.mg3-fx img { width: 100%; height: auto; }
@@ -0,0 +1,80 @@
/* =========================================================
howto.css หน้า 01 + 01-2 (HOW TO PLAY popup)
ใช้ popup-Howto.png เป็น content หลัก
+ ปุ่ม READY/START และ status text ใต้ popup
========================================================= */
/* ---------- dark overlay ทับ BG ---------- */
.mg-overlay {
left: 0;
top: 0;
width: 1920px;
height: 1080px;
background: rgba(4, 6, 18, 0.45);
z-index: 9;
}
/* ---------- popup HOW TO PLAY ---------- */
.howto-popup {
/* popup-Howto.png native 1451x851 (aspect 1.706)
ใน mockup กินพื้นที่เกือบทั้งจอ → ขยายให้ใหญ่ขึ้น แต่ยังคง aspect ratio */
left: 50%;
top: 50px;
transform: translateX(-50%);
width: 1500px;
height: 880px;
z-index: 10;
}
.howto-popup img {
width: 100%;
height: 100%;
}
/* ---------- ปุ่ม READY/START + status text ---------- */
.howto-status {
/* "Ready Status : 4/5" อยู่เหนือปุ่ม READY (ตาม mockup 01.png) */
left: 50%;
top: 808px;
transform: translateX(-50%);
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 22px;
color: #f067e8;
text-shadow: 0 0 10px rgba(240, 103, 232, 0.6),
0 0 22px rgba(237, 86, 224, 0.35);
letter-spacing: 0.5px;
text-align: center;
z-index: 13;
white-space: nowrap;
pointer-events: none;
}
.howto-status #hwRatio {
color: #f067e8;
}
.howto-btn {
/* btn-ready.png / btn-start.png native 351x141 (aspect 2.49)
ใน mockup ปุ่มอยู่ตรงเส้นกรอบล่าง popup (กึ่งกลาง) */
left: 957px;
top: 885px;
transform: translate(-50%, -50%);
height: 120px;
width: auto;
z-index: 12;
}
.howto-btn img {
height: 100%;
width: auto;
filter: drop-shadow(0 0 18px rgba(120, 220, 255, 0.65));
}
/* ---------- hover effect บนปุ่ม ---------- */
.howto-btn.btn:hover {
transform: translate(-50%, calc(-50% - 3px));
}
.howto-btn.btn:hover img {
filter: drop-shadow(0 0 28px rgba(120, 220, 255, 0.95));
}
.howto-btn.btn:active {
transform: translate(-50%, calc(-50% + 2px));
}
@@ -0,0 +1,170 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>08 · สรุปผลภารกิจ</title>
<meta name="viewport" content="width=1920, initial-scale=1">
<link rel="stylesheet" href="../assets/css/base.css">
<link rel="stylesheet" href="../assets/css/game-hud.css">
<link rel="stylesheet" href="../assets/css/summary.css">
<link rel="stylesheet" href="../assets/css/game.css">
</head>
<body>
<div class="stage-wrap">
<div class="stage mg-stage ">
<div class="layer mg-bg"><img src="../cut/BG-loop.png" alt="bg"></div>
<div class="layer mg-score-panel">
<div class="mg-score-title">SCORE</div>
<div class="mg-score-list">
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MONE</span><span class="sc">200</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JACKSON</span><span class="sc">180</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MICKY</span><span class="sc">160</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">RAINY</span><span class="sc">190</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JAME</span><span class="sc">150</span></div></div>
</div>
</div>
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">0</span>
</div>
<div class="layer mg-host">
<img class="mg-host-frame" src="../cut/Avartar.png" alt="">
<img class="mg-host-face" src="" alt="">
</div>
<div class="layer mg-mic"><img src="../cut/btn-mic_on.png" alt="mic"></div>
<div class="layer sm-overlay"></div>
<div class="layer sm-popup">
<img src="../cut/popup-result.png" alt="สรุปผลภารกิจ">
</div>
<div class="layer sm-content">
<div class="sm-ranks">
<div class="sm-rank is-1st" style="--bg:#ffd96b; --hair:#3a2210; --body:#e09f2a; --skin:#f5d6b3;">
<img class="pos" src="../cut/result-1st.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">JACKSON</div>
<div class="sc">100</div>
</div>
<div class="sm-rank is-2nd" style="--bg:#f5b9c8; --hair:#ec5fa0; --body:#ffffff; --skin:#f7d8c2;">
<img class="pos" src="../cut/result-2nd.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">MONE</div>
<div class="sc">100</div>
</div>
<div class="sm-rank is-3rd" style="--bg:#ff7b7b; --hair:#c8252a; --body:#9b1f23; --skin:#f5cba7;">
<img class="pos" src="../cut/result-3rd.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">MICKY</div>
<div class="sc">100</div>
</div>
<div class="sm-rank is-4th" style="--bg:#7e84d1; --hair:#2a3580; --body:#3848a8; --skin:#f5d6b3;">
<img class="pos" src="../cut/result-txt-1.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">RAINY</div>
<div class="sc">90</div>
</div>
<div class="sm-rank is-5th" style="--bg:#85d28a; --hair:#216a2c; --body:#2f8a4a; --skin:#f5d6b3;">
<img class="pos" src="../cut/result-txt-2.png" alt="">
<div class="av">
<div class="portrait">
<div class="chibi">
<div class="ch-body"></div>
<div class="ch-head"></div>
<div class="ch-hair"></div>
</div>
</div>
<img class="frame" src="../cut/player-frame.png" alt="">
</div>
<div class="nm">JAME</div>
<div class="sc">90</div>
</div>
</div>
<img class="sm-line sm-line-1 sm-line-above" src="../cut/popup-result-Line1.png" alt="">
<div class="sm-total">
คะแนนรวม (100+100+100+90+90) =<span class="num">480</span>
</div>
<img class="sm-line sm-line-1 sm-line-below" src="../cut/popup-result-Line1.png" alt="">
<div class="sm-bottom">
<section class="sm-col sm-col-grade">
<h3 class="head">ระดับความสำเร็จ</h3>
<p class="sm-grade" aria-label="เกรด A">A</p>
</section>
<div class="sm-vrule" aria-hidden="true">
<img class="sm-line-2" src="../cut/popup-result-Line2.png" alt="">
</div>
<section class="sm-col sm-col-bonus">
<div class="sm-bonus">
<div class="sm-bonus-left">
<h3 class="head">โบนัสพิเศษ</h3>
<img class="complete" src="../cut/mission-complete-select.png" alt="ภารกิจสำเร็จ">
</div>
<div class="sm-bonus-right">
<img class="bail-card" src="../../cut/10-Game-1-result/card-5.png" alt="Bail Coin">
</div>
</div>
</section>
</div>
</div>
<div class="layer sm-btn-done btn" id="smBtnDone"><img src="../cut/btn-done.png" alt="รับหลักฐาน"></div>
</div>
</div>
<script src="../assets/js/scale.js"></script>
<script>
document.getElementById('smBtnDone')?.addEventListener('click', () => {
alert('รับหลักฐาน (mockup)');
});
</script>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>01-2 · Host START</title>
<meta name="viewport" content="width=1920, initial-scale=1">
<link rel="stylesheet" href="../assets/css/base.css">
<link rel="stylesheet" href="../assets/css/game-hud.css">
<link rel="stylesheet" href="../assets/css/game.css">
<link rel="stylesheet" href="../assets/css/howto.css">
</head>
<body>
<div class="stage-wrap">
<div class="stage mg-stage ">
<div class="layer mg-bg"><img src="../cut/BG-1.png" alt="bg"></div>
<div class="layer mg-score-panel">
<div class="mg-score-title">SCORE</div>
<div class="mg-score-list">
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MONE</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JACKSON</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MICKY</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">RAINY</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JAME</span><span class="sc">20</span></div></div>
</div>
</div>
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">60</span>
</div>
<div class="layer mg-host">
<img class="mg-host-frame" src="../cut/Avartar.png" alt="">
<img class="mg-host-face" src="" alt="">
</div>
<div class="layer mg-mic"><img src="../cut/btn-mic_on.png" alt="mic"></div>
<div class="layer mg-overlay"></div>
<div class="layer howto-popup"><img src="../cut/popup-Howto.png" alt="HOW TO PLAY"></div>
<div class="layer howto-status" id="hwStatus">กำลังรอ..ผู้เล่นกด Ready : <span>3/4</span></div>
<div class="layer howto-btn btn" id="hwBtn">
<img id="hwBtnImg" src="../cut/btn-start.png" alt="START">
</div>
</div>
</div>
<script src="../assets/js/scale.js"></script>
<script>
(function(){
const btn=document.getElementById('hwBtn'), img=document.getElementById('hwBtnImg'), status=document.getElementById('hwStatus');
if(!btn) return;
let isStart=false;
btn.addEventListener('click',()=>{
isStart=!isStart;
if(isStart){ img.src='../cut/btn-start.png'; img.alt='START'; status.innerHTML='กำลังรอ..ผู้เล่นกด Ready : <span>3/4</span>'; }
else { img.src='../cut/btn-ready.png'; img.alt='READY'; status.innerHTML='Ready Status : <span>4/5</span>'; }
});
})();
</script>
</body>
</html>
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>02 · Countdown</title>
<meta name="viewport" content="width=1920, initial-scale=1">
<link rel="stylesheet" href="../assets/css/base.css">
<link rel="stylesheet" href="../assets/css/game-hud.css">
<link rel="stylesheet" href="../assets/css/game.css">
</head>
<body>
<div class="stage-wrap">
<div class="stage mg-stage ">
<div class="layer mg-bg"><img src="../cut/BG-1.png" alt="bg"></div>
<div class="layer mg-score-panel">
<div class="mg-score-title">SCORE</div>
<div class="mg-score-list">
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MONE</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JACKSON</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MICKY</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">RAINY</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JAME</span><span class="sc">20</span></div></div>
</div>
</div>
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">60</span>
</div>
<div class="layer mg-host">
<img class="mg-host-frame" src="../cut/Avartar.png" alt="">
<img class="mg-host-face" src="" alt="">
</div>
<div class="layer mg-mic"><img src="../cut/btn-mic_on.png" alt="mic"></div>
<div class="layer pg-countdown">3</div><div class="layer mg6-rocket r1"><img src="../cut/Rocket-1.png" alt=""></div><div class="layer mg6-rocket r2"><img src="../cut/Rocket-2.png" alt=""></div><div class="layer mg6-rocket r3"><img src="../cut/Rocket-3.png" alt=""></div><div class="layer mg6-rocket r4"><img src="../cut/Rocket-4.png" alt=""></div><div class="layer mg6-rocket r5"><img src="../cut/Rocket-5.png" alt=""></div>
</div>
</div>
<script src="../assets/js/scale.js"></script>
</body>
</html>
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>03 · Gameplay</title>
<meta name="viewport" content="width=1920, initial-scale=1">
<link rel="stylesheet" href="../assets/css/base.css">
<link rel="stylesheet" href="../assets/css/game-hud.css">
<link rel="stylesheet" href="../assets/css/game.css">
</head>
<body>
<div class="stage-wrap">
<div class="stage mg-stage ">
<div class="layer mg-bg"><img src="../cut/BG-2_Loop.png" alt="bg"></div>
<div class="layer mg-score-panel">
<div class="mg-score-title">SCORE</div>
<div class="mg-score-list">
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MONE</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JACKSON</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">MICKY</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">RAINY</span><span class="sc">20</span></div></div>
<div class="mg-score-row"><div class="av"></div><div class="meta"><span class="nm">JAME</span><span class="sc">20</span></div></div>
</div>
</div>
<div class="layer mg-time">
<img class="mg-time-label" src="../cut/time.png" alt="TIME :">
<span class="num">60</span>
</div>
<div class="layer mg-host">
<img class="mg-host-frame" src="../cut/Avartar.png" alt="">
<img class="mg-host-face" src="" alt="">
</div>
<div class="layer mg-mic"><img src="../cut/btn-mic_on.png" alt="mic"></div>
<div class="layer mg6-rocket r1"><img src="../cut/Rocket-1.png" alt=""></div><div class="layer mg6-rocket r2"><img src="../cut/Rocket-2.png" alt=""></div><div class="layer mg6-rocket r3"><img src="../cut/Rocket-3.png" alt=""></div><div class="layer mg6-rocket r4"><img src="../cut/Rocket-4.png" alt=""></div><div class="layer mg6-rocket r5"><img src="../cut/Rocket-5.png" alt=""></div><div class="layer mg6-meteo m1"><img src="../cut/Meteo-1.png" alt=""></div><div class="layer mg6-meteo m2"><img src="../cut/Meteo-2.png" alt=""></div>
</div>
</div>
<script src="../assets/js/scale.js"></script>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 32 KiB