/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Block = Container.expand(function (blockType, gridX, gridY) { var self = Container.call(this); self.blockType = blockType || '1x1'; self.gridX = gridX || 0; self.gridY = gridY || 0; self.rotation = 0; self.isPlaced = false; self.supportedByGround = false; // Create graphics based on block type if (self.blockType === '1x1') { self.blockGraphics = self.attachAsset('block1x1', { anchorX: 0.5, anchorY: 0.5 }); self.widthGrid = 1; self.heightGrid = 1; } else if (self.blockType === '2x1') { self.blockGraphics = self.attachAsset('block2x1', { anchorX: 0.5, anchorY: 0.5 }); self.widthGrid = 2; self.heightGrid = 1; } else if (self.blockType === '1x2') { self.blockGraphics = self.attachAsset('block1x2', { anchorX: 0.5, anchorY: 0.5 }); self.widthGrid = 1; self.heightGrid = 2; } else if (self.blockType === 'special') { self.blockGraphics = self.attachAsset('blockSpecial', { anchorX: 0.5, anchorY: 0.5 }); self.widthGrid = 1; self.heightGrid = 1; } self.setGridPosition = function (gx, gy) { self.gridX = gx; self.gridY = gy; self.x = gx * gridSize + gridSize / 2 + gameOffsetX; self.y = gy * gridSize + gridSize / 2 + gameOffsetY; }; self.rotateBlock = function () { self.rotation += 90; if (self.rotation >= 360) self.rotation = 0; self.blockGraphics.rotation = self.rotation * Math.PI / 180; // Swap dimensions for non-square blocks if (self.blockType === '2x1' || self.blockType === '1x2') { var temp = self.widthGrid; self.widthGrid = self.heightGrid; self.heightGrid = temp; } }; self.checkSupport = function () { // Check if block is on ground level if (self.gridY + self.heightGrid >= maxGridY - 2) { self.supportedByGround = true; return true; } // Check if supported by other blocks for (var i = 0; i < placedBlocks.length; i++) { var otherBlock = placedBlocks[i]; if (otherBlock === self) continue; // Check if this block is directly above another block if (self.gridY + self.heightGrid === otherBlock.gridY) { if (self.gridX < otherBlock.gridX + otherBlock.widthGrid && self.gridX + self.widthGrid > otherBlock.gridX) { return true; } } } return false; }; self.down = function (x, y, obj) { if (self.isPlaced) { self.rotateBlock(); LK.getSound('rotateBlock').play(); } }; return self; }); var GridHelper = Container.expand(function () { var self = Container.call(this); self.helperGraphics = self.attachAsset('gridHelper', { anchorX: 0.5, anchorY: 0.5 }); self.helperGraphics.alpha = 0.3; self.showAt = function (gridX, gridY) { self.x = gridX * gridSize + gridSize / 2 + gameOffsetX; self.y = gridY * gridSize + gridSize / 2 + gameOffsetY; self.alpha = 1; }; self.hide = function () { self.alpha = 0; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var gridSize = 80; var maxGridX = Math.floor(2048 / gridSize); var maxGridY = Math.floor(2732 / gridSize); var gameOffsetX = (2048 - maxGridX * gridSize) / 2; var gameOffsetY = 100; var placedBlocks = []; var currentBlockType = '1x1'; var blockTypes = ['1x1', '2x1', '1x2', 'special']; var currentBlockIndex = 0; var buildingGrid = []; for (var x = 0; x < maxGridX; x++) { buildingGrid[x] = []; for (var y = 0; y < maxGridY; y++) { buildingGrid[x][y] = false; } } var gridHelper = game.addChild(new GridHelper()); gridHelper.hide(); // UI Elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var blockTypeTxt = new Text2('Block: 1x1', { size: 50, fill: 0xFFFFFF }); blockTypeTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(blockTypeTxt); var instructionTxt = new Text2('Tap to place blocks | Tap blocks to rotate | Swipe to change block type', { size: 35, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 1); instructionTxt.y = -80; LK.gui.bottom.addChild(instructionTxt); function worldToGrid(worldX, worldY) { var gridX = Math.floor((worldX - gameOffsetX) / gridSize); var gridY = Math.floor((worldY - gameOffsetY) / gridSize); return { x: gridX, y: gridY }; } function isValidPlacement(gridX, gridY, blockWidth, blockHeight) { if (gridX < 0 || gridY < 0) return false; if (gridX + blockWidth > maxGridX || gridY + blockHeight > maxGridY) return false; for (var x = gridX; x < gridX + blockWidth; x++) { for (var y = gridY; y < gridY + blockHeight; y++) { if (buildingGrid[x] && buildingGrid[x][y]) { return false; } } } return true; } function occupyGrid(gridX, gridY, blockWidth, blockHeight) { for (var x = gridX; x < gridX + blockWidth; x++) { for (var y = gridY; y < gridY + blockHeight; y++) { if (buildingGrid[x]) { buildingGrid[x][y] = true; } } } } function freeGrid(gridX, gridY, blockWidth, blockHeight) { for (var x = gridX; x < gridX + blockWidth; x++) { for (var y = gridY; y < gridY + blockHeight; y++) { if (buildingGrid[x]) { buildingGrid[x][y] = false; } } } } function switchBlockType(direction) { currentBlockIndex += direction; if (currentBlockIndex < 0) currentBlockIndex = blockTypes.length - 1; if (currentBlockIndex >= blockTypes.length) currentBlockIndex = 0; currentBlockType = blockTypes[currentBlockIndex]; blockTypeTxt.setText('Block: ' + currentBlockType); } function checkPhysics() { var blocksToRemove = []; for (var i = 0; i < placedBlocks.length; i++) { var block = placedBlocks[i]; if (!block.checkSupport()) { // Block should fall blocksToRemove.push(block); } } // Remove unsupported blocks for (var j = 0; j < blocksToRemove.length; j++) { var fallingBlock = blocksToRemove[j]; freeGrid(fallingBlock.gridX, fallingBlock.gridY, fallingBlock.widthGrid, fallingBlock.heightGrid); fallingBlock.destroy(); var index = placedBlocks.indexOf(fallingBlock); if (index > -1) { placedBlocks.splice(index, 1); } // Animate falling tween(fallingBlock, { y: 2732 + 100 }, { duration: 1000 }); } } var lastTouchX = 0; var lastTouchY = 0; var swipeThreshold = 100; game.down = function (x, y, obj) { lastTouchX = x; lastTouchY = y; }; game.up = function (x, y, obj) { var deltaX = x - lastTouchX; // Check for swipe to change block type if (Math.abs(deltaX) > swipeThreshold) { if (deltaX > 0) { switchBlockType(1); } else { switchBlockType(-1); } return; } var gridPos = worldToGrid(x, y); // Get dimensions for current block type var blockWidth = 1, blockHeight = 1; if (currentBlockType === '2x1') { blockWidth = 2; blockHeight = 1; } else if (currentBlockType === '1x2') { blockWidth = 1; blockHeight = 2; } if (isValidPlacement(gridPos.x, gridPos.y, blockWidth, blockHeight)) { var newBlock = new Block(currentBlockType, gridPos.x, gridPos.y); newBlock.setGridPosition(gridPos.x, gridPos.y); newBlock.isPlaced = true; game.addChild(newBlock); placedBlocks.push(newBlock); occupyGrid(gridPos.x, gridPos.y, blockWidth, blockHeight); // Update score var points = 10; if (currentBlockType === '2x1' || currentBlockType === '1x2') points = 15; if (currentBlockType === 'special') points = 25; LK.setScore(LK.getScore() + points); scoreTxt.setText('Score: ' + LK.getScore()); LK.getSound('placeBlock').play(); // Check physics after placement LK.setTimeout(function () { checkPhysics(); }, 100); // Flash effect LK.effects.flashObject(newBlock, 0xFFFF00, 300); } gridHelper.hide(); }; game.move = function (x, y, obj) { var gridPos = worldToGrid(x, y); // Get dimensions for current block type var blockWidth = 1, blockHeight = 1; if (currentBlockType === '2x1') { blockWidth = 2; blockHeight = 1; } else if (currentBlockType === '1x2') { blockWidth = 1; blockHeight = 2; } if (isValidPlacement(gridPos.x, gridPos.y, blockWidth, blockHeight)) { gridHelper.showAt(gridPos.x, gridPos.y); } else { gridHelper.hide(); } }; // Physics check every few seconds var physicsTimer = LK.setInterval(function () { checkPhysics(); }, 3000); game.update = function () { // Update score display if (LK.ticks % 60 === 0) { scoreTxt.setText('Score: ' + LK.getScore()); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Block = Container.expand(function (blockType, gridX, gridY) {
var self = Container.call(this);
self.blockType = blockType || '1x1';
self.gridX = gridX || 0;
self.gridY = gridY || 0;
self.rotation = 0;
self.isPlaced = false;
self.supportedByGround = false;
// Create graphics based on block type
if (self.blockType === '1x1') {
self.blockGraphics = self.attachAsset('block1x1', {
anchorX: 0.5,
anchorY: 0.5
});
self.widthGrid = 1;
self.heightGrid = 1;
} else if (self.blockType === '2x1') {
self.blockGraphics = self.attachAsset('block2x1', {
anchorX: 0.5,
anchorY: 0.5
});
self.widthGrid = 2;
self.heightGrid = 1;
} else if (self.blockType === '1x2') {
self.blockGraphics = self.attachAsset('block1x2', {
anchorX: 0.5,
anchorY: 0.5
});
self.widthGrid = 1;
self.heightGrid = 2;
} else if (self.blockType === 'special') {
self.blockGraphics = self.attachAsset('blockSpecial', {
anchorX: 0.5,
anchorY: 0.5
});
self.widthGrid = 1;
self.heightGrid = 1;
}
self.setGridPosition = function (gx, gy) {
self.gridX = gx;
self.gridY = gy;
self.x = gx * gridSize + gridSize / 2 + gameOffsetX;
self.y = gy * gridSize + gridSize / 2 + gameOffsetY;
};
self.rotateBlock = function () {
self.rotation += 90;
if (self.rotation >= 360) self.rotation = 0;
self.blockGraphics.rotation = self.rotation * Math.PI / 180;
// Swap dimensions for non-square blocks
if (self.blockType === '2x1' || self.blockType === '1x2') {
var temp = self.widthGrid;
self.widthGrid = self.heightGrid;
self.heightGrid = temp;
}
};
self.checkSupport = function () {
// Check if block is on ground level
if (self.gridY + self.heightGrid >= maxGridY - 2) {
self.supportedByGround = true;
return true;
}
// Check if supported by other blocks
for (var i = 0; i < placedBlocks.length; i++) {
var otherBlock = placedBlocks[i];
if (otherBlock === self) continue;
// Check if this block is directly above another block
if (self.gridY + self.heightGrid === otherBlock.gridY) {
if (self.gridX < otherBlock.gridX + otherBlock.widthGrid && self.gridX + self.widthGrid > otherBlock.gridX) {
return true;
}
}
}
return false;
};
self.down = function (x, y, obj) {
if (self.isPlaced) {
self.rotateBlock();
LK.getSound('rotateBlock').play();
}
};
return self;
});
var GridHelper = Container.expand(function () {
var self = Container.call(this);
self.helperGraphics = self.attachAsset('gridHelper', {
anchorX: 0.5,
anchorY: 0.5
});
self.helperGraphics.alpha = 0.3;
self.showAt = function (gridX, gridY) {
self.x = gridX * gridSize + gridSize / 2 + gameOffsetX;
self.y = gridY * gridSize + gridSize / 2 + gameOffsetY;
self.alpha = 1;
};
self.hide = function () {
self.alpha = 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var gridSize = 80;
var maxGridX = Math.floor(2048 / gridSize);
var maxGridY = Math.floor(2732 / gridSize);
var gameOffsetX = (2048 - maxGridX * gridSize) / 2;
var gameOffsetY = 100;
var placedBlocks = [];
var currentBlockType = '1x1';
var blockTypes = ['1x1', '2x1', '1x2', 'special'];
var currentBlockIndex = 0;
var buildingGrid = [];
for (var x = 0; x < maxGridX; x++) {
buildingGrid[x] = [];
for (var y = 0; y < maxGridY; y++) {
buildingGrid[x][y] = false;
}
}
var gridHelper = game.addChild(new GridHelper());
gridHelper.hide();
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var blockTypeTxt = new Text2('Block: 1x1', {
size: 50,
fill: 0xFFFFFF
});
blockTypeTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(blockTypeTxt);
var instructionTxt = new Text2('Tap to place blocks | Tap blocks to rotate | Swipe to change block type', {
size: 35,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 1);
instructionTxt.y = -80;
LK.gui.bottom.addChild(instructionTxt);
function worldToGrid(worldX, worldY) {
var gridX = Math.floor((worldX - gameOffsetX) / gridSize);
var gridY = Math.floor((worldY - gameOffsetY) / gridSize);
return {
x: gridX,
y: gridY
};
}
function isValidPlacement(gridX, gridY, blockWidth, blockHeight) {
if (gridX < 0 || gridY < 0) return false;
if (gridX + blockWidth > maxGridX || gridY + blockHeight > maxGridY) return false;
for (var x = gridX; x < gridX + blockWidth; x++) {
for (var y = gridY; y < gridY + blockHeight; y++) {
if (buildingGrid[x] && buildingGrid[x][y]) {
return false;
}
}
}
return true;
}
function occupyGrid(gridX, gridY, blockWidth, blockHeight) {
for (var x = gridX; x < gridX + blockWidth; x++) {
for (var y = gridY; y < gridY + blockHeight; y++) {
if (buildingGrid[x]) {
buildingGrid[x][y] = true;
}
}
}
}
function freeGrid(gridX, gridY, blockWidth, blockHeight) {
for (var x = gridX; x < gridX + blockWidth; x++) {
for (var y = gridY; y < gridY + blockHeight; y++) {
if (buildingGrid[x]) {
buildingGrid[x][y] = false;
}
}
}
}
function switchBlockType(direction) {
currentBlockIndex += direction;
if (currentBlockIndex < 0) currentBlockIndex = blockTypes.length - 1;
if (currentBlockIndex >= blockTypes.length) currentBlockIndex = 0;
currentBlockType = blockTypes[currentBlockIndex];
blockTypeTxt.setText('Block: ' + currentBlockType);
}
function checkPhysics() {
var blocksToRemove = [];
for (var i = 0; i < placedBlocks.length; i++) {
var block = placedBlocks[i];
if (!block.checkSupport()) {
// Block should fall
blocksToRemove.push(block);
}
}
// Remove unsupported blocks
for (var j = 0; j < blocksToRemove.length; j++) {
var fallingBlock = blocksToRemove[j];
freeGrid(fallingBlock.gridX, fallingBlock.gridY, fallingBlock.widthGrid, fallingBlock.heightGrid);
fallingBlock.destroy();
var index = placedBlocks.indexOf(fallingBlock);
if (index > -1) {
placedBlocks.splice(index, 1);
}
// Animate falling
tween(fallingBlock, {
y: 2732 + 100
}, {
duration: 1000
});
}
}
var lastTouchX = 0;
var lastTouchY = 0;
var swipeThreshold = 100;
game.down = function (x, y, obj) {
lastTouchX = x;
lastTouchY = y;
};
game.up = function (x, y, obj) {
var deltaX = x - lastTouchX;
// Check for swipe to change block type
if (Math.abs(deltaX) > swipeThreshold) {
if (deltaX > 0) {
switchBlockType(1);
} else {
switchBlockType(-1);
}
return;
}
var gridPos = worldToGrid(x, y);
// Get dimensions for current block type
var blockWidth = 1,
blockHeight = 1;
if (currentBlockType === '2x1') {
blockWidth = 2;
blockHeight = 1;
} else if (currentBlockType === '1x2') {
blockWidth = 1;
blockHeight = 2;
}
if (isValidPlacement(gridPos.x, gridPos.y, blockWidth, blockHeight)) {
var newBlock = new Block(currentBlockType, gridPos.x, gridPos.y);
newBlock.setGridPosition(gridPos.x, gridPos.y);
newBlock.isPlaced = true;
game.addChild(newBlock);
placedBlocks.push(newBlock);
occupyGrid(gridPos.x, gridPos.y, blockWidth, blockHeight);
// Update score
var points = 10;
if (currentBlockType === '2x1' || currentBlockType === '1x2') points = 15;
if (currentBlockType === 'special') points = 25;
LK.setScore(LK.getScore() + points);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('placeBlock').play();
// Check physics after placement
LK.setTimeout(function () {
checkPhysics();
}, 100);
// Flash effect
LK.effects.flashObject(newBlock, 0xFFFF00, 300);
}
gridHelper.hide();
};
game.move = function (x, y, obj) {
var gridPos = worldToGrid(x, y);
// Get dimensions for current block type
var blockWidth = 1,
blockHeight = 1;
if (currentBlockType === '2x1') {
blockWidth = 2;
blockHeight = 1;
} else if (currentBlockType === '1x2') {
blockWidth = 1;
blockHeight = 2;
}
if (isValidPlacement(gridPos.x, gridPos.y, blockWidth, blockHeight)) {
gridHelper.showAt(gridPos.x, gridPos.y);
} else {
gridHelper.hide();
}
};
// Physics check every few seconds
var physicsTimer = LK.setInterval(function () {
checkPhysics();
}, 3000);
game.update = function () {
// Update score display
if (LK.ticks % 60 === 0) {
scoreTxt.setText('Score: ' + LK.getScore());
}
};