/****
* 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());
}
};