/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // IceBlock: Represents a single moving or stacked ice block var IceBlock = Container.expand(function () { var self = Container.call(this); // Attach the ice block asset var block = self.attachAsset('iceBlock', { anchorX: 0.5, anchorY: 1 }); // Set block size (will be updated on creation) self.setSize = function (w, h) { block.width = w; block.height = h; self.width = w; self.height = h; }; // Animate block drop self.dropTo = function (targetY, duration, onFinish) { tween(self, { y: targetY }, { duration: duration, easing: tween.cubicIn, onFinish: onFinish }); }; // Animate block shake (for miss) self.shake = function () { var origX = self.x; tween(self, { x: origX - 30 }, { duration: 60, easing: tween.linear, onFinish: function onFinish() { tween(self, { x: origX + 30 }, { duration: 60, easing: tween.linear, onFinish: function onFinish() { tween(self, { x: origX }, { duration: 60 }); } }); } }); }; return self; }); // IceShard: Represents a falling broken piece var IceShard = Container.expand(function () { var self = Container.call(this); var shard = self.attachAsset('iceShard', { anchorX: 0.5, anchorY: 1 }); self.setSize = function (w, h) { shard.width = w; shard.height = h; self.width = w; self.height = h; }; // Animate falling and fading out self.fallAndFade = function (_onFinish) { tween(self, { y: self.y + 400, alpha: 0 }, { duration: 600, easing: tween.cubicIn, onFinish: function onFinish() { if (_onFinish) _onFinish(); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a2a3a }); /**** * Game Code ****/ // Shard (falling broken piece) // Tower base (static base block) // Ice block (main block for stacking) // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var BASE_Y = GAME_HEIGHT - 200; var BLOCK_START_Y = 400; var BLOCK_MIN_WIDTH = 120; var BLOCK_HEIGHT = 100; var BLOCK_MOVE_SPEED = 12; // px per frame // Game state var stack = []; // Array of stacked blocks (bottom to top) var movingBlock = null; // The currently moving block var movingDir = 1; // 1: right, -1: left var movingSpeed = BLOCK_MOVE_SPEED; var blockWidth = 600; var blockHeight = BLOCK_HEIGHT; var blockX = GAME_WIDTH / 2; var blockY = BLOCK_START_Y; var canDrop = true; var score = 0; var gameOver = false; // Score display var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Tower base var baseBlock = new IceBlock(); baseBlock.setSize(700, 120); baseBlock.x = GAME_WIDTH / 2; baseBlock.y = BASE_Y; game.addChild(baseBlock); stack.push(baseBlock); // Helper: Add a new moving block at the top function spawnMovingBlock() { blockWidth = stack[stack.length - 1].width; if (blockWidth < BLOCK_MIN_WIDTH) { endGame(); return; } blockHeight = BLOCK_HEIGHT; blockX = 0 + blockWidth / 2 + 80; // Start from left blockY = BLOCK_START_Y; movingDir = 1; movingSpeed = BLOCK_MOVE_SPEED + Math.floor(score / 10) * 2; // Slightly faster as score increases movingBlock = new IceBlock(); movingBlock.setSize(blockWidth, blockHeight); movingBlock.x = blockX; movingBlock.y = blockY; movingBlock.alpha = 1; game.addChild(movingBlock); canDrop = true; } // Helper: End the game function endGame() { if (gameOver) return; gameOver = true; LK.showGameOver(); } // Helper: Update score display function updateScore() { scoreTxt.setText(score); } // Helper: Drop the moving block function dropBlock() { if (!movingBlock || !canDrop || gameOver) return; canDrop = false; // Find the top block to stack on var prevBlock = stack[stack.length - 1]; var prevX = prevBlock.x; var prevY = prevBlock.y; var prevW = prevBlock.width; // Target Y for stacking var targetY = prevY - blockHeight; // Animate drop movingBlock.dropTo(targetY, 220, function () { // Check overlap var leftEdge = movingBlock.x - blockWidth / 2; var rightEdge = movingBlock.x + blockWidth / 2; var prevLeft = prevX - prevW / 2; var prevRight = prevX + prevW / 2; var overlapLeft = Math.max(leftEdge, prevLeft); var overlapRight = Math.min(rightEdge, prevRight); var overlapWidth = overlapRight - overlapLeft; if (overlapWidth <= 0) { // Missed completely movingBlock.shake(); tween(movingBlock, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { endGame(); } }); return; } // If overhang, break off the left or right part var overhangLeft = overlapLeft - leftEdge; var overhangRight = rightEdge - overlapRight; // Animate left shard if (overhangLeft > 2) { var shardL = new IceShard(); shardL.setSize(overhangLeft, blockHeight); shardL.x = leftEdge + overhangLeft / 2; shardL.y = targetY; game.addChild(shardL); shardL.fallAndFade(function () { shardL.destroy(); }); } // Animate right shard if (overhangRight > 2) { var shardR = new IceShard(); shardR.setSize(overhangRight, blockHeight); shardR.x = rightEdge - overhangRight / 2; shardR.y = targetY; game.addChild(shardR); shardR.fallAndFade(function () { shardR.destroy(); }); } // Shrink the block to the overlap movingBlock.setSize(overlapWidth, blockHeight); movingBlock.x = overlapLeft + overlapWidth / 2; movingBlock.y = targetY; stack.push(movingBlock); // Update score score += 1; updateScore(); // Move camera up if needed (optional: not implemented, as LK handles scaling) // Spawn next block spawnMovingBlock(); }); } // Handle tap/click to drop block game.down = function (x, y, obj) { if (canDrop && !gameOver) { dropBlock(); } }; // Main game update loop game.update = function () { if (gameOver) return; // Move the moving block horizontally if (movingBlock && canDrop) { blockX += movingDir * movingSpeed; // Clamp and bounce at edges var minX = blockWidth / 2 + 80; var maxX = GAME_WIDTH - blockWidth / 2 - 80; if (blockX > maxX) { blockX = maxX; movingDir = -1; } if (blockX < minX) { blockX = minX; movingDir = 1; } movingBlock.x = blockX; } }; // Start the game function startGame() { // Reset state for (var i = stack.length - 1; i >= 1; i--) { stack[i].destroy(); stack.splice(i, 1); } if (movingBlock) { movingBlock.destroy(); movingBlock = null; } score = 0; updateScore(); gameOver = false; spawnMovingBlock(); } // On game start startGame(); // On game over, restart game when LK resets // (LK will re-initialize the Game class, so no need to handle reset here)
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,284 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// IceBlock: Represents a single moving or stacked ice block
+var IceBlock = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach the ice block asset
+ var block = self.attachAsset('iceBlock', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ // Set block size (will be updated on creation)
+ self.setSize = function (w, h) {
+ block.width = w;
+ block.height = h;
+ self.width = w;
+ self.height = h;
+ };
+ // Animate block drop
+ self.dropTo = function (targetY, duration, onFinish) {
+ tween(self, {
+ y: targetY
+ }, {
+ duration: duration,
+ easing: tween.cubicIn,
+ onFinish: onFinish
+ });
+ };
+ // Animate block shake (for miss)
+ self.shake = function () {
+ var origX = self.x;
+ tween(self, {
+ x: origX - 30
+ }, {
+ duration: 60,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ tween(self, {
+ x: origX + 30
+ }, {
+ duration: 60,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ tween(self, {
+ x: origX
+ }, {
+ duration: 60
+ });
+ }
+ });
+ }
+ });
+ };
+ return self;
+});
+// IceShard: Represents a falling broken piece
+var IceShard = Container.expand(function () {
+ var self = Container.call(this);
+ var shard = self.attachAsset('iceShard', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.setSize = function (w, h) {
+ shard.width = w;
+ shard.height = h;
+ self.width = w;
+ self.height = h;
+ };
+ // Animate falling and fading out
+ self.fallAndFade = function (_onFinish) {
+ tween(self, {
+ y: self.y + 400,
+ alpha: 0
+ }, {
+ duration: 600,
+ easing: tween.cubicIn,
+ onFinish: function onFinish() {
+ if (_onFinish) _onFinish();
+ }
+ });
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x1a2a3a
+});
+
+/****
+* Game Code
+****/
+// Shard (falling broken piece)
+// Tower base (static base block)
+// Ice block (main block for stacking)
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var BASE_Y = GAME_HEIGHT - 200;
+var BLOCK_START_Y = 400;
+var BLOCK_MIN_WIDTH = 120;
+var BLOCK_HEIGHT = 100;
+var BLOCK_MOVE_SPEED = 12; // px per frame
+// Game state
+var stack = []; // Array of stacked blocks (bottom to top)
+var movingBlock = null; // The currently moving block
+var movingDir = 1; // 1: right, -1: left
+var movingSpeed = BLOCK_MOVE_SPEED;
+var blockWidth = 600;
+var blockHeight = BLOCK_HEIGHT;
+var blockX = GAME_WIDTH / 2;
+var blockY = BLOCK_START_Y;
+var canDrop = true;
+var score = 0;
+var gameOver = false;
+// Score display
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Tower base
+var baseBlock = new IceBlock();
+baseBlock.setSize(700, 120);
+baseBlock.x = GAME_WIDTH / 2;
+baseBlock.y = BASE_Y;
+game.addChild(baseBlock);
+stack.push(baseBlock);
+// Helper: Add a new moving block at the top
+function spawnMovingBlock() {
+ blockWidth = stack[stack.length - 1].width;
+ if (blockWidth < BLOCK_MIN_WIDTH) {
+ endGame();
+ return;
+ }
+ blockHeight = BLOCK_HEIGHT;
+ blockX = 0 + blockWidth / 2 + 80; // Start from left
+ blockY = BLOCK_START_Y;
+ movingDir = 1;
+ movingSpeed = BLOCK_MOVE_SPEED + Math.floor(score / 10) * 2; // Slightly faster as score increases
+ movingBlock = new IceBlock();
+ movingBlock.setSize(blockWidth, blockHeight);
+ movingBlock.x = blockX;
+ movingBlock.y = blockY;
+ movingBlock.alpha = 1;
+ game.addChild(movingBlock);
+ canDrop = true;
+}
+// Helper: End the game
+function endGame() {
+ if (gameOver) return;
+ gameOver = true;
+ LK.showGameOver();
+}
+// Helper: Update score display
+function updateScore() {
+ scoreTxt.setText(score);
+}
+// Helper: Drop the moving block
+function dropBlock() {
+ if (!movingBlock || !canDrop || gameOver) return;
+ canDrop = false;
+ // Find the top block to stack on
+ var prevBlock = stack[stack.length - 1];
+ var prevX = prevBlock.x;
+ var prevY = prevBlock.y;
+ var prevW = prevBlock.width;
+ // Target Y for stacking
+ var targetY = prevY - blockHeight;
+ // Animate drop
+ movingBlock.dropTo(targetY, 220, function () {
+ // Check overlap
+ var leftEdge = movingBlock.x - blockWidth / 2;
+ var rightEdge = movingBlock.x + blockWidth / 2;
+ var prevLeft = prevX - prevW / 2;
+ var prevRight = prevX + prevW / 2;
+ var overlapLeft = Math.max(leftEdge, prevLeft);
+ var overlapRight = Math.min(rightEdge, prevRight);
+ var overlapWidth = overlapRight - overlapLeft;
+ if (overlapWidth <= 0) {
+ // Missed completely
+ movingBlock.shake();
+ tween(movingBlock, {
+ alpha: 0
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ endGame();
+ }
+ });
+ return;
+ }
+ // If overhang, break off the left or right part
+ var overhangLeft = overlapLeft - leftEdge;
+ var overhangRight = rightEdge - overlapRight;
+ // Animate left shard
+ if (overhangLeft > 2) {
+ var shardL = new IceShard();
+ shardL.setSize(overhangLeft, blockHeight);
+ shardL.x = leftEdge + overhangLeft / 2;
+ shardL.y = targetY;
+ game.addChild(shardL);
+ shardL.fallAndFade(function () {
+ shardL.destroy();
+ });
+ }
+ // Animate right shard
+ if (overhangRight > 2) {
+ var shardR = new IceShard();
+ shardR.setSize(overhangRight, blockHeight);
+ shardR.x = rightEdge - overhangRight / 2;
+ shardR.y = targetY;
+ game.addChild(shardR);
+ shardR.fallAndFade(function () {
+ shardR.destroy();
+ });
+ }
+ // Shrink the block to the overlap
+ movingBlock.setSize(overlapWidth, blockHeight);
+ movingBlock.x = overlapLeft + overlapWidth / 2;
+ movingBlock.y = targetY;
+ stack.push(movingBlock);
+ // Update score
+ score += 1;
+ updateScore();
+ // Move camera up if needed (optional: not implemented, as LK handles scaling)
+ // Spawn next block
+ spawnMovingBlock();
+ });
+}
+// Handle tap/click to drop block
+game.down = function (x, y, obj) {
+ if (canDrop && !gameOver) {
+ dropBlock();
+ }
+};
+// Main game update loop
+game.update = function () {
+ if (gameOver) return;
+ // Move the moving block horizontally
+ if (movingBlock && canDrop) {
+ blockX += movingDir * movingSpeed;
+ // Clamp and bounce at edges
+ var minX = blockWidth / 2 + 80;
+ var maxX = GAME_WIDTH - blockWidth / 2 - 80;
+ if (blockX > maxX) {
+ blockX = maxX;
+ movingDir = -1;
+ }
+ if (blockX < minX) {
+ blockX = minX;
+ movingDir = 1;
+ }
+ movingBlock.x = blockX;
+ }
+};
+// Start the game
+function startGame() {
+ // Reset state
+ for (var i = stack.length - 1; i >= 1; i--) {
+ stack[i].destroy();
+ stack.splice(i, 1);
+ }
+ if (movingBlock) {
+ movingBlock.destroy();
+ movingBlock = null;
+ }
+ score = 0;
+ updateScore();
+ gameOver = false;
+ spawnMovingBlock();
+}
+// On game start
+startGame();
+// On game over, restart game when LK resets
+// (LK will re-initialize the Game class, so no need to handle reset here)
\ No newline at end of file