minigame 3add more design 1.65

This commit is contained in:
2026-05-04 18:00:51 +00:00
parent b481e585a3
commit e69216cb4a
3 changed files with 56 additions and 22 deletions
@@ -25,7 +25,7 @@ English: Upload Stack / tower assets under **`TowerBlock`** (no spaces). **`Towe
| `sling.png` | เชือกเหวี่ยงบล็อกในเกม (ยืดจากจุดแขวนถึงบล็อก) — แนวตั้งในไฟล์ = แนวสาย; ไม่มีไฟล์จะใช้เส้นประแทน |
| `heart-1.png` | โชว์กลางเหนือกองเมื่อ **พลาด** (Tower live) — ไม่มีจะ fallback ข้อความ `♥ 1` |
| `life-full.png` | HUD มุมขวา: หัวใจ **เต็ม** ในแถบชีวิต (คู่ `life-hit.png`) — ไม่มีจะ fallback เป็น `heart-1.png` |
| `life-bar.png` | HUD: สไตล์ข้อความ **SYSTEM INTEGRITY** + วงเล็บ — วาง **ซ้ายของอวตาร** ในแผง cyan (mock รูป2) |
| `life-bar.png` | HUD: ใช้เฉพาะ **ครึ่งบน** (~38%) เป็นหัวข้อ SYSTEM INTEGRITY — แถวหัวใจวาดแยกใต้ + วงเล็บ `[` `]` จากโค้ด (ไม่ทับขอบใน PNG) · ปรับ `STACK_TOWER_LIFE_BAR_TITLE_FRAC` ใน `play.js` ถ้า art เปลี่ยน |
| `life-hit.png` | หัวใจ **หาย / โดนตี** ในแถบชีวิต (คู่ `life-full.png`) |
| `btn-drop.png` | ปุ่ม **DROP** มุมขวาล่างใน `play.html` (เทียบ Space / Enter) |
| `score+10.png` | Tower live: โชว์เหนือบล็อกเมื่อได้ **+10** |
+54 -20
View File
@@ -4211,13 +4211,12 @@
}
/**
* นทระหวางวงเลบบน life-bar.png (normalized 01) ปรบถ asset เปลยนเลยเอาต
* UV rect on life-bar.png for heart row between brackets (tune if art changes).
* ดสวนสงของ life-bar.png เปนขอความ "SYSTEM INTEGRITY" (เหล = แถวหวใจแยกวาดเอง ไมบขอบ `[` `]` ใน PNG)
*/
const STACK_TOWER_LIFE_BAR_HEART_SLOT_UV = { u0: 0.11, u1: 0.89, v0: 0.40, v1: 0.86 };
const STACK_TOWER_LIFE_BAR_TITLE_FRAC = 0.38;
/**
* วาด life-bar + วใจ life-full (เต) / life-hit (หาย) ในกรอบ dest นความสงจรงทวาด
* วาดวขอจาก life-bar.png (ครอปบน) + แถววใจ life-full / life-hit งกลาง นความสงทใชจร
*/
function drawStackTowerLifeIntegrityBarPlay(ctx, destX, destY, maxW, maxH, lifeSlots, livesRem) {
ensureStackTowerLifeHudImagesPlay();
@@ -4246,35 +4245,69 @@
const bw0 = bar.naturalWidth;
const bh0 = bar.naturalHeight;
const scale = Math.min(maxW / bw0, maxH / bh0, 1.35);
const titleSrcH = Math.max(2, Math.floor(bh0 * STACK_TOWER_LIFE_BAR_TITLE_FRAC));
const scale = Math.min(maxW / bw0, 1.45);
const bw = bw0 * scale;
const bh = bh0 * scale;
const titleDh = titleSrcH * scale;
const gap = 3;
const bx = destX;
const by = destY + Math.max(0, (maxH - bh) * 0.5);
const by0 = destY + Math.max(0, (maxH - titleDh - gap - Math.min(40, maxH * 0.45)) * 0.35);
const heartsTop = by0 + titleDh + gap;
const roomHearts = Math.max(10, destY + maxH - heartsTop - 2);
const heartsH = Math.max(18, Math.min(roomHearts, 40, Math.floor(maxH * 0.5)));
ctx.save();
try {
ctx.drawImage(bar, 0, 0, bw0, bh0, bx, by, bw, bh);
ctx.drawImage(bar, 0, 0, bw0, titleSrcH, bx, by0, bw, titleDh);
} catch (e) { /* ignore */ }
const uv = STACK_TOWER_LIFE_BAR_HEART_SLOT_UV;
const ix = bx + uv.u0 * bw;
const iy = by + uv.v0 * bh;
const iwSlot = Math.max(4, (uv.u1 - uv.u0) * bw);
const ihSlot = Math.max(4, (uv.v1 - uv.v0) * bh);
const slotW = iwSlot / slots;
const iconMax = Math.min(slotW * 0.82, ihSlot * 0.88, 36);
const cy = heartsTop + heartsH * 0.5;
const bracketW = Math.min(14, Math.max(9, bw * 0.07));
ctx.fillStyle = 'rgba(94, 239, 255, 0.88)';
ctx.font = '600 ' + Math.round(Math.min(17, heartsH * 0.55)) + 'px ui-monospace, "Cascadia Mono", Consolas, monospace';
ctx.textBaseline = 'middle';
ctx.textAlign = 'left';
ctx.shadowColor = 'rgba(0, 234, 255, 0.45)';
ctx.shadowBlur = 4;
ctx.fillText('[', bx + 1, cy);
ctx.textAlign = 'right';
ctx.fillText(']', bx + bw - 1, cy);
ctx.shadowBlur = 0;
const ix = bx + bracketW + 4;
const iwInner = Math.max(24, bw - (bracketW + 4) * 2);
const slotW = iwInner / slots;
const iconMax = Math.min(heartsH * 0.78, slotW * 0.72, 34);
for (let i = 0; i < slots; i++) {
const cx = ix + slotW * (i + 0.5);
const cy = iy + ihSlot * 0.5;
const useFull = i < lives;
const im = useFull ? fullIm : hitIm;
if (im && im.complete && im.naturalWidth > 0 && im.naturalHeight > 0) {
const ih = iconMax;
const iw = (ih * im.naturalWidth) / im.naturalHeight;
const nw = im.naturalWidth;
const nh = im.naturalHeight;
let ih = iconMax;
let iw = (ih * nw) / nh;
const capW = slotW * 0.82;
const capH = heartsH * 0.88;
if (iw > capW) {
iw = capW;
ih = (iw * nh) / nw;
}
if (ih > capH) {
ih = capH;
iw = (ih * nw) / nh;
}
if (iw < 6 && nh > 0) {
iw = 6;
ih = (iw * nh) / nw;
if (ih > capH) {
ih = capH;
iw = (ih * nw) / nh;
}
}
try {
ctx.drawImage(im, 0, 0, im.naturalWidth, im.naturalHeight, cx - iw / 2, cy - ih / 2, iw, ih);
ctx.drawImage(im, 0, 0, nw, nh, cx - iw / 2, cy - ih / 2, iw, ih);
} catch (e2) { /* ignore */ }
} else {
ctx.fillStyle = useFull ? '#9ece6a' : '#565f89';
@@ -4285,7 +4318,8 @@
}
}
ctx.restore();
return bh;
const usedH = heartsTop + heartsH - by0 + 2;
return Math.min(maxH, Math.max(titleDh, usedH));
}
function triggerStackTowerHeartMinusFxPlay() {
+1 -1
View File
@@ -2753,7 +2753,7 @@
</div>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0258"></script>
<script src="js/play.js?v=0.0259"></script>
<script src="js/play.js?v=0.0260"></script>
<div class="version-tag">v —</div>
</body>
</html>