/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Block = Container.expand(function (color, width, height) {
var self = Container.call(this);
// Default values if not provided
color = color || 0x4287f5;
width = width || 100;
height = height || 100;
// Create custom block shape with specified color and dimensions
var blockShape = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: height
});
// Set the block's color
blockShape.tint = color;
// Properties
self.isPlaced = false;
self.velocity = {
x: 0,
y: 0
};
self.acceleration = {
x: 0,
y: 0.2
}; // Gravity
self.onGround = false;
self.width = width;
self.height = height;
// Physics update
self.updatePhysics = function () {
if (self.isPlaced && !self.onGround) {
// Apply physics only if the block is placed but not on ground
self.velocity.x += self.acceleration.x;
self.velocity.y += self.acceleration.y;
self.x += self.velocity.x;
self.y += self.velocity.y;
// Check boundaries
if (self.x < self.width / 2) {
self.x = self.width / 2;
self.velocity.x = -self.velocity.x * 0.5; // Bounce with damping
} else if (self.x > 2048 - self.width / 2) {
self.x = 2048 - self.width / 2;
self.velocity.x = -self.velocity.x * 0.5; // Bounce with damping
}
// Check if block has hit the ground
if (self.y >= groundY - self.height / 2) {
self.y = groundY - self.height / 2;
self.velocity.y = 0;
self.velocity.x *= 0.9; // Friction
self.onGround = true;
LK.getSound('fall').play();
}
}
};
// Dragging handlers
self.down = function (x, y, obj) {
if (!self.isPlaced) {
currentDraggedBlock = self;
}
};
return self;
});
var Platform = Container.expand(function (x, y, width) {
var self = Container.call(this);
width = width || 500;
// Create platform shape
var platformShape = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: 20
});
// Position platform
self.x = x;
self.y = y;
// Platform properties
self.width = width;
self.height = 20;
return self;
});
var ScoreZone = Container.expand(function (x, y, width) {
var self = Container.call(this);
width = width || 500;
// Create score zone shape - this will be invisible in the game
var zoneShape = self.attachAsset('scoreZone', {
anchorX: 0.5,
anchorY: 0,
width: width,
height: 2000,
alpha: 0.1 // Almost invisible
});
// Position zone
self.x = x;
self.y = y;
// Zone properties
self.width = width;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game variables
var currentLevel = storage.level || 1;
var score = 0;
var currentDraggedBlock = null;
var blocks = [];
var placedBlocks = [];
var maxStackHeight = 0;
var groundY = 2500;
var platformY = groundY - 20;
var centerX = 2048 / 2;
var levelCompleted = false;
var windStrength = 0;
var windDirection = 1;
var blockColors = [0x4287f5, 0xff5757, 0x57ff57, 0xffff57, 0xff57ff, 0x57ffff];
var nextBlockColor = blockColors[Math.floor(Math.random() * blockColors.length)];
var nextBlockWidth = 100;
var nextBlockHeight = 100;
var blockWidths = [80, 100, 120, 150];
var blockHeights = [60, 80, 100, 120];
// Set up game environment
game.setBackgroundColor(0x87CEEB); // Sky blue background
// Create ground
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0,
width: 2048,
height: 100
}));
ground.x = centerX;
ground.y = groundY;
// Create main platform
var mainPlatform = game.addChild(new Platform(centerX, platformY, 500));
// Create score zone (for checking if blocks are within scoring area)
var scoreZone = game.addChild(new ScoreZone(centerX, 0, 500));
// Score display
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0); // Top right anchor
LK.gui.topRight.addChild(scoreTxt);
// Level display
var levelTxt = new Text2('Level: ' + currentLevel, {
size: 70,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0); // Top left anchor
LK.gui.topRight.addChild(levelTxt);
levelTxt.y = 80; // Position below score
// Height display
var heightTxt = new Text2('Tower Height: 0m', {
size: 50,
fill: 0xFFFFFF
});
heightTxt.anchor.set(0.5, 0); // Top center anchor
LK.gui.top.addChild(heightTxt);
heightTxt.y = 20;
// Message text for level completion, etc.
var messageTxt = new Text2('', {
size: 80,
fill: 0xFFFF00
});
messageTxt.anchor.set(0.5, 0.5); // Center anchor
LK.gui.center.addChild(messageTxt);
messageTxt.alpha = 0;
// Create initial block
function createNewBlock() {
var newBlock = new Block(nextBlockColor, nextBlockWidth, nextBlockHeight);
newBlock.x = centerX;
newBlock.y = 200;
// Set next block's properties
nextBlockColor = blockColors[Math.floor(Math.random() * blockColors.length)];
// As levels progress, vary block sizes more
if (currentLevel > 1) {
nextBlockWidth = blockWidths[Math.floor(Math.random() * blockWidths.length)];
nextBlockHeight = blockHeights[Math.floor(Math.random() * blockHeights.length)];
}
blocks.push(newBlock);
game.addChild(newBlock);
return newBlock;
}
// Create first block
createNewBlock();
// Update score
function updateScore(points) {
score += points;
scoreTxt.setText('Score: ' + score);
}
// Update level
function setLevel(level) {
currentLevel = level;
storage.level = level;
levelTxt.setText('Level: ' + currentLevel);
// Adjust difficulty based on level
windStrength = (currentLevel - 1) * 0.02;
}
// Check tower height and update
function updateTowerHeight() {
if (placedBlocks.length === 0) {
return 0;
}
// Find the highest block's top edge
var highestY = groundY;
for (var i = 0; i < placedBlocks.length; i++) {
var blockTopY = placedBlocks[i].y - placedBlocks[i].height / 2;
if (blockTopY < highestY) {
highestY = blockTopY;
}
}
// Calculate height from ground
var height = groundY - highestY;
var heightInMeters = Math.floor(height / 50); // Convert pixels to "meters" for display
heightTxt.setText('Tower Height: ' + heightInMeters + 'm');
// Update max height if needed
if (height > maxStackHeight) {
maxStackHeight = height;
// Check for level completion
var requiredHeight = 200 + currentLevel * 100;
if (maxStackHeight >= requiredHeight && !levelCompleted) {
levelCompleted = true;
showLevelCompleteMessage();
}
}
return height;
}
// Show level complete message
function showLevelCompleteMessage() {
messageTxt.setText('Level ' + currentLevel + ' Complete!');
messageTxt.alpha = 1;
// Play success sound
LK.getSound('success').play();
// Award bonus points for level completion
updateScore(currentLevel * 100);
// Set timeout to advance to next level
LK.setTimeout(function () {
setLevel(currentLevel + 1);
levelCompleted = false;
// Hide message with fade
tween(messageTxt, {
alpha: 0
}, {
duration: 1000
});
// Create new block if needed
if (blocks.length === 0) {
createNewBlock();
}
}, 3000);
}
// Check stability of the tower
function checkTowerStability() {
// Simple implementation: if blocks are stacked too high without sufficient width, they become unstable
var unstableBlocks = 0;
for (var i = 0; i < placedBlocks.length; i++) {
var block = placedBlocks[i];
// Skip blocks that are already on the ground
if (block.onGround) {
continue;
}
var isSupported = false;
// Check if block is supported by platform
if (block.y + block.height / 2 >= platformY - 10 && block.x + block.width / 2 >= mainPlatform.x - mainPlatform.width / 2 && block.x - block.width / 2 <= mainPlatform.x + mainPlatform.width / 2) {
isSupported = true;
} else {
// Check if supported by other blocks
for (var j = 0; j < placedBlocks.length; j++) {
if (i !== j) {
var supportBlock = placedBlocks[j];
// Simple overlap check
if (block.y + block.height / 2 >= supportBlock.y - supportBlock.height / 2 - 5 && block.y + block.height / 2 <= supportBlock.y - supportBlock.height / 2 + 5 && block.x + block.width / 2 >= supportBlock.x - supportBlock.width / 2 && block.x - block.width / 2 <= supportBlock.x + supportBlock.width / 2) {
isSupported = true;
break;
}
}
}
}
if (!isSupported) {
// Make block fall
block.velocity.y = 1;
block.onGround = false;
unstableBlocks++;
}
}
return unstableBlocks;
}
// Apply wind effects based on level
function applyWindEffects() {
if (windStrength > 0) {
// Occasionally change wind direction
if (Math.random() < 0.01) {
windDirection = -windDirection;
}
// Apply wind force to blocks
for (var i = 0; i < placedBlocks.length; i++) {
var block = placedBlocks[i];
if (!block.onGround) {
block.velocity.x += windDirection * windStrength;
}
}
}
}
// Handle touch/mouse move
function handleMove(x, y, obj) {
if (currentDraggedBlock) {
currentDraggedBlock.x = x;
currentDraggedBlock.y = y;
}
}
// Game event handlers
game.move = handleMove;
game.down = function (x, y, obj) {
// Already handled in Block class
};
game.up = function (x, y, obj) {
if (currentDraggedBlock && !currentDraggedBlock.isPlaced) {
// Place the block
currentDraggedBlock.isPlaced = true;
placedBlocks.push(currentDraggedBlock);
// Play placement sound
LK.getSound('place').play();
// Check if block is within score zone
var inScoreZone = currentDraggedBlock.x + currentDraggedBlock.width / 2 >= scoreZone.x - scoreZone.width / 2 && currentDraggedBlock.x - currentDraggedBlock.width / 2 <= scoreZone.x + scoreZone.width / 2;
// Award points based on placement height and zone
var points = 10;
if (inScoreZone) {
points += 20;
}
// Bonus points for height
var height = groundY - currentDraggedBlock.y;
points += Math.floor(height / 50) * 5;
updateScore(points);
// Create a new block after a short delay
LK.setTimeout(function () {
if (!levelCompleted && blocks.length < 2) {
createNewBlock();
}
}, 500);
currentDraggedBlock = null;
}
};
// Main game update loop
game.update = function () {
// Skip updates if game is in level transition
if (messageTxt.alpha > 0) {
return;
}
// Update all placed blocks
for (var i = 0; i < placedBlocks.length; i++) {
placedBlocks[i].updatePhysics();
}
// Check tower stability
checkTowerStability();
// Apply wind effects
applyWindEffects();
// Update tower height
updateTowerHeight();
// Check for game over (structure collapse)
var unstableCount = 0;
for (var j = 0; j < placedBlocks.length; j++) {
if (placedBlocks[j].onGround && (placedBlocks[j].x < centerX - 500 || placedBlocks[j].x > centerX + 500)) {
unstableCount++;
}
}
// If too many blocks have fallen off the platform, game over
if (unstableCount > 3 && placedBlocks.length > 5) {
LK.showGameOver();
}
// Every 5 seconds, check if tower is completely stable
if (LK.ticks % 300 === 0 && placedBlocks.length > 0) {
var allStable = true;
for (var k = 0; k < placedBlocks.length; k++) {
if (!placedBlocks[k].onGround && (Math.abs(placedBlocks[k].velocity.x) > 0.1 || Math.abs(placedBlocks[k].velocity.y) > 0.1)) {
allStable = false;
break;
}
}
// If tower is completely stable and tall enough, award stability bonus
if (allStable && maxStackHeight > 200) {
updateScore(25);
// Show small message
messageTxt.setText('Stability Bonus: +25');
messageTxt.alpha = 1;
// Fade out message
tween(messageTxt, {
alpha: 0
}, {
duration: 1500
});
}
}
};
// Play background music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.3,
duration: 2000
}
}); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,417 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var Block = Container.expand(function (color, width, height) {
+ var self = Container.call(this);
+ // Default values if not provided
+ color = color || 0x4287f5;
+ width = width || 100;
+ height = height || 100;
+ // Create custom block shape with specified color and dimensions
+ var blockShape = self.attachAsset('block', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: width,
+ height: height
+ });
+ // Set the block's color
+ blockShape.tint = color;
+ // Properties
+ self.isPlaced = false;
+ self.velocity = {
+ x: 0,
+ y: 0
+ };
+ self.acceleration = {
+ x: 0,
+ y: 0.2
+ }; // Gravity
+ self.onGround = false;
+ self.width = width;
+ self.height = height;
+ // Physics update
+ self.updatePhysics = function () {
+ if (self.isPlaced && !self.onGround) {
+ // Apply physics only if the block is placed but not on ground
+ self.velocity.x += self.acceleration.x;
+ self.velocity.y += self.acceleration.y;
+ self.x += self.velocity.x;
+ self.y += self.velocity.y;
+ // Check boundaries
+ if (self.x < self.width / 2) {
+ self.x = self.width / 2;
+ self.velocity.x = -self.velocity.x * 0.5; // Bounce with damping
+ } else if (self.x > 2048 - self.width / 2) {
+ self.x = 2048 - self.width / 2;
+ self.velocity.x = -self.velocity.x * 0.5; // Bounce with damping
+ }
+ // Check if block has hit the ground
+ if (self.y >= groundY - self.height / 2) {
+ self.y = groundY - self.height / 2;
+ self.velocity.y = 0;
+ self.velocity.x *= 0.9; // Friction
+ self.onGround = true;
+ LK.getSound('fall').play();
+ }
+ }
+ };
+ // Dragging handlers
+ self.down = function (x, y, obj) {
+ if (!self.isPlaced) {
+ currentDraggedBlock = self;
+ }
+ };
+ return self;
+});
+var Platform = Container.expand(function (x, y, width) {
+ var self = Container.call(this);
+ width = width || 500;
+ // Create platform shape
+ var platformShape = self.attachAsset('platform', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: width,
+ height: 20
+ });
+ // Position platform
+ self.x = x;
+ self.y = y;
+ // Platform properties
+ self.width = width;
+ self.height = 20;
+ return self;
+});
+var ScoreZone = Container.expand(function (x, y, width) {
+ var self = Container.call(this);
+ width = width || 500;
+ // Create score zone shape - this will be invisible in the game
+ var zoneShape = self.attachAsset('scoreZone', {
+ anchorX: 0.5,
+ anchorY: 0,
+ width: width,
+ height: 2000,
+ alpha: 0.1 // Almost invisible
+ });
+ // Position zone
+ self.x = x;
+ self.y = y;
+ // Zone properties
+ self.width = width;
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x87CEEB // Sky blue background
+});
+
+/****
+* Game Code
+****/
+// Game variables
+var currentLevel = storage.level || 1;
+var score = 0;
+var currentDraggedBlock = null;
+var blocks = [];
+var placedBlocks = [];
+var maxStackHeight = 0;
+var groundY = 2500;
+var platformY = groundY - 20;
+var centerX = 2048 / 2;
+var levelCompleted = false;
+var windStrength = 0;
+var windDirection = 1;
+var blockColors = [0x4287f5, 0xff5757, 0x57ff57, 0xffff57, 0xff57ff, 0x57ffff];
+var nextBlockColor = blockColors[Math.floor(Math.random() * blockColors.length)];
+var nextBlockWidth = 100;
+var nextBlockHeight = 100;
+var blockWidths = [80, 100, 120, 150];
+var blockHeights = [60, 80, 100, 120];
+// Set up game environment
+game.setBackgroundColor(0x87CEEB); // Sky blue background
+// Create ground
+var ground = game.addChild(LK.getAsset('ground', {
+ anchorX: 0.5,
+ anchorY: 0,
+ width: 2048,
+ height: 100
+}));
+ground.x = centerX;
+ground.y = groundY;
+// Create main platform
+var mainPlatform = game.addChild(new Platform(centerX, platformY, 500));
+// Create score zone (for checking if blocks are within scoring area)
+var scoreZone = game.addChild(new ScoreZone(centerX, 0, 500));
+// Score display
+var scoreTxt = new Text2('Score: 0', {
+ size: 70,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(1, 0); // Top right anchor
+LK.gui.topRight.addChild(scoreTxt);
+// Level display
+var levelTxt = new Text2('Level: ' + currentLevel, {
+ size: 70,
+ fill: 0xFFFFFF
+});
+levelTxt.anchor.set(0, 0); // Top left anchor
+LK.gui.topRight.addChild(levelTxt);
+levelTxt.y = 80; // Position below score
+// Height display
+var heightTxt = new Text2('Tower Height: 0m', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+heightTxt.anchor.set(0.5, 0); // Top center anchor
+LK.gui.top.addChild(heightTxt);
+heightTxt.y = 20;
+// Message text for level completion, etc.
+var messageTxt = new Text2('', {
+ size: 80,
+ fill: 0xFFFF00
+});
+messageTxt.anchor.set(0.5, 0.5); // Center anchor
+LK.gui.center.addChild(messageTxt);
+messageTxt.alpha = 0;
+// Create initial block
+function createNewBlock() {
+ var newBlock = new Block(nextBlockColor, nextBlockWidth, nextBlockHeight);
+ newBlock.x = centerX;
+ newBlock.y = 200;
+ // Set next block's properties
+ nextBlockColor = blockColors[Math.floor(Math.random() * blockColors.length)];
+ // As levels progress, vary block sizes more
+ if (currentLevel > 1) {
+ nextBlockWidth = blockWidths[Math.floor(Math.random() * blockWidths.length)];
+ nextBlockHeight = blockHeights[Math.floor(Math.random() * blockHeights.length)];
+ }
+ blocks.push(newBlock);
+ game.addChild(newBlock);
+ return newBlock;
+}
+// Create first block
+createNewBlock();
+// Update score
+function updateScore(points) {
+ score += points;
+ scoreTxt.setText('Score: ' + score);
+}
+// Update level
+function setLevel(level) {
+ currentLevel = level;
+ storage.level = level;
+ levelTxt.setText('Level: ' + currentLevel);
+ // Adjust difficulty based on level
+ windStrength = (currentLevel - 1) * 0.02;
+}
+// Check tower height and update
+function updateTowerHeight() {
+ if (placedBlocks.length === 0) {
+ return 0;
+ }
+ // Find the highest block's top edge
+ var highestY = groundY;
+ for (var i = 0; i < placedBlocks.length; i++) {
+ var blockTopY = placedBlocks[i].y - placedBlocks[i].height / 2;
+ if (blockTopY < highestY) {
+ highestY = blockTopY;
+ }
+ }
+ // Calculate height from ground
+ var height = groundY - highestY;
+ var heightInMeters = Math.floor(height / 50); // Convert pixels to "meters" for display
+ heightTxt.setText('Tower Height: ' + heightInMeters + 'm');
+ // Update max height if needed
+ if (height > maxStackHeight) {
+ maxStackHeight = height;
+ // Check for level completion
+ var requiredHeight = 200 + currentLevel * 100;
+ if (maxStackHeight >= requiredHeight && !levelCompleted) {
+ levelCompleted = true;
+ showLevelCompleteMessage();
+ }
+ }
+ return height;
+}
+// Show level complete message
+function showLevelCompleteMessage() {
+ messageTxt.setText('Level ' + currentLevel + ' Complete!');
+ messageTxt.alpha = 1;
+ // Play success sound
+ LK.getSound('success').play();
+ // Award bonus points for level completion
+ updateScore(currentLevel * 100);
+ // Set timeout to advance to next level
+ LK.setTimeout(function () {
+ setLevel(currentLevel + 1);
+ levelCompleted = false;
+ // Hide message with fade
+ tween(messageTxt, {
+ alpha: 0
+ }, {
+ duration: 1000
+ });
+ // Create new block if needed
+ if (blocks.length === 0) {
+ createNewBlock();
+ }
+ }, 3000);
+}
+// Check stability of the tower
+function checkTowerStability() {
+ // Simple implementation: if blocks are stacked too high without sufficient width, they become unstable
+ var unstableBlocks = 0;
+ for (var i = 0; i < placedBlocks.length; i++) {
+ var block = placedBlocks[i];
+ // Skip blocks that are already on the ground
+ if (block.onGround) {
+ continue;
+ }
+ var isSupported = false;
+ // Check if block is supported by platform
+ if (block.y + block.height / 2 >= platformY - 10 && block.x + block.width / 2 >= mainPlatform.x - mainPlatform.width / 2 && block.x - block.width / 2 <= mainPlatform.x + mainPlatform.width / 2) {
+ isSupported = true;
+ } else {
+ // Check if supported by other blocks
+ for (var j = 0; j < placedBlocks.length; j++) {
+ if (i !== j) {
+ var supportBlock = placedBlocks[j];
+ // Simple overlap check
+ if (block.y + block.height / 2 >= supportBlock.y - supportBlock.height / 2 - 5 && block.y + block.height / 2 <= supportBlock.y - supportBlock.height / 2 + 5 && block.x + block.width / 2 >= supportBlock.x - supportBlock.width / 2 && block.x - block.width / 2 <= supportBlock.x + supportBlock.width / 2) {
+ isSupported = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!isSupported) {
+ // Make block fall
+ block.velocity.y = 1;
+ block.onGround = false;
+ unstableBlocks++;
+ }
+ }
+ return unstableBlocks;
+}
+// Apply wind effects based on level
+function applyWindEffects() {
+ if (windStrength > 0) {
+ // Occasionally change wind direction
+ if (Math.random() < 0.01) {
+ windDirection = -windDirection;
+ }
+ // Apply wind force to blocks
+ for (var i = 0; i < placedBlocks.length; i++) {
+ var block = placedBlocks[i];
+ if (!block.onGround) {
+ block.velocity.x += windDirection * windStrength;
+ }
+ }
+ }
+}
+// Handle touch/mouse move
+function handleMove(x, y, obj) {
+ if (currentDraggedBlock) {
+ currentDraggedBlock.x = x;
+ currentDraggedBlock.y = y;
+ }
+}
+// Game event handlers
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ // Already handled in Block class
+};
+game.up = function (x, y, obj) {
+ if (currentDraggedBlock && !currentDraggedBlock.isPlaced) {
+ // Place the block
+ currentDraggedBlock.isPlaced = true;
+ placedBlocks.push(currentDraggedBlock);
+ // Play placement sound
+ LK.getSound('place').play();
+ // Check if block is within score zone
+ var inScoreZone = currentDraggedBlock.x + currentDraggedBlock.width / 2 >= scoreZone.x - scoreZone.width / 2 && currentDraggedBlock.x - currentDraggedBlock.width / 2 <= scoreZone.x + scoreZone.width / 2;
+ // Award points based on placement height and zone
+ var points = 10;
+ if (inScoreZone) {
+ points += 20;
+ }
+ // Bonus points for height
+ var height = groundY - currentDraggedBlock.y;
+ points += Math.floor(height / 50) * 5;
+ updateScore(points);
+ // Create a new block after a short delay
+ LK.setTimeout(function () {
+ if (!levelCompleted && blocks.length < 2) {
+ createNewBlock();
+ }
+ }, 500);
+ currentDraggedBlock = null;
+ }
+};
+// Main game update loop
+game.update = function () {
+ // Skip updates if game is in level transition
+ if (messageTxt.alpha > 0) {
+ return;
+ }
+ // Update all placed blocks
+ for (var i = 0; i < placedBlocks.length; i++) {
+ placedBlocks[i].updatePhysics();
+ }
+ // Check tower stability
+ checkTowerStability();
+ // Apply wind effects
+ applyWindEffects();
+ // Update tower height
+ updateTowerHeight();
+ // Check for game over (structure collapse)
+ var unstableCount = 0;
+ for (var j = 0; j < placedBlocks.length; j++) {
+ if (placedBlocks[j].onGround && (placedBlocks[j].x < centerX - 500 || placedBlocks[j].x > centerX + 500)) {
+ unstableCount++;
+ }
+ }
+ // If too many blocks have fallen off the platform, game over
+ if (unstableCount > 3 && placedBlocks.length > 5) {
+ LK.showGameOver();
+ }
+ // Every 5 seconds, check if tower is completely stable
+ if (LK.ticks % 300 === 0 && placedBlocks.length > 0) {
+ var allStable = true;
+ for (var k = 0; k < placedBlocks.length; k++) {
+ if (!placedBlocks[k].onGround && (Math.abs(placedBlocks[k].velocity.x) > 0.1 || Math.abs(placedBlocks[k].velocity.y) > 0.1)) {
+ allStable = false;
+ break;
+ }
+ }
+ // If tower is completely stable and tall enough, award stability bonus
+ if (allStable && maxStackHeight > 200) {
+ updateScore(25);
+ // Show small message
+ messageTxt.setText('Stability Bonus: +25');
+ messageTxt.alpha = 1;
+ // Fade out message
+ tween(messageTxt, {
+ alpha: 0
+ }, {
+ duration: 1500
+ });
+ }
+ }
+};
+// Play background music
+LK.playMusic('bgmusic', {
+ fade: {
+ start: 0,
+ end: 0.3,
+ duration: 2000
+ }
});
\ No newline at end of file