/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Block = Container.expand(function (blockType) { var self = Container.call(this); var blockGraphics = self.attachAsset(blockType + 'Block', { anchorX: 0.5, anchorY: 0.5 }); self.blockType = blockType; self.gridX = -1; self.gridY = -1; self.isPlaced = false; self.isDragging = false; self.fallSpeed = 0; self.isStable = true; self.lastStable = true; self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = GRID_START_X + gridX * GRID_SIZE + GRID_SIZE / 2; self.y = GRID_START_Y + gridY * GRID_SIZE + GRID_SIZE / 2; }; self.checkStability = function () { if (self.gridY >= GRID_HEIGHT - 1) { return true; // Ground level is stable } // Check if there's a block below for (var i = 0; i < placedBlocks.length; i++) { var otherBlock = placedBlocks[i]; if (otherBlock !== self && otherBlock.gridX === self.gridX && otherBlock.gridY === self.gridY + 1) { return true; } } return false; }; self.update = function () { if (!self.isPlaced || self.isDragging) return; self.lastStable = self.isStable; self.isStable = self.checkStability(); // If block becomes unstable, make it fall if (self.lastStable && !self.isStable) { self.fallSpeed = 2; } // Apply falling physics if (!self.isStable && self.fallSpeed > 0) { self.y += self.fallSpeed; self.fallSpeed += 0.5; // Gravity // Check if block has hit the ground or another block var targetY = GRID_START_Y + (GRID_HEIGHT - 1) * GRID_SIZE + GRID_SIZE / 2; if (self.y >= targetY) { self.y = targetY; self.gridY = GRID_HEIGHT - 1; self.fallSpeed = 0; self.isStable = true; LK.getSound('place').play(); updateScore(); } else { // Check collision with other blocks for (var i = 0; i < placedBlocks.length; i++) { var otherBlock = placedBlocks[i]; if (otherBlock !== self && Math.abs(otherBlock.x - self.x) < GRID_SIZE && Math.abs(otherBlock.y - self.y) < GRID_SIZE && self.y >= otherBlock.y - GRID_SIZE) { self.y = otherBlock.y - GRID_SIZE; self.gridY = otherBlock.gridY - 1; self.fallSpeed = 0; self.isStable = true; LK.getSound('place').play(); updateScore(); break; } } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game constants var GRID_SIZE = 120; var GRID_WIDTH = 16; var GRID_HEIGHT = 14; var GRID_START_X = 64; var GRID_START_Y = 300; var PALETTE_HEIGHT = 200; // Game variables var placedBlocks = []; var draggedBlock = null; var blockTypes = ['red', 'blue', 'green', 'yellow']; var paletteBlocks = []; // Create grid background var gridBg = game.attachAsset('gridBackground', { x: 0, y: 300, anchorX: 0, anchorY: 0 }); // Create palette background var paletteBg = game.attachAsset('paletteBackground', { x: 0, y: 2732 - PALETTE_HEIGHT, anchorX: 0, anchorY: 0 }); // Create palette blocks for (var i = 0; i < blockTypes.length; i++) { var paletteBlock = new Block(blockTypes[i]); paletteBlock.x = 200 + i * 300; paletteBlock.y = 2732 - PALETTE_HEIGHT / 2; paletteBlock.isPaletteBlock = true; paletteBlocks.push(paletteBlock); game.addChild(paletteBlock); } // Score display var scoreTxt = new Text2('Height: 0 | Blocks: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // High score display var highScoreTxt = new Text2('Best: ' + (storage.highScore || 0), { size: 60, fill: 0xFFFF00 }); highScoreTxt.anchor.set(0.5, 0); highScoreTxt.y = 100; LK.gui.top.addChild(highScoreTxt); function updateScore() { var maxHeight = 0; var blockCount = placedBlocks.length; // Calculate maximum height for (var i = 0; i < placedBlocks.length; i++) { var block = placedBlocks[i]; if (block.isPlaced && block.isStable) { var height = GRID_HEIGHT - block.gridY; if (height > maxHeight) { maxHeight = height; } } } var currentScore = maxHeight * 10 + blockCount; LK.setScore(currentScore); scoreTxt.setText('Height: ' + maxHeight + ' | Blocks: ' + blockCount); // Update high score var highScore = storage.highScore || 0; if (currentScore > highScore) { storage.highScore = currentScore; highScoreTxt.setText('Best: ' + currentScore); } } function isValidPlacement(gridX, gridY) { if (gridX < 0 || gridX >= GRID_WIDTH || gridY < 0 || gridY >= GRID_HEIGHT) { return false; } // Check if position is occupied for (var i = 0; i < placedBlocks.length; i++) { var block = placedBlocks[i]; if (block.gridX === gridX && block.gridY === gridY) { return false; } } return true; } function getGridPosition(x, y) { var gridX = Math.floor((x - GRID_START_X) / GRID_SIZE); var gridY = Math.floor((y - GRID_START_Y) / GRID_SIZE); return { x: gridX, y: gridY }; } function checkForCollapses() { var collapsedAny = false; // Check all blocks for stability for (var i = placedBlocks.length - 1; i >= 0; i--) { var block = placedBlocks[i]; if (block.isPlaced && !block.checkStability() && block.isStable) { block.isStable = false; collapsedAny = true; } } if (collapsedAny) { LK.getSound('collapse').play(); } } game.down = function (x, y, obj) { // Check if clicking on palette block for (var i = 0; i < paletteBlocks.length; i++) { var paletteBlock = paletteBlocks[i]; if (Math.abs(x - paletteBlock.x) < GRID_SIZE / 2 && Math.abs(y - paletteBlock.y) < GRID_SIZE / 2) { // Create new block from palette draggedBlock = new Block(paletteBlock.blockType); draggedBlock.x = x; draggedBlock.y = y; draggedBlock.isDragging = true; game.addChild(draggedBlock); return; } } // Check if clicking on placed block for (var i = 0; i < placedBlocks.length; i++) { var block = placedBlocks[i]; if (Math.abs(x - block.x) < GRID_SIZE / 2 && Math.abs(y - block.y) < GRID_SIZE / 2) { draggedBlock = block; draggedBlock.isDragging = true; if (block.isPlaced) { // Remove from grid block.isPlaced = false; var index = placedBlocks.indexOf(block); placedBlocks.splice(index, 1); checkForCollapses(); } return; } } }; game.move = function (x, y, obj) { if (draggedBlock) { draggedBlock.x = x; draggedBlock.y = y; // Visual feedback for valid placement var gridPos = getGridPosition(x, y); if (y >= GRID_START_Y && y < GRID_START_Y + GRID_HEIGHT * GRID_SIZE) { if (isValidPlacement(gridPos.x, gridPos.y)) { draggedBlock.alpha = 1.0; } else { draggedBlock.alpha = 0.5; } } else { draggedBlock.alpha = 0.7; } } }; game.up = function (x, y, obj) { if (draggedBlock) { draggedBlock.isDragging = false; draggedBlock.alpha = 1.0; var gridPos = getGridPosition(x, y); // Check if dropping in valid grid position if (y >= GRID_START_Y && y < GRID_START_Y + GRID_HEIGHT * GRID_SIZE && isValidPlacement(gridPos.x, gridPos.y)) { draggedBlock.setGridPosition(gridPos.x, gridPos.y); draggedBlock.isPlaced = true; placedBlocks.push(draggedBlock); LK.getSound('place').play(); updateScore(); } else if (y < GRID_START_Y || y >= 2732 - PALETTE_HEIGHT) { // Dropped outside grid area - remove block if (!draggedBlock.isPaletteBlock) { draggedBlock.destroy(); } } else { // Invalid placement - snap back or remove if (draggedBlock.isPlaced) { // Was previously placed, return to grid draggedBlock.setGridPosition(draggedBlock.gridX, draggedBlock.gridY); placedBlocks.push(draggedBlock); } else { // New block dropped in invalid location draggedBlock.destroy(); } } draggedBlock = null; } }; game.update = function () { // Update all placed blocks for (var i = 0; i < placedBlocks.length; i++) { placedBlocks[i].update(); } // Clean up blocks that have fallen off screen for (var i = placedBlocks.length - 1; i >= 0; i--) { var block = placedBlocks[i]; if (block.y > 2732 + 200) { block.destroy(); placedBlocks.splice(i, 1); updateScore(); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Block = Container.expand(function (blockType) {
var self = Container.call(this);
var blockGraphics = self.attachAsset(blockType + 'Block', {
anchorX: 0.5,
anchorY: 0.5
});
self.blockType = blockType;
self.gridX = -1;
self.gridY = -1;
self.isPlaced = false;
self.isDragging = false;
self.fallSpeed = 0;
self.isStable = true;
self.lastStable = true;
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * GRID_SIZE + GRID_SIZE / 2;
self.y = GRID_START_Y + gridY * GRID_SIZE + GRID_SIZE / 2;
};
self.checkStability = function () {
if (self.gridY >= GRID_HEIGHT - 1) {
return true; // Ground level is stable
}
// Check if there's a block below
for (var i = 0; i < placedBlocks.length; i++) {
var otherBlock = placedBlocks[i];
if (otherBlock !== self && otherBlock.gridX === self.gridX && otherBlock.gridY === self.gridY + 1) {
return true;
}
}
return false;
};
self.update = function () {
if (!self.isPlaced || self.isDragging) return;
self.lastStable = self.isStable;
self.isStable = self.checkStability();
// If block becomes unstable, make it fall
if (self.lastStable && !self.isStable) {
self.fallSpeed = 2;
}
// Apply falling physics
if (!self.isStable && self.fallSpeed > 0) {
self.y += self.fallSpeed;
self.fallSpeed += 0.5; // Gravity
// Check if block has hit the ground or another block
var targetY = GRID_START_Y + (GRID_HEIGHT - 1) * GRID_SIZE + GRID_SIZE / 2;
if (self.y >= targetY) {
self.y = targetY;
self.gridY = GRID_HEIGHT - 1;
self.fallSpeed = 0;
self.isStable = true;
LK.getSound('place').play();
updateScore();
} else {
// Check collision with other blocks
for (var i = 0; i < placedBlocks.length; i++) {
var otherBlock = placedBlocks[i];
if (otherBlock !== self && Math.abs(otherBlock.x - self.x) < GRID_SIZE && Math.abs(otherBlock.y - self.y) < GRID_SIZE && self.y >= otherBlock.y - GRID_SIZE) {
self.y = otherBlock.y - GRID_SIZE;
self.gridY = otherBlock.gridY - 1;
self.fallSpeed = 0;
self.isStable = true;
LK.getSound('place').play();
updateScore();
break;
}
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game constants
var GRID_SIZE = 120;
var GRID_WIDTH = 16;
var GRID_HEIGHT = 14;
var GRID_START_X = 64;
var GRID_START_Y = 300;
var PALETTE_HEIGHT = 200;
// Game variables
var placedBlocks = [];
var draggedBlock = null;
var blockTypes = ['red', 'blue', 'green', 'yellow'];
var paletteBlocks = [];
// Create grid background
var gridBg = game.attachAsset('gridBackground', {
x: 0,
y: 300,
anchorX: 0,
anchorY: 0
});
// Create palette background
var paletteBg = game.attachAsset('paletteBackground', {
x: 0,
y: 2732 - PALETTE_HEIGHT,
anchorX: 0,
anchorY: 0
});
// Create palette blocks
for (var i = 0; i < blockTypes.length; i++) {
var paletteBlock = new Block(blockTypes[i]);
paletteBlock.x = 200 + i * 300;
paletteBlock.y = 2732 - PALETTE_HEIGHT / 2;
paletteBlock.isPaletteBlock = true;
paletteBlocks.push(paletteBlock);
game.addChild(paletteBlock);
}
// Score display
var scoreTxt = new Text2('Height: 0 | Blocks: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// High score display
var highScoreTxt = new Text2('Best: ' + (storage.highScore || 0), {
size: 60,
fill: 0xFFFF00
});
highScoreTxt.anchor.set(0.5, 0);
highScoreTxt.y = 100;
LK.gui.top.addChild(highScoreTxt);
function updateScore() {
var maxHeight = 0;
var blockCount = placedBlocks.length;
// Calculate maximum height
for (var i = 0; i < placedBlocks.length; i++) {
var block = placedBlocks[i];
if (block.isPlaced && block.isStable) {
var height = GRID_HEIGHT - block.gridY;
if (height > maxHeight) {
maxHeight = height;
}
}
}
var currentScore = maxHeight * 10 + blockCount;
LK.setScore(currentScore);
scoreTxt.setText('Height: ' + maxHeight + ' | Blocks: ' + blockCount);
// Update high score
var highScore = storage.highScore || 0;
if (currentScore > highScore) {
storage.highScore = currentScore;
highScoreTxt.setText('Best: ' + currentScore);
}
}
function isValidPlacement(gridX, gridY) {
if (gridX < 0 || gridX >= GRID_WIDTH || gridY < 0 || gridY >= GRID_HEIGHT) {
return false;
}
// Check if position is occupied
for (var i = 0; i < placedBlocks.length; i++) {
var block = placedBlocks[i];
if (block.gridX === gridX && block.gridY === gridY) {
return false;
}
}
return true;
}
function getGridPosition(x, y) {
var gridX = Math.floor((x - GRID_START_X) / GRID_SIZE);
var gridY = Math.floor((y - GRID_START_Y) / GRID_SIZE);
return {
x: gridX,
y: gridY
};
}
function checkForCollapses() {
var collapsedAny = false;
// Check all blocks for stability
for (var i = placedBlocks.length - 1; i >= 0; i--) {
var block = placedBlocks[i];
if (block.isPlaced && !block.checkStability() && block.isStable) {
block.isStable = false;
collapsedAny = true;
}
}
if (collapsedAny) {
LK.getSound('collapse').play();
}
}
game.down = function (x, y, obj) {
// Check if clicking on palette block
for (var i = 0; i < paletteBlocks.length; i++) {
var paletteBlock = paletteBlocks[i];
if (Math.abs(x - paletteBlock.x) < GRID_SIZE / 2 && Math.abs(y - paletteBlock.y) < GRID_SIZE / 2) {
// Create new block from palette
draggedBlock = new Block(paletteBlock.blockType);
draggedBlock.x = x;
draggedBlock.y = y;
draggedBlock.isDragging = true;
game.addChild(draggedBlock);
return;
}
}
// Check if clicking on placed block
for (var i = 0; i < placedBlocks.length; i++) {
var block = placedBlocks[i];
if (Math.abs(x - block.x) < GRID_SIZE / 2 && Math.abs(y - block.y) < GRID_SIZE / 2) {
draggedBlock = block;
draggedBlock.isDragging = true;
if (block.isPlaced) {
// Remove from grid
block.isPlaced = false;
var index = placedBlocks.indexOf(block);
placedBlocks.splice(index, 1);
checkForCollapses();
}
return;
}
}
};
game.move = function (x, y, obj) {
if (draggedBlock) {
draggedBlock.x = x;
draggedBlock.y = y;
// Visual feedback for valid placement
var gridPos = getGridPosition(x, y);
if (y >= GRID_START_Y && y < GRID_START_Y + GRID_HEIGHT * GRID_SIZE) {
if (isValidPlacement(gridPos.x, gridPos.y)) {
draggedBlock.alpha = 1.0;
} else {
draggedBlock.alpha = 0.5;
}
} else {
draggedBlock.alpha = 0.7;
}
}
};
game.up = function (x, y, obj) {
if (draggedBlock) {
draggedBlock.isDragging = false;
draggedBlock.alpha = 1.0;
var gridPos = getGridPosition(x, y);
// Check if dropping in valid grid position
if (y >= GRID_START_Y && y < GRID_START_Y + GRID_HEIGHT * GRID_SIZE && isValidPlacement(gridPos.x, gridPos.y)) {
draggedBlock.setGridPosition(gridPos.x, gridPos.y);
draggedBlock.isPlaced = true;
placedBlocks.push(draggedBlock);
LK.getSound('place').play();
updateScore();
} else if (y < GRID_START_Y || y >= 2732 - PALETTE_HEIGHT) {
// Dropped outside grid area - remove block
if (!draggedBlock.isPaletteBlock) {
draggedBlock.destroy();
}
} else {
// Invalid placement - snap back or remove
if (draggedBlock.isPlaced) {
// Was previously placed, return to grid
draggedBlock.setGridPosition(draggedBlock.gridX, draggedBlock.gridY);
placedBlocks.push(draggedBlock);
} else {
// New block dropped in invalid location
draggedBlock.destroy();
}
}
draggedBlock = null;
}
};
game.update = function () {
// Update all placed blocks
for (var i = 0; i < placedBlocks.length; i++) {
placedBlocks[i].update();
}
// Clean up blocks that have fallen off screen
for (var i = placedBlocks.length - 1; i >= 0; i--) {
var block = placedBlocks[i];
if (block.y > 2732 + 200) {
block.destroy();
placedBlocks.splice(i, 1);
updateScore();
}
}
};