minigame 1 add joystick
This commit is contained in:
@@ -1962,6 +1962,10 @@
|
||||
let quizQuestionMissionPhase = null;
|
||||
let quizQuestionMissionCountdownTimer = null;
|
||||
let quizQuestionMissionDeferredPhase = null;
|
||||
/** mng8a80o live: virtual joystick (+x right, +y down) normalized ~[-1,1] */
|
||||
let quizQuestionMissionJoyVecX = 0;
|
||||
let quizQuestionMissionJoyVecY = 0;
|
||||
let quizQuestionMissionJoyPointerId = null;
|
||||
/** Stack Tower (mnn93hpi) — flow เดียวกับ crown / quiz mission */
|
||||
let stackTowerMissionPhase = null;
|
||||
let stackTowerMissionCountdownTimer = null;
|
||||
@@ -15395,6 +15399,60 @@
|
||||
}
|
||||
}
|
||||
|
||||
function quizQuestionMissionJoystickResetVisual() {
|
||||
quizQuestionMissionJoyVecX = 0;
|
||||
quizQuestionMissionJoyVecY = 0;
|
||||
const knob = document.getElementById('quiz-q-mission-joystick-knob');
|
||||
if (knob) knob.style.transform = 'translate(-50%, -50%)';
|
||||
}
|
||||
|
||||
function quizQuestionMissionJoystickUpdateFromClientXY(clientX, clientY) {
|
||||
const base = document.getElementById('quiz-q-mission-joystick-base');
|
||||
const knob = document.getElementById('quiz-q-mission-joystick-knob');
|
||||
if (!base || !knob) return;
|
||||
const r = base.getBoundingClientRect();
|
||||
const cx = r.left + r.width * 0.5;
|
||||
const cy = r.top + r.height * 0.5;
|
||||
let dx = clientX - cx;
|
||||
let dy = clientY - cy;
|
||||
const half = Math.min(r.width, r.height) * 0.5;
|
||||
const maxKn = Math.max(18, half * 0.52);
|
||||
const len = Math.hypot(dx, dy);
|
||||
if (len > maxKn && len > 1e-6) {
|
||||
dx = (dx / len) * maxKn;
|
||||
dy = (dy / len) * maxKn;
|
||||
}
|
||||
const nlen = Math.hypot(dx, dy);
|
||||
const dead = maxKn * 0.12;
|
||||
if (nlen < dead) {
|
||||
quizQuestionMissionJoyVecX = 0;
|
||||
quizQuestionMissionJoyVecY = 0;
|
||||
knob.style.transform = 'translate(-50%, -50%)';
|
||||
return;
|
||||
}
|
||||
quizQuestionMissionJoyVecX = dx / maxKn;
|
||||
quizQuestionMissionJoyVecY = dy / maxKn;
|
||||
knob.style.transform = 'translate(calc(-50% + ' + dx + 'px), calc(-50% + ' + dy + 'px))';
|
||||
}
|
||||
|
||||
function syncQuizQuestionMissionJoystickPlay() {
|
||||
const root = document.getElementById('quiz-question-mission-joystick');
|
||||
if (!root) return;
|
||||
const on = !!(isQuizQuestionMissionHudActivePlay() && !isChatFocused());
|
||||
root.classList.toggle('is-hidden', !on);
|
||||
root.setAttribute('aria-hidden', on ? 'false' : 'true');
|
||||
if (!on) {
|
||||
const base = document.getElementById('quiz-q-mission-joystick-base');
|
||||
if (base && quizQuestionMissionJoyPointerId != null) {
|
||||
try {
|
||||
base.releasePointerCapture(quizQuestionMissionJoyPointerId);
|
||||
} catch (_e) { /* ignore */ }
|
||||
}
|
||||
quizQuestionMissionJoyPointerId = null;
|
||||
quizQuestionMissionJoystickResetVisual();
|
||||
}
|
||||
}
|
||||
|
||||
function syncPlayCyberHud() {
|
||||
const root = document.getElementById('play-cyber-hud');
|
||||
const stackEl = document.getElementById('play-canvas-stack');
|
||||
@@ -16754,6 +16812,7 @@
|
||||
}
|
||||
drawQuizTfScorePopupsLayer(ctx, worldToScreen, zDraw, timeMs);
|
||||
syncPlayCyberHud();
|
||||
syncQuizQuestionMissionJoystickPlay();
|
||||
syncQuizCarryGrabButton();
|
||||
syncGauntletCrownJumpButton();
|
||||
syncStackTowerDropButtonPlay();
|
||||
@@ -17068,10 +17127,24 @@
|
||||
}
|
||||
}
|
||||
if (!usePath) {
|
||||
if (keys['ArrowUp'] || keys['KeyW']) { accY = -1; me.direction = 'up'; }
|
||||
if (keys['ArrowDown'] || keys['KeyS']) { accY = 1; me.direction = 'down'; }
|
||||
if (keys['ArrowLeft'] || keys['KeyA']) { accX = -1; me.direction = 'left'; }
|
||||
if (keys['ArrowRight'] || keys['KeyD']) { accX = 1; me.direction = 'right'; }
|
||||
let kx = 0;
|
||||
let ky = 0;
|
||||
if (keys['ArrowLeft'] || keys['KeyA']) kx -= 1;
|
||||
if (keys['ArrowRight'] || keys['KeyD']) kx += 1;
|
||||
if (keys['ArrowUp'] || keys['KeyW']) ky -= 1;
|
||||
if (keys['ArrowDown'] || keys['KeyS']) ky += 1;
|
||||
let jx = 0;
|
||||
let jy = 0;
|
||||
if (isQuizQuestionMissionHudActivePlay()) {
|
||||
jx = quizQuestionMissionJoyVecX;
|
||||
jy = quizQuestionMissionJoyVecY;
|
||||
}
|
||||
accX = kx + jx;
|
||||
accY = ky + jy;
|
||||
if (accX !== 0 || accY !== 0) {
|
||||
if (Math.abs(accY) > Math.abs(accX)) me.direction = accY > 0 ? 'down' : 'up';
|
||||
else if (accX !== 0) me.direction = accX > 0 ? 'right' : 'left';
|
||||
}
|
||||
}
|
||||
const preWalkX = me.x, preWalkY = me.y;
|
||||
if (accX !== 0 || accY !== 0) {
|
||||
@@ -17177,6 +17250,57 @@
|
||||
});
|
||||
})();
|
||||
|
||||
(function wireQuizQuestionMissionJoystick() {
|
||||
const base = document.getElementById('quiz-q-mission-joystick-base');
|
||||
const bg = document.getElementById('quiz-q-mission-joystick-bg');
|
||||
const knobImg = document.getElementById('quiz-q-mission-joystick-knob-img');
|
||||
if (!base) return;
|
||||
if (bg) {
|
||||
bg.src = questionMissionAssetUrl('btn-joystick-1.png');
|
||||
bg.onerror = function () {
|
||||
this.onerror = null;
|
||||
this.removeAttribute('src');
|
||||
};
|
||||
}
|
||||
if (knobImg) {
|
||||
knobImg.src = questionMissionAssetUrl('btn-joystick-2.png');
|
||||
knobImg.onerror = function () {
|
||||
this.onerror = null;
|
||||
this.removeAttribute('src');
|
||||
};
|
||||
}
|
||||
function endJoy(e) {
|
||||
if (quizQuestionMissionJoyPointerId == null || e.pointerId !== quizQuestionMissionJoyPointerId) return;
|
||||
try {
|
||||
base.releasePointerCapture(e.pointerId);
|
||||
} catch (_err) { /* ignore */ }
|
||||
quizQuestionMissionJoyPointerId = null;
|
||||
quizQuestionMissionJoystickResetVisual();
|
||||
}
|
||||
base.addEventListener('pointerdown', (e) => {
|
||||
if (!isQuizQuestionMissionHudActivePlay() || isChatFocused()) return;
|
||||
if (e.button != null && e.button !== 0) return;
|
||||
e.preventDefault();
|
||||
try {
|
||||
base.setPointerCapture(e.pointerId);
|
||||
} catch (_err) { /* ignore */ }
|
||||
quizQuestionMissionJoyPointerId = e.pointerId;
|
||||
quizQuestionMissionJoystickUpdateFromClientXY(e.clientX, e.clientY);
|
||||
});
|
||||
base.addEventListener('pointermove', (e) => {
|
||||
if (quizQuestionMissionJoyPointerId == null || e.pointerId !== quizQuestionMissionJoyPointerId) return;
|
||||
e.preventDefault();
|
||||
quizQuestionMissionJoystickUpdateFromClientXY(e.clientX, e.clientY);
|
||||
});
|
||||
base.addEventListener('pointerup', endJoy);
|
||||
base.addEventListener('pointercancel', endJoy);
|
||||
base.addEventListener('lostpointercapture', (e) => {
|
||||
if (quizQuestionMissionJoyPointerId == null || e.pointerId !== quizQuestionMissionJoyPointerId) return;
|
||||
quizQuestionMissionJoyPointerId = null;
|
||||
quizQuestionMissionJoystickResetVisual();
|
||||
});
|
||||
})();
|
||||
|
||||
(function wireGauntletCrownHowtoPrimary() {
|
||||
const btn = document.getElementById('btn-gch-ready');
|
||||
if (!btn) return;
|
||||
|
||||
@@ -1673,6 +1673,67 @@
|
||||
overflow: visible;
|
||||
min-height: unset;
|
||||
}
|
||||
/* mng8a80o — virtual joystick (Roblox-style) มุมซ้ายล่าง */
|
||||
.quiz-q-mission-joystick {
|
||||
position: fixed;
|
||||
z-index: 56;
|
||||
left: max(10px, env(safe-area-inset-left, 0px));
|
||||
bottom: max(12px, env(safe-area-inset-bottom, 0px));
|
||||
width: min(132px, 28vw);
|
||||
height: min(132px, 28vw);
|
||||
touch-action: none;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
pointer-events: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html.play-preview-editor-embed .quiz-q-mission-joystick {
|
||||
position: absolute;
|
||||
bottom: max(12px, env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
.quiz-q-mission-joystick.is-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
.quiz-q-mission-joystick-base {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: grab;
|
||||
}
|
||||
.quiz-q-mission-joystick-base:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
.quiz-q-mission-joystick-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
pointer-events: none;
|
||||
image-rendering: pixelated;
|
||||
filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.45));
|
||||
}
|
||||
.quiz-q-mission-joystick-knob {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 42%;
|
||||
height: 42%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
transition: transform 0.04s linear;
|
||||
}
|
||||
.quiz-q-mission-joystick-knob-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
image-rendering: pixelated;
|
||||
filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35));
|
||||
}
|
||||
|
||||
#play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-list {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
@@ -2938,6 +2999,15 @@
|
||||
<div class="play-cyber-corruption-text">RAM ERROR · CORRUPTING · DELETE INITIATED · 01001101 01110011 01100101 01100011</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ภารกิจคำถาม mng8a80o ช่วง live: virtual joystick (QUESTION/btn-joystick-*.png) -->
|
||||
<div id="quiz-question-mission-joystick" class="quiz-q-mission-joystick is-hidden" aria-hidden="true">
|
||||
<div class="quiz-q-mission-joystick-base" id="quiz-q-mission-joystick-base">
|
||||
<img id="quiz-q-mission-joystick-bg" class="quiz-q-mission-joystick-bg" src="" alt="" decoding="async" />
|
||||
<div class="quiz-q-mission-joystick-knob" id="quiz-q-mission-joystick-knob">
|
||||
<img id="quiz-q-mission-joystick-knob-img" class="quiz-q-mission-joystick-knob-img" src="" alt="" decoding="async" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="play-quiz-scoreboard" class="is-hidden" aria-live="polite">
|
||||
<div class="play-quiz-scoreboard-title">คะแนน</div>
|
||||
@@ -3075,7 +3145,7 @@
|
||||
</div>
|
||||
<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.0332"></script>
|
||||
<script src="js/play.js?v=0.0333"></script>
|
||||
<div class="version-tag">v —</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user