minigame 2 just begin1.1

This commit is contained in:
2026-04-30 16:10:12 +00:00
parent 2ad5401d28
commit 001d46f76d
3 changed files with 69 additions and 33 deletions
+34 -16
View File
@@ -17,6 +17,8 @@
/** สรุปภารกิจแบบ mock (popup-result ฯลฯ) — ใช้เฉพาะฉากนี้จาก editor (id ใน URL เช่น editor.html?id=mnorwqx1) */
const quizCarryMissionSummaryMapId = 'mnorwqx1';
const quizCarryUseMissionSummaryOverlay = playMapIdFromQuery === quizCarryMissionSummaryMapId;
/** Gauntlet พรมแดง — ฉากนี้จาก editor (?map=mno9kb07): วาดตัวหันขวา + ใช้รูป lane/laser จาก game-timing */
const GAUNTLET_FACE_RIGHT_MAP_ID = 'mno9kb07';
/** จนกว่าโหลด /api/characters — placeholder ชั่วคราวก่อน join */
const LEGACY_PLACEHOLDER_CHARACTER_ID = 'Chatest';
let firstCharacterDefaultResolved = null;
@@ -699,8 +701,23 @@
let gauntletLaserLineWidthPx = 2;
const gauntletAssetImageCache = new Map();
/** แปลง URL จาก Admin/game-timing ให้โหลดได้ (nginx เสิร์ฟจาก /Game/...) */
function normalizeGauntletAssetUrlForPlay(u) {
if (typeof u !== 'string') return '';
const t = u.trim();
if (!t) return '';
if (/^https?:\/\//i.test(t)) return t;
const qIdx = t.indexOf('?');
const base = (qIdx >= 0 ? t.slice(0, qIdx) : t).trim();
const qs = qIdx >= 0 ? t.slice(qIdx) : '';
if (!base) return '';
if (base.startsWith('/')) return base + qs;
if (/^Game\//i.test(base)) return '/' + base.replace(/^\/+/, '') + qs;
return base + qs;
}
function ensureGauntletAssetImage(url) {
const u = typeof url === 'string' ? url.trim() : '';
const u = normalizeGauntletAssetUrlForPlay(typeof url === 'string' ? url : '');
if (!u) return null;
let rec = gauntletAssetImageCache.get(u);
if (rec) return rec;
@@ -2423,6 +2440,9 @@
function isFrogger() { return mapData && mapData.gameType === 'frogger'; }
function isGauntlet() { return mapData && mapData.gameType === 'gauntlet'; }
function isGauntletFaceRightMapMno9kb07() {
return !!(isGauntlet() && playMapIdFromQuery === GAUNTLET_FACE_RIGHT_MAP_ID);
}
function isStack() { return mapData && mapData.gameType === 'stack'; }
function isJumpSurvive() { return mapData && mapData.gameType === 'jump_survive'; }
function isSpaceShooter() { return mapData && mapData.gameType === 'space_shooter'; }
@@ -4873,19 +4893,23 @@
}
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaneImageUrls') && Array.isArray(payload.gauntletLaneImageUrls)) {
gauntletLaneImageUrls = payload.gauntletLaneImageUrls.filter((x) => typeof x === 'string').slice(0, 24);
gauntletLaneImageUrls = payload.gauntletLaneImageUrls
.filter((x) => typeof x === 'string')
.map((x) => normalizeGauntletAssetUrlForPlay(x))
.filter((x) => x)
.slice(0, 24);
gauntletLaneImageUrls.forEach((x) => ensureGauntletAssetImage(x));
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserTopUrl')) {
gauntletLaserTopUrl = typeof payload.gauntletLaserTopUrl === 'string' ? payload.gauntletLaserTopUrl : '';
gauntletLaserTopUrl = normalizeGauntletAssetUrlForPlay(typeof payload.gauntletLaserTopUrl === 'string' ? payload.gauntletLaserTopUrl : '');
ensureGauntletAssetImage(gauntletLaserTopUrl);
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserBottomUrl')) {
gauntletLaserBottomUrl = typeof payload.gauntletLaserBottomUrl === 'string' ? payload.gauntletLaserBottomUrl : '';
gauntletLaserBottomUrl = normalizeGauntletAssetUrlForPlay(typeof payload.gauntletLaserBottomUrl === 'string' ? payload.gauntletLaserBottomUrl : '');
ensureGauntletAssetImage(gauntletLaserBottomUrl);
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserLineUrl')) {
gauntletLaserLineUrl = typeof payload.gauntletLaserLineUrl === 'string' ? payload.gauntletLaserLineUrl : '';
gauntletLaserLineUrl = normalizeGauntletAssetUrlForPlay(typeof payload.gauntletLaserLineUrl === 'string' ? payload.gauntletLaserLineUrl : '');
ensureGauntletAssetImage(gauntletLaserLineUrl);
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserFillColor')) {
@@ -9069,7 +9093,7 @@
if (portrait) {
const cid = me.characterId || getPlayCharacterId();
const dir = me.direction || 'down';
const dir = (isGauntletFaceRightMapMno9kb07() ? 'right' : (me.direction || 'down'));
const nowT = Date.now();
const walk = !!me.isWalking;
const rawImg = getAvatarImg(cid, dir, nowT, walk);
@@ -9665,17 +9689,9 @@
ctx.fillStyle = '#f7768e';
ctx.fillRect(sx + 2, sy + 2, size - 4, size - 4);
}
ctx.strokeStyle = '#ff9ebc';
ctx.lineWidth = 2;
ctx.strokeRect(sx + 2, sy + 2, size - 4, size - 4);
ctx.lineWidth = 1;
} else {
ctx.fillStyle = '#f7768e';
ctx.fillRect(sx + 2, sy + 2, size - 4, size - 4);
ctx.strokeStyle = '#ff9ebc';
ctx.lineWidth = 2;
ctx.strokeRect(sx + 2, sy + 2, size - 4, size - 4);
ctx.lineWidth = 1;
}
} else if (o.kind === 'laser' && typeof o.drawX === 'number') {
if (o.drawX < stx - 2 || o.drawX > enx + 2) continue;
@@ -9882,16 +9898,18 @@
? !!o.botIsWalking
: !!((o.tx != null && Math.abs((o.tx || o.x) - o.x) > 0.02) || (o.ty != null && Math.abs((o.ty || o.y) - o.y) > 0.02)));
const ot = o.playTint || playTintFromPeerId(id);
const faceDirOther = isGauntletFaceRightMapMno9kb07() ? 'right' : o.direction;
const botOut = isJumpSurvive() && isPreviewBotId(id) && o.jumpSurviveEliminated;
const peerName = botOut ? (o.nickname + ' (ตกรอบ)') : o.nickname;
if (botOut) ctx.save();
if (botOut) ctx.globalAlpha = 0.4;
drawAvatar(safeX(o.x) + off.ax, safeY(o.y) + off.ay, false, peerName, o.characterId, o.direction, otherWalk, ot, (o.gauntletJumpVis != null ? o.gauntletJumpVis : o.gauntletJumpTicks) || 0, o.gauntletScore || 0, quizCarrySignForEntity(o));
drawAvatar(safeX(o.x) + off.ax, safeY(o.y) + off.ay, false, peerName, o.characterId, faceDirOther, otherWalk, ot, (o.gauntletJumpVis != null ? o.gauntletJumpVis : o.gauntletJumpTicks) || 0, o.gauntletScore || 0, quizCarrySignForEntity(o));
if (botOut) ctx.restore();
} else {
if (isJumpSurvive() && jumpSurviveEliminated) ctx.save();
if (isJumpSurvive() && jumpSurviveEliminated) ctx.globalAlpha = 0.4;
drawAvatar(safeX(me.x), safeY(me.y), true, me.nickname + meTag, me.characterId, me.direction, meWalking, mt, meGauntletJumpVis, me.gauntletScore || 0, quizCarrySignForEntity(me));
const faceDirMe = isGauntletFaceRightMapMno9kb07() ? 'right' : me.direction;
drawAvatar(safeX(me.x), safeY(me.y), true, me.nickname + meTag, me.characterId, faceDirMe, meWalking, mt, meGauntletJumpVis, me.gauntletScore || 0, quizCarrySignForEntity(me));
if (isJumpSurvive() && jumpSurviveEliminated) ctx.restore();
}
});
+1 -1
View File
@@ -1462,7 +1462,7 @@
</div>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0166"></script>
<script src="js/play.js?v=0.182"></script>
<script src="js/play.js?v=0.184"></script>
<div class="version-tag">v —</div>
</body>
</html>
+34 -16
View File
@@ -17,6 +17,8 @@
/** สรุปภารกิจแบบ mock (popup-result ฯลฯ) — ใช้เฉพาะฉากนี้จาก editor (id ใน URL เช่น editor.html?id=mnorwqx1) */
const quizCarryMissionSummaryMapId = 'mnorwqx1';
const quizCarryUseMissionSummaryOverlay = playMapIdFromQuery === quizCarryMissionSummaryMapId;
/** Gauntlet พรมแดง — ฉากนี้จาก editor (?map=mno9kb07): วาดตัวหันขวา + ใช้รูป lane/laser จาก game-timing */
const GAUNTLET_FACE_RIGHT_MAP_ID = 'mno9kb07';
/** จนกว่าโหลด /api/characters — placeholder ชั่วคราวก่อน join */
const LEGACY_PLACEHOLDER_CHARACTER_ID = 'Chatest';
let firstCharacterDefaultResolved = null;
@@ -699,8 +701,23 @@
let gauntletLaserLineWidthPx = 2;
const gauntletAssetImageCache = new Map();
/** แปลง URL จาก Admin/game-timing ให้โหลดได้ (nginx เสิร์ฟจาก /Game/...) */
function normalizeGauntletAssetUrlForPlay(u) {
if (typeof u !== 'string') return '';
const t = u.trim();
if (!t) return '';
if (/^https?:\/\//i.test(t)) return t;
const qIdx = t.indexOf('?');
const base = (qIdx >= 0 ? t.slice(0, qIdx) : t).trim();
const qs = qIdx >= 0 ? t.slice(qIdx) : '';
if (!base) return '';
if (base.startsWith('/')) return base + qs;
if (/^Game\//i.test(base)) return '/' + base.replace(/^\/+/, '') + qs;
return base + qs;
}
function ensureGauntletAssetImage(url) {
const u = typeof url === 'string' ? url.trim() : '';
const u = normalizeGauntletAssetUrlForPlay(typeof url === 'string' ? url : '');
if (!u) return null;
let rec = gauntletAssetImageCache.get(u);
if (rec) return rec;
@@ -2423,6 +2440,9 @@
function isFrogger() { return mapData && mapData.gameType === 'frogger'; }
function isGauntlet() { return mapData && mapData.gameType === 'gauntlet'; }
function isGauntletFaceRightMapMno9kb07() {
return !!(isGauntlet() && playMapIdFromQuery === GAUNTLET_FACE_RIGHT_MAP_ID);
}
function isStack() { return mapData && mapData.gameType === 'stack'; }
function isJumpSurvive() { return mapData && mapData.gameType === 'jump_survive'; }
function isSpaceShooter() { return mapData && mapData.gameType === 'space_shooter'; }
@@ -4873,19 +4893,23 @@
}
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaneImageUrls') && Array.isArray(payload.gauntletLaneImageUrls)) {
gauntletLaneImageUrls = payload.gauntletLaneImageUrls.filter((x) => typeof x === 'string').slice(0, 24);
gauntletLaneImageUrls = payload.gauntletLaneImageUrls
.filter((x) => typeof x === 'string')
.map((x) => normalizeGauntletAssetUrlForPlay(x))
.filter((x) => x)
.slice(0, 24);
gauntletLaneImageUrls.forEach((x) => ensureGauntletAssetImage(x));
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserTopUrl')) {
gauntletLaserTopUrl = typeof payload.gauntletLaserTopUrl === 'string' ? payload.gauntletLaserTopUrl : '';
gauntletLaserTopUrl = normalizeGauntletAssetUrlForPlay(typeof payload.gauntletLaserTopUrl === 'string' ? payload.gauntletLaserTopUrl : '');
ensureGauntletAssetImage(gauntletLaserTopUrl);
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserBottomUrl')) {
gauntletLaserBottomUrl = typeof payload.gauntletLaserBottomUrl === 'string' ? payload.gauntletLaserBottomUrl : '';
gauntletLaserBottomUrl = normalizeGauntletAssetUrlForPlay(typeof payload.gauntletLaserBottomUrl === 'string' ? payload.gauntletLaserBottomUrl : '');
ensureGauntletAssetImage(gauntletLaserBottomUrl);
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserLineUrl')) {
gauntletLaserLineUrl = typeof payload.gauntletLaserLineUrl === 'string' ? payload.gauntletLaserLineUrl : '';
gauntletLaserLineUrl = normalizeGauntletAssetUrlForPlay(typeof payload.gauntletLaserLineUrl === 'string' ? payload.gauntletLaserLineUrl : '');
ensureGauntletAssetImage(gauntletLaserLineUrl);
}
if (Object.prototype.hasOwnProperty.call(payload, 'gauntletLaserFillColor')) {
@@ -9069,7 +9093,7 @@
if (portrait) {
const cid = me.characterId || getPlayCharacterId();
const dir = me.direction || 'down';
const dir = (isGauntletFaceRightMapMno9kb07() ? 'right' : (me.direction || 'down'));
const nowT = Date.now();
const walk = !!me.isWalking;
const rawImg = getAvatarImg(cid, dir, nowT, walk);
@@ -9665,17 +9689,9 @@
ctx.fillStyle = '#f7768e';
ctx.fillRect(sx + 2, sy + 2, size - 4, size - 4);
}
ctx.strokeStyle = '#ff9ebc';
ctx.lineWidth = 2;
ctx.strokeRect(sx + 2, sy + 2, size - 4, size - 4);
ctx.lineWidth = 1;
} else {
ctx.fillStyle = '#f7768e';
ctx.fillRect(sx + 2, sy + 2, size - 4, size - 4);
ctx.strokeStyle = '#ff9ebc';
ctx.lineWidth = 2;
ctx.strokeRect(sx + 2, sy + 2, size - 4, size - 4);
ctx.lineWidth = 1;
}
} else if (o.kind === 'laser' && typeof o.drawX === 'number') {
if (o.drawX < stx - 2 || o.drawX > enx + 2) continue;
@@ -9882,16 +9898,18 @@
? !!o.botIsWalking
: !!((o.tx != null && Math.abs((o.tx || o.x) - o.x) > 0.02) || (o.ty != null && Math.abs((o.ty || o.y) - o.y) > 0.02)));
const ot = o.playTint || playTintFromPeerId(id);
const faceDirOther = isGauntletFaceRightMapMno9kb07() ? 'right' : o.direction;
const botOut = isJumpSurvive() && isPreviewBotId(id) && o.jumpSurviveEliminated;
const peerName = botOut ? (o.nickname + ' (ตกรอบ)') : o.nickname;
if (botOut) ctx.save();
if (botOut) ctx.globalAlpha = 0.4;
drawAvatar(safeX(o.x) + off.ax, safeY(o.y) + off.ay, false, peerName, o.characterId, o.direction, otherWalk, ot, (o.gauntletJumpVis != null ? o.gauntletJumpVis : o.gauntletJumpTicks) || 0, o.gauntletScore || 0, quizCarrySignForEntity(o));
drawAvatar(safeX(o.x) + off.ax, safeY(o.y) + off.ay, false, peerName, o.characterId, faceDirOther, otherWalk, ot, (o.gauntletJumpVis != null ? o.gauntletJumpVis : o.gauntletJumpTicks) || 0, o.gauntletScore || 0, quizCarrySignForEntity(o));
if (botOut) ctx.restore();
} else {
if (isJumpSurvive() && jumpSurviveEliminated) ctx.save();
if (isJumpSurvive() && jumpSurviveEliminated) ctx.globalAlpha = 0.4;
drawAvatar(safeX(me.x), safeY(me.y), true, me.nickname + meTag, me.characterId, me.direction, meWalking, mt, meGauntletJumpVis, me.gauntletScore || 0, quizCarrySignForEntity(me));
const faceDirMe = isGauntletFaceRightMapMno9kb07() ? 'right' : me.direction;
drawAvatar(safeX(me.x), safeY(me.y), true, me.nickname + meTag, me.characterId, faceDirMe, meWalking, mt, meGauntletJumpVis, me.gauntletScore || 0, quizCarrySignForEntity(me));
if (isJumpSurvive() && jumpSurviveEliminated) ctx.restore();
}
});