Game: Tower — always load strip images; loop fill above map; rope top unclamped
- Load intro/loop even when stackTowerBgScroll disabled (still no tick if off) - Tile loop sky when mapBackground path and worldMinY<0 - Tower: cable/guide top no Math.max(0) so rope follows swing above map Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -328,13 +328,17 @@
|
||||
return !!(mapData && mapData.gameType === 'stack' && (currentPlayMapId() || '').trim() === STACK_TOWER_MISSION_MAP_ID);
|
||||
}
|
||||
|
||||
function stackTowerScrollBgDrawActive() {
|
||||
if (!stackTowerScrollBgMapEligible() || stackTowerScrollBgOff) return false;
|
||||
function stackTowerScrollBgImagesReady() {
|
||||
if (!stackTowerScrollBgMapEligible()) return false;
|
||||
const a = stackTowerScrollBgIntroImg;
|
||||
const b = stackTowerScrollBgLoopImg;
|
||||
return !!(a && a.complete && a.naturalWidth && b && b.complete && b.naturalWidth);
|
||||
}
|
||||
|
||||
function stackTowerScrollBgDrawActive() {
|
||||
return stackTowerScrollBgImagesReady();
|
||||
}
|
||||
|
||||
function reloadStackTowerScrollBgFromMap() {
|
||||
stackTowerScrollBgIntroImg = null;
|
||||
stackTowerScrollBgLoopImg = null;
|
||||
@@ -345,7 +349,6 @@
|
||||
stackTowerScrollBgSpeedPxPerSec = Math.max(8, Math.min(400, Math.floor(Number(raw.speedPxPerSec)) || 40));
|
||||
const dirRaw = String(raw.scrollDirection || raw.direction || 'up').toLowerCase();
|
||||
stackTowerScrollBgFlowDown = (dirRaw === 'down' || dirRaw === 'top' || dirRaw === 'toptobottom');
|
||||
if (stackTowerScrollBgOff) return;
|
||||
const introSrc = (typeof raw.introImage === 'string' && raw.introImage.length) ? raw.introImage : STACK_TOWER_SCROLL_BG_DEFAULT_INTRO;
|
||||
const loopSrc = (typeof raw.loopImage === 'string' && raw.loopImage.length) ? raw.loopImage : STACK_TOWER_SCROLL_BG_DEFAULT_LOOP;
|
||||
let pending = 2;
|
||||
@@ -440,8 +443,32 @@
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
/** กล้องมองเหนือขอบบนแมป (worldMinY<0) + ใช้รูปแผนที่ — ยัด loop ท้องฟ้าเติมครึ่งบนจอ */
|
||||
function drawStackTowerLoopSkyFillAboveMap(ctx, worldMinY, zDraw, cw, ch) {
|
||||
if (!isStackTowerMissionUiMapPlay() || worldMinY >= 0) return;
|
||||
const loop = stackTowerScrollBgLoopImg;
|
||||
if (!loop || !loop.complete || !loop.naturalWidth) return;
|
||||
const cwR = Math.max(1, Math.round(cw));
|
||||
const chR = Math.max(1, Math.round(ch));
|
||||
const scaleL = cwR / loop.naturalWidth;
|
||||
const drawHLoop = Math.max(1, Math.round(loop.naturalHeight * scaleL));
|
||||
const skyScreenH = Math.min(chR, Math.ceil(-worldMinY * zDraw) + 4);
|
||||
const scroll = (stackTowerScrollBgPx + getStackTowerBgScrollHeightBoostPx()) % drawHLoop;
|
||||
let y = -scroll;
|
||||
ctx.save();
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
while (y < skyScreenH + drawHLoop) {
|
||||
if (y + drawHLoop > 0) {
|
||||
ctx.drawImage(loop, 0, 0, loop.naturalWidth, loop.naturalHeight, 0, y, cwR, drawHLoop);
|
||||
}
|
||||
y += drawHLoop;
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
function tickStackTowerScrollBg(dtSec) {
|
||||
if (!stackTowerScrollBgDrawActive()) return;
|
||||
if (!stackTowerScrollBgMapEligible() || stackTowerScrollBgOff) return;
|
||||
if (!stackTowerScrollBgImagesReady()) return;
|
||||
stackTowerScrollBgPx += (stackTowerScrollBgSpeedPxPerSec || 40) * dtSec;
|
||||
}
|
||||
|
||||
@@ -6890,7 +6917,9 @@
|
||||
: 0.16 * offN * (hit.perfect ? 0.1 : 1);
|
||||
const isHumanPreview = !!(previewActor && previewActor.human);
|
||||
const botIdPreview = previewActor && previewActor.botId ? previewActor.botId : null;
|
||||
const cableTopYRel = Math.max(0, swingAttachY - tileSize * 6);
|
||||
const cableTopYRel = isStackTowerMissionUiMapPlay()
|
||||
? (swingAttachY - tileSize * 6)
|
||||
: Math.max(0, swingAttachY - tileSize * 6);
|
||||
const craneXRel = m.craneWorldX != null ? m.craneWorldX : m.topCenterX * tileSize;
|
||||
const releaseRopeAng = Math.atan2(swingAttachY - cableTopYRel, swingXW - craneXRel);
|
||||
stackFall = {
|
||||
@@ -7076,7 +7105,9 @@
|
||||
const floorY = m.floorWorldY;
|
||||
const swingLiftDraw = getStackTowerSwingLiftWorldPx(m.layers.length, layerWorldH);
|
||||
const swingDrawY = m.swingWorldY - swingLiftDraw;
|
||||
const guideTopY = Math.max(0, swingDrawY - tileSize * 6.5);
|
||||
const guideTopY = isStackTowerMissionUiMapPlay()
|
||||
? (swingDrawY - tileSize * 6.5)
|
||||
: Math.max(0, swingDrawY - tileSize * 6.5);
|
||||
const [gtx, gty] = worldToScreen(m.topCenterX * tileSize, guideTopY);
|
||||
const [gbx, gby] = worldToScreen(m.topCenterX * tileSize, floorY);
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.22)';
|
||||
@@ -7132,7 +7163,9 @@
|
||||
} else {
|
||||
const twWorld = m.widthTiles * tileSize;
|
||||
const drawStripPx = stripH * zoom;
|
||||
const cableTopY = Math.max(0, swingDrawY - tileSize * 6);
|
||||
const cableTopY = isStackTowerMissionUiMapPlay()
|
||||
? (swingDrawY - tileSize * 6)
|
||||
: Math.max(0, swingDrawY - tileSize * 6);
|
||||
const craneX = m.craneWorldX != null ? m.craneWorldX : m.topCenterX * tileSize;
|
||||
let blockLeftWorld;
|
||||
let blockTopWorld;
|
||||
@@ -12937,6 +12970,7 @@
|
||||
/* กล้องเห็นพื้นที่นอก [0,map] ได้ — ห้ามสุ่มต้นทาง drawImage เกินขอบภาพ (จะเกิดซ้ำ/เส้นตัด/ซ้อนกันที่ขอบจอ) */
|
||||
ctx.fillStyle = (isSpaceShooter() || isBalloonBoss()) ? '#0a0e22' : '#1a1b26';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
drawStackTowerLoopSkyFillAboveMap(ctx, worldMinY, zDraw, canvas.width, canvas.height);
|
||||
const natW = mapBackgroundImg.naturalWidth;
|
||||
const natH = mapBackgroundImg.naturalHeight;
|
||||
const bgMinX = Math.max(0, worldMinX);
|
||||
|
||||
@@ -2009,7 +2009,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.271"></script>
|
||||
<script src="js/play.js?v=0.272"></script>
|
||||
<div class="version-tag">v —</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user