minigame 6 rocker 1.3

This commit is contained in:
2026-05-01 10:39:10 +00:00
parent 52eb6744bf
commit ed0f24b344
7 changed files with 69 additions and 10 deletions
+11 -1
View File
@@ -2776,6 +2776,11 @@
var ss = Number(data.spaceShooterMissionTimeSec);
inpT.value = String(Number.isFinite(ss) && ss > 0 ? Math.floor(ss) : 0);
}
var inpIv = el('space-shooter-asteroid-interval-ms');
if (inpIv) {
var iv = Number(data.spaceShooterAsteroidIntervalMs);
inpIv.value = String(Number.isFinite(iv) && iv >= 200 ? Math.min(10000, Math.floor(iv)) : 1040);
}
var urls = data.spaceShooterShipImageUrls;
if (!Array.isArray(urls)) urls = [];
for (var k = 1; k <= 6; k++) {
@@ -2819,6 +2824,10 @@
var explodeMs = inpFms ? parseInt(String(inpFms.value), 10) : 70;
if (Number.isNaN(explodeMs)) explodeMs = 70;
explodeMs = Math.max(30, Math.min(500, explodeMs));
var inpIv = el('space-shooter-asteroid-interval-ms');
var asteroidIv = inpIv ? parseInt(String(inpIv.value), 10) : 1040;
if (Number.isNaN(asteroidIv)) asteroidIv = 1040;
asteroidIv = Math.max(200, Math.min(10000, asteroidIv));
gameTimingFetch('GET')
.then(function (data) {
data.spaceShooterMissionTimeSec = limSs;
@@ -2826,10 +2835,11 @@
data.spaceShooterShipDamageOverlayUrls = damageUrls;
data.spaceShooterAsteroidSpriteUrls = astUrls;
data.spaceShooterAsteroidExplodeFrameMs = explodeMs;
data.spaceShooterAsteroidIntervalMs = asteroidIv;
return gameTimingFetch('PUT', data);
})
.then(function () {
setMsg('space-shooter-timing-msg', 'บันทึกแล้ว — เวลา / รูปยาน / overlay ความเสียหาย / อุกาบาต มีผลเมื่อรีเฟรชหน้าเล่นหรือโหลด /api/game-timing', 'ok');
setMsg('space-shooter-timing-msg', 'บันทึกแล้ว — เวลา / ความถี่เกิดอุกาบาต / รูปยาน / overlay / อุกาบาต มีผลเมื่อรีเฟรชหน้าเล่นหรือโหลด /api/game-timing', 'ok');
})
.catch(function (e) {
setMsg('space-shooter-timing-msg', e.message || 'บันทึกไม่ได้', 'error');
+9 -2
View File
@@ -468,13 +468,20 @@
<section id="tab-panel-space-shooter" class="tab-panel card" hidden role="tabpanel" aria-labelledby="tab-space-shooter">
<h2>ยิงยานอวกาศ (Violent Crime / space_shooter) — เวลารอบ + รูปยานต่อช่อง</h2>
<p class="muted">เก็บที่ <code>/Game/data/game-timing.json</code><code>spaceShooterMissionTimeSec</code> · <code>spaceShooterShipImageUrls</code> · <code>spaceShooterShipDamageOverlayUrls</code> (ทับรอยร้าวเมื่อโดนอุกาบาต 1–3 ครั้ง) · <code>spaceShooterAsteroidSpriteUrls</code> + <code>spaceShooterAsteroidExplodeFrameMs</code> · ผู้เล่นได้ค่าใหม่เมื่อโหลดหน้าเล่น / <code>GET /api/game-timing</code> · อัปโหลด PNG ไปที่ <code>/Game/public/img/ViolentCrime/</code> (โฟลเดอร์<strong>ไม่มีช่องว่าง</strong>) · อัปโหลด overlay ผ่านคลัง Gauntlet (<code>/Game/img/gauntlet-assets/</code>)</p>
<p class="muted">เก็บที่ <code>/Game/data/game-timing.json</code><code>spaceShooterMissionTimeSec</code> · <code>spaceShooterShipImageUrls</code> · <code>spaceShooterShipDamageOverlayUrls</code> · <code>spaceShooterAsteroidIntervalMs</code> · <code>spaceShooterAsteroidSpriteUrls</code> + <code>spaceShooterAsteroidExplodeFrameMs</code> · ผู้เล่นได้ค่าใหม่เมื่อโหลดหน้าเล่น / <code>GET /api/game-timing</code> · อัปโหลด PNG ไปที่ <code>/Game/public/img/ViolentCrime/</code> (โฟลเดอร์<strong>ไม่มีช่องว่าง</strong>) · อัปโหลด overlay ผ่านคลัง Gauntlet (<code>/Game/img/gauntlet-assets/</code>)</p>
<fieldset class="quiz-timing-fieldset">
<legend>จำกัดเวลารอบ (ยิงอุกาบาต)</legend>
<div class="form-grid form-inline quiz-timing-grid">
<label title="0 = ใช้ค่าเริ่ม 90 วินาทีในเกม · ตั้งอย่างน้อย 10 วินาทีถ้าต้องการกำหนดเอง">เวลารอบ (วินาที) <input type="number" id="space-shooter-mission-sec" min="0" max="7200" step="5" value="0"></label>
</div>
</fieldset>
<fieldset class="quiz-timing-fieldset">
<legend>อุกาบาต — อัตราการเกิด (ความถี่ร่วง)</legend>
<p class="muted" style="margin-top:0">ระยะห่างระหว่างเกิดดวงใหม่ (มิลลิวินาที) · <strong>ค่าน้อย = อุกาบาตถี่ขึ้น</strong> (เช่น 400 ถี่กว่า 2000) · 200–10000 ms · ทุกแมป space_shooter โหลดค่านี้จากเซิร์ฟเวอร์เมื่อเข้าเกม · ถ้าในแมปตั้ง <code>spaceShooterAsteroidIntervalMs</code> ≥ 200 จะใช้ค่าบนแมปแทนค่านี้ · <em>English:</em> Lower ms = denser rain. Map ≥200 overrides.</p>
<div class="form-grid form-inline quiz-timing-grid">
<label title="มิลลิวินาทีระหว่างเกิดดวงใหม่ — ค่าเริ่มในเกมเดิม 1040">ช่วงเวลาเกิด (ms) <input type="number" id="space-shooter-asteroid-interval-ms" min="200" max="10000" step="10" value="1040"></label>
</div>
</fieldset>
<fieldset class="quiz-timing-fieldset">
<legend>รูปยานต่อช่อง (spawn slot 16)</legend>
<p class="muted" style="margin-top:0">ช่องตรงกับ <code>shooterSpawnSlots</code> บนแมป (1–6) · ว่าง = ใช้ยานวาดเวกเตอร์เดิม · <em>English:</em> One image URL per map slot; empty keeps the default vector ship.</p>
@@ -746,6 +753,6 @@
</div>
</main>
</div>
<script src="admin.js?v=58"></script>
<script src="admin.js?v=60"></script>
</body>
</html>
+1
View File
@@ -33,6 +33,7 @@
"/Game/img/ViolentCrime/Meteo-3.png"
],
"spaceShooterAsteroidExplodeFrameMs": 60,
"spaceShooterAsteroidIntervalMs": 300,
"spaceShooterShipDamageOverlayUrls": [
"/Game/img/ViolentCrime/Rocket-broke-1.png",
"/Game/img/ViolentCrime/Rocket-broke-2.png",
File diff suppressed because one or more lines are too long
+27 -5
View File
@@ -755,6 +755,8 @@
/** อุกาบาต: [0]=ตก, [1..]=แตก — จาก game-timing */
let playSpaceShooterAsteroidSpriteUrls = [];
let playSpaceShooterAsteroidExplodeFrameMs = 70;
/** ระยะห่างเกิดอุกาบาต (ms) จาก game-timing — แมป spaceShooterAsteroidIntervalMs ≥200 ทับ */
let playSpaceShooterAsteroidIntervalMs = 1040;
/** ทับยานเมื่อชนอุกาบาต ครั้งที่ 1–3 (PNG โปร่ง) — ภารกิจ Violent Crime */
let playSpaceShooterShipDamageOverlayUrls = ['', '', ''];
/** 0 = ไม่จำกัด — จาก game-timing / gauntlet-sync (พรมแดง Gauntlet เท่านั้น) */
@@ -5812,6 +5814,14 @@
playSpaceShooterAsteroidExplodeFrameMs = Math.max(30, Math.min(500, Math.round(ef)));
}
}
if (Object.prototype.hasOwnProperty.call(payload, 'spaceShooterAsteroidIntervalMs')) {
const iv = Number(payload.spaceShooterAsteroidIntervalMs);
if (Number.isFinite(iv) && iv >= 200) {
playSpaceShooterAsteroidIntervalMs = Math.min(10000, Math.floor(iv));
} else {
playSpaceShooterAsteroidIntervalMs = 1040;
}
}
if (Object.prototype.hasOwnProperty.call(payload, 'spaceShooterShipDamageOverlayUrls')) {
const rawD = payload.spaceShooterShipDamageOverlayUrls;
const nextD = ['', '', ''];
@@ -7096,6 +7106,18 @@
return Math.max(lo, Math.min(hi, cy));
}
const SPACE_SHOOTER_ASTEROID_INTERVAL_MIN = 200;
/** ms ระหว่างเกิดอุกาบาต — แมปทับถ้าตั้ง ≥200 */
function spaceShooterAsteroidSpawnIntervalMsPlay() {
const mapI = Number(mapData && mapData.spaceShooterAsteroidIntervalMs);
if (Number.isFinite(mapI) && mapI >= SPACE_SHOOTER_ASTEROID_INTERVAL_MIN) {
return Math.min(10000, Math.floor(mapI));
}
const g = Number(playSpaceShooterAsteroidIntervalMs);
if (Number.isFinite(g) && g >= SPACE_SHOOTER_ASTEROID_INTERVAL_MIN) return Math.min(10000, Math.floor(g));
return 1040;
}
function stepSpaceShooterPreviewBots(dt) {
if (spaceShooterGameEnded || !previewFillBots || !mapData || mapData.gameType !== 'space_shooter') return;
if (isSpaceShooterMissionUiMapPlay() && spaceShooterMissionPhase !== 'live') return;
@@ -7161,7 +7183,7 @@
return;
}
const interval = Math.max(320, Number(mapData.spaceShooterAsteroidIntervalMs) || 1040);
const interval = spaceShooterAsteroidSpawnIntervalMsPlay();
spaceShooterSpawnAccMs += dt * 1000;
while (spaceShooterSpawnAccMs >= interval) {
spaceShooterSpawnAccMs -= interval;
@@ -9046,14 +9068,14 @@
clearTimeout(spaceShooterMissionCountdownTimer);
spaceShooterMissionCountdownTimer = null;
}
fetch(BASE + '/api/game-timing?_=' + Date.now(), { cache: 'no-store' })
.then(function (r) { return r.ok ? r.json() : null; })
.then(function (t) { if (t) applyGauntletTimingFromServer(t); })
.catch(function () {});
if (isSpaceShooterMissionUiMapPlay()) {
spaceShooterMissionPhase = 'howto';
hideConflictingOverlaysForGauntletCrown();
applySpaceShooterMissionPanelImages();
fetch(BASE + '/api/game-timing?_=' + Date.now(), { cache: 'no-store' })
.then(function (r) { return r.ok ? r.json() : null; })
.then(function (t) { if (t) applyGauntletTimingFromServer(t); })
.catch(function () {});
setTimeout(function () { showSpaceShooterMissionHowtoOverlay(); }, 50);
} else {
spaceShooterMissionPhase = null;
+1 -1
View File
@@ -1897,7 +1897,7 @@
</div>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0184"></script>
<script src="js/play.js?v=0.220"></script>
<script src="js/play.js?v=0.222"></script>
<div class="version-tag">v —</div>
</body>
</html>
+19
View File
@@ -545,6 +545,8 @@ function defaultGameTiming() {
spaceShooterShipImageUrls: ['', '', '', '', '', ''],
spaceShooterAsteroidSpriteUrls: [],
spaceShooterAsteroidExplodeFrameMs: 70,
/** ระยะห่างเกิดอุกาบาต (ms) — ค่าน้อย = ถี่ขึ้น; แมป spaceShooterAsteroidIntervalMs ≥200 ทับ */
spaceShooterAsteroidIntervalMs: 1040,
spaceShooterShipDamageOverlayUrls: ['', '', ''],
};
}
@@ -627,6 +629,13 @@ function clampSpaceShooterAsteroidExplodeFrameMs(n) {
return Math.max(30, Math.min(500, Math.round(v)));
}
const SPACE_SHOOTER_ASTEROID_INTERVAL_MS_DEFAULT = 1040;
function clampSpaceShooterAsteroidIntervalMs(n) {
const v = Number(n);
if (Number.isNaN(v) || v <= 0) return SPACE_SHOOTER_ASTEROID_INTERVAL_MS_DEFAULT;
return Math.max(200, Math.min(10000, Math.floor(v)));
}
/** รูปทับยานเมื่อชนอุกาบาต ครั้งที่ 1–3 (ภารกิจ Violent Crime) */
function normalizeSpaceShooterShipDamageOverlayUrls(val) {
let arr = val;
@@ -765,6 +774,9 @@ function loadGameTiming() {
spaceShooterAsteroidExplodeFrameMs: Object.prototype.hasOwnProperty.call(j, 'spaceShooterAsteroidExplodeFrameMs')
? clampSpaceShooterAsteroidExplodeFrameMs(j.spaceShooterAsteroidExplodeFrameMs)
: 70,
spaceShooterAsteroidIntervalMs: Object.prototype.hasOwnProperty.call(j, 'spaceShooterAsteroidIntervalMs')
? clampSpaceShooterAsteroidIntervalMs(j.spaceShooterAsteroidIntervalMs)
: SPACE_SHOOTER_ASTEROID_INTERVAL_MS_DEFAULT,
spaceShooterShipDamageOverlayUrls: normalizeSpaceShooterShipDamageOverlayUrls(j.spaceShooterShipDamageOverlayUrls),
};
}
@@ -836,6 +848,12 @@ function saveGameTimingToFile(d) {
const spaceShooterAsteroidExplodeFrameMs = Object.prototype.hasOwnProperty.call(d, 'spaceShooterAsteroidExplodeFrameMs')
? clampSpaceShooterAsteroidExplodeFrameMs(d.spaceShooterAsteroidExplodeFrameMs)
: clampSpaceShooterAsteroidExplodeFrameMs(prevAstFms);
const prevAstIv = Object.prototype.hasOwnProperty.call(prev, 'spaceShooterAsteroidIntervalMs')
? prev.spaceShooterAsteroidIntervalMs
: SPACE_SHOOTER_ASTEROID_INTERVAL_MS_DEFAULT;
const spaceShooterAsteroidIntervalMs = Object.prototype.hasOwnProperty.call(d, 'spaceShooterAsteroidIntervalMs')
? clampSpaceShooterAsteroidIntervalMs(d.spaceShooterAsteroidIntervalMs)
: clampSpaceShooterAsteroidIntervalMs(prevAstIv);
const prevDmg = Array.isArray(prev.spaceShooterShipDamageOverlayUrls)
? normalizeSpaceShooterShipDamageOverlayUrls(prev.spaceShooterShipDamageOverlayUrls)
: normalizeSpaceShooterShipDamageOverlayUrls([]);
@@ -855,6 +873,7 @@ function saveGameTimingToFile(d) {
spaceShooterShipImageUrls,
spaceShooterAsteroidSpriteUrls,
spaceShooterAsteroidExplodeFrameMs,
spaceShooterAsteroidIntervalMs,
spaceShooterShipDamageOverlayUrls,
};
fs.writeFileSync(GAME_TIMING_PATH, JSON.stringify(out, null, 2), 'utf8');