User prompt
ses ekle
User prompt
her blok konulduğunda ses ekle
User prompt
arka plan ekle
User prompt
özel yetenekler ekle
User prompt
arka plan oluştur
User prompt
blockler daha uzun ve biraz daha ince olsun
Code edit (1 edits merged)
Please save this source code
User prompt
Ice Stack Tower
Initial prompt
bana ıce tower benzeri bi oyun yap
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { best: 0 }); /**** * Classes ****/ // IceBlock class: represents a single moving or stacked ice block var IceBlock = Container.expand(function () { var self = Container.call(this); // Default block size (will be set on creation) self.blockWidth = 900; self.blockHeight = 70; self.color = 0xB3E6FF; // Light blue ice color // Create and attach the block asset var blockAsset = self.attachAsset('iceBlock', { width: self.blockWidth, height: self.blockHeight, color: self.color, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Update block asset size if changed self.setSize = function (w, h) { self.blockWidth = w; self.blockHeight = h; blockAsset.width = w; blockAsset.height = h; }; // Set color (for possible effects) self.setColor = function (color) { self.color = color; blockAsset.color = color; }; // Animate block to a new position (used for drop) self.animateTo = function (targetY, duration, onFinish) { tween(self, { y: targetY }, { duration: duration, easing: tween.cubicOut, onFinish: onFinish }); }; // Animate block shrink (used for misaligned drops) self.animateShrink = function (newWidth, duration, _onFinish) { tween(self, { blockWidth: newWidth }, { duration: duration, easing: tween.cubicInOut, onFinish: function onFinish() { self.setSize(newWidth, self.blockHeight); if (_onFinish) _onFinish(); } }); }; // For collision and alignment calculations self.getLeft = function () { return self.x - self.blockWidth / 2; }; self.getRight = function () { return self.x + self.blockWidth / 2; }; // For updating asset size if tweened self.update = function () { // If tweening blockWidth, update asset if (blockAsset.width !== self.blockWidth) { blockAsset.width = self.blockWidth; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Tween plugin for block drop and shrink animations // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; // Add background image to the game scene var bg = LK.getAsset('iceBg', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: GAME_WIDTH, height: GAME_HEIGHT }); game.addChild(bg); var START_BLOCK_WIDTH = 900; var BLOCK_HEIGHT = 70; var BLOCK_COLOR = 0xB3E6FF; var BLOCK_SPEED = 16; // px per frame var MIN_BLOCK_WIDTH = 80; // Minimum width before game over var DROP_ANIMATION_TIME = 180; // ms var SHRINK_ANIMATION_TIME = 120; // ms var START_Y = GAME_HEIGHT - 400; // Y position of the first block // Game state var stack = []; // Array of stacked blocks (bottom to top) var movingBlock = null; // The current moving block var movingDirection = 1; // 1 = right, -1 = left var isDropping = false; // Prevents double drop var scoreTxt = null; var bestTxt = null; var currentScore = 0; var bestScore = 0; // Special ability state var specialReady = true; var specialCooldown = 0; // ms remaining var SPECIAL_COOLDOWN_TIME = 5000; // 5 seconds cooldown var specialBtn = null; // Storage for best score if (typeof storage.best === 'number') { bestScore = storage.best; } // Score display scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); bestTxt = new Text2('Best: ' + bestScore, { size: 60, fill: 0xAEEFFF }); bestTxt.anchor.set(0.5, 0); LK.gui.top.addChild(bestTxt); bestTxt.y = 120; // Special ability button specialBtn = new Text2('ICE POWER', { size: 70, fill: specialReady ? 0x00eaff : 0x888888 }); specialBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(specialBtn); specialBtn.y = -120; // Raise above bottom edge specialBtn.x = 0; // Centered // Cooldown text var cooldownTxt = new Text2('', { size: 40, fill: 0xAEEFFF }); cooldownTxt.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(cooldownTxt); cooldownTxt.y = -40; cooldownTxt.x = 0; // Helper: update score display function updateScoreDisplay() { scoreTxt.setText(currentScore); if (currentScore > bestScore) { bestScore = currentScore; storage.best = bestScore; bestTxt.setText('Best: ' + bestScore); } } // Helper: center X for a block function getCenterX() { return GAME_WIDTH / 2; } // Helper: spawn a new moving block function spawnMovingBlock(width) { var block = new IceBlock(); block.setSize(width, BLOCK_HEIGHT); block.setColor(BLOCK_COLOR); // Start above the last block, or at START_Y if first var y = START_Y - stack.length * BLOCK_HEIGHT; block.y = y; block.blockHeight = BLOCK_HEIGHT; // Start at left or right edge, alternate each time if (stack.length % 2 === 0) { block.x = 0 + width / 2; movingDirection = 1; } else { block.x = GAME_WIDTH - width / 2; movingDirection = -1; } game.addChild(block); return block; } // Helper: get top block (last in stack) function getTopBlock() { if (stack.length === 0) return null; return stack[stack.length - 1]; } // Helper: drop the moving block function dropBlock() { if (!movingBlock || isDropping) return; isDropping = true; // Find where the block should land (on top of stack or at START_Y) var targetY = START_Y - stack.length * BLOCK_HEIGHT; // Animate drop movingBlock.animateTo(targetY, DROP_ANIMATION_TIME, function () { // After drop, check alignment var prevBlock = getTopBlock(); var overlapLeft, overlapRight, overlapWidth; if (prevBlock) { // Calculate overlap var left = Math.max(movingBlock.getLeft(), prevBlock.getLeft()); var right = Math.min(movingBlock.getRight(), prevBlock.getRight()); overlapWidth = right - left; if (overlapWidth <= 0 || overlapWidth < MIN_BLOCK_WIDTH) { // No overlap or too small: game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } // Shrink block to overlap var newWidth = overlapWidth; var newX = left + overlapWidth / 2; // Animate shrink and move to center of overlap tween(movingBlock, { x: newX }, { duration: SHRINK_ANIMATION_TIME, easing: tween.cubicInOut }); movingBlock.animateShrink(newWidth, SHRINK_ANIMATION_TIME, function () { // Add to stack stack.push(movingBlock); // Play block placed sound LK.getSound('a').play(); currentScore++; updateScoreDisplay(); // Next block nextTurn(newWidth); }); } else { // First block, always succeeds stack.push(movingBlock); // Play block placed sound LK.getSound('a').play(); currentScore = 1; updateScoreDisplay(); nextTurn(movingBlock.blockWidth); } }); } // Helper: start next turn function nextTurn(width) { // Check win condition (optional: e.g. 50 blocks) if (currentScore >= 50) { LK.showYouWin(); return; } // Spawn next moving block movingBlock = spawnMovingBlock(width); isDropping = false; } // Game move handler: tap/click anywhere to drop game.down = function (x, y, obj) { // Check if special button pressed if (specialBtn && obj && obj.target === specialBtn && specialReady && movingBlock && !isDropping) { // Activate special ability: perfect align the block specialReady = false; specialCooldown = SPECIAL_COOLDOWN_TIME; specialBtn.setText('COOLDOWN'); specialBtn.setStyle({ fill: 0x888888 }); // Instantly align moving block to top of stack (or center if first) var prevBlock = getTopBlock(); if (prevBlock) { movingBlock.x = prevBlock.x; movingBlock.blockWidth = prevBlock.blockWidth; movingBlock.setSize(prevBlock.blockWidth, BLOCK_HEIGHT); } else { movingBlock.x = getCenterX(); } // Drop the block as if perfectly aligned dropBlock(); return; } // Normal drop if (!isDropping) { dropBlock(); } }; // Main game update loop game.update = function () { // Move the moving block horizontally if (movingBlock && !isDropping) { movingBlock.x += movingDirection * BLOCK_SPEED; // Bounce at edges var halfW = movingBlock.blockWidth / 2; if (movingBlock.x + halfW > GAME_WIDTH) { movingBlock.x = GAME_WIDTH - halfW; movingDirection = -1; } if (movingBlock.x - halfW < 0) { movingBlock.x = halfW; movingDirection = 1; } } // Update all blocks (for tweened width) for (var i = 0; i < stack.length; i++) { if (stack[i].update) stack[i].update(); } if (movingBlock && movingBlock.update) movingBlock.update(); // Special ability cooldown logic if (!specialReady && specialCooldown > 0) { specialCooldown -= 1000 / 60; // Approx ms per frame at 60fps if (specialCooldown <= 0) { specialReady = true; specialBtn.setText('ICE POWER'); specialBtn.setStyle({ fill: 0x00eaff }); cooldownTxt.setText(''); } else { // Show seconds left var secs = Math.ceil(specialCooldown / 1000); cooldownTxt.setText('Ready in ' + secs + 's'); } } else if (specialReady) { cooldownTxt.setText(''); } }; // Game reset: clear stack and start new game function resetGame() { // Remove all blocks for (var i = 0; i < stack.length; i++) { stack[i].destroy(); } stack = []; if (movingBlock) { movingBlock.destroy(); movingBlock = null; } currentScore = 0; updateScoreDisplay(); // Start first block movingBlock = spawnMovingBlock(START_BLOCK_WIDTH); isDropping = false; // Reset special ability specialReady = true; specialCooldown = 0; if (specialBtn) { specialBtn.setText('ICE POWER'); specialBtn.setStyle({ fill: 0x00eaff }); } if (typeof cooldownTxt !== 'undefined') { cooldownTxt.setText(''); } } // Listen for game over to reset LK.on('gameover', function () { // Delay reset to allow game over screen LK.setTimeout(function () { resetGame(); }, 800); }); // Listen for you win to reset LK.on('youwin', function () { LK.setTimeout(function () { resetGame(); }, 1200); }); // Start the game resetGame();
===================================================================
--- original.js
+++ change.js