diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index 2eb4392..d3686ee 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -221,20 +221,32 @@ return null; } + /** @returns {boolean} true = วาดสไปรต์แล้ว (ไม่ยืด — fit ในกล่องแบบ contain) · false = วาดสี่เหลี่ยมสี fallback */ function drawStackBlockSpriteOrHue(ctx, sx, sy, drawW, drawH, seat, heavy, hueFallback, opts) { const o = opts || {}; const rec = resolveStackBlockSpriteRec(seat, heavy); if (rec && rec.ready && rec.img && rec.img.naturalWidth > 0) { - ctx.drawImage(rec.img, sx, sy, drawW, drawH); - if (o.missOverlay) { - ctx.fillStyle = 'rgba(247, 118, 190, 0.42)'; - ctx.fillRect(sx, sy, drawW, drawH); + const img = rec.img; + const iw = img.naturalWidth; + const ih = img.naturalHeight; + if (iw > 0 && ih > 0 && drawW > 0 && drawH > 0) { + const scale = Math.min(drawW / iw, drawH / ih); + const dw = iw * scale; + const dh = ih * scale; + const dx = sx + (drawW - dw) * 0.5; + const dy = sy + (drawH - dh) * 0.5; + ctx.drawImage(img, 0, 0, iw, ih, dx, dy, dw, dh); + if (o.missOverlay) { + ctx.fillStyle = 'rgba(247, 118, 190, 0.42)'; + ctx.fillRect(dx, dy, dw, dh); + } + return true; } - return; } const hue = ((hueFallback % 360) + 360) % 360; ctx.fillStyle = o.missTint ? 'rgba(247, 118, 190, 0.88)' : ('hsla(' + hue + ', 68%, 56%, 0.9)'); ctx.fillRect(sx, sy, drawW, drawH); + return false; } if (!spaceId) { window.location.replace(BASE + '/lobby.html'); return; } @@ -7228,10 +7240,12 @@ const hue = (i * 47) % 360; const seatL = L.seat != null ? L.seat : 1; const heavyL = !!L.heavy; - drawStackBlockSpriteOrHue(ctx, sx, sy, drawW, drawH, seatL, heavyL, hue, {}); - ctx.strokeStyle = 'rgba(255,255,255,0.38)'; - ctx.lineWidth = 1; - ctx.strokeRect(sx, sy, drawW, drawH); + const drewSpr = drawStackBlockSpriteOrHue(ctx, sx, sy, drawW, drawH, seatL, heavyL, hue, {}); + if (!drewSpr) { + ctx.strokeStyle = 'rgba(255,255,255,0.38)'; + ctx.lineWidth = 1; + ctx.strokeRect(sx, sy, drawW, drawH); + } } if (m.settling) { const s = m.settling; @@ -7252,10 +7266,12 @@ ctx.save(); ctx.translate(cxs, cys); ctx.rotate(rotRad); - drawStackBlockSpriteOrHue(ctx, -drawW / 2, -drawH / 2, drawW, drawH, seatS, heavyS, hue, {}); - ctx.strokeStyle = 'rgba(255, 200, 140, 0.9)'; - ctx.lineWidth = 2; - ctx.strokeRect(-drawW / 2, -drawH / 2, drawW, drawH); + const drewSet = drawStackBlockSpriteOrHue(ctx, -drawW / 2, -drawH / 2, drawW, drawH, seatS, heavyS, hue, {}); + if (!drewSet) { + ctx.strokeStyle = 'rgba(255, 200, 140, 0.9)'; + ctx.lineWidth = 2; + ctx.strokeRect(-drawW / 2, -drawH / 2, drawW, drawH); + } ctx.restore(); } else { const twWorld = m.widthTiles * tileSize; @@ -7300,13 +7316,15 @@ : (m.pendingDropSeat != null ? m.pendingDropSeat : getStackDropActorSeat()); const heavyDraw = stackFall ? !!stackFall.actorHeavy : !!m.pendingDropHeavy; const hueHint = (m.layers.length * 47) % 360; - ctx.strokeStyle = hitMissTint ? 'rgba(255, 180, 210, 0.98)' : 'rgba(192, 202, 245, 0.98)'; ctx.save(); ctx.translate(bcx, bcy); ctx.rotate(fallTiltRad + swingTiltRad); - drawStackBlockSpriteOrHue(ctx, -twWorld * zoom / 2, 0, twWorld * zoom, drawStripPx, seatDraw, heavyDraw, hueHint, { missTint: !!hitMissTint, missOverlay: !!hitMissTint }); - ctx.lineWidth = 2; - ctx.strokeRect(-twWorld * zoom / 2, 0, twWorld * zoom, drawStripPx); + const drewSwing = drawStackBlockSpriteOrHue(ctx, -twWorld * zoom / 2, 0, twWorld * zoom, drawStripPx, seatDraw, heavyDraw, hueHint, { missTint: !!hitMissTint, missOverlay: !!hitMissTint }); + if (!drewSwing) { + ctx.strokeStyle = hitMissTint ? 'rgba(255, 180, 210, 0.98)' : 'rgba(192, 202, 245, 0.98)'; + ctx.lineWidth = 2; + ctx.strokeRect(-twWorld * zoom / 2, 0, twWorld * zoom, drawStripPx); + } ctx.lineWidth = 1; ctx.restore(); } diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index a767e2a..d3170cd 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -2009,7 +2009,7 @@ - +