User prompt
Alla kuber skall ha olika färger
User prompt
Jag vill ha mer ljusa färger på kuberna
User prompt
Fixa flera kuber och varje kub skall ha en ljus färglad färg som regnbågen
User prompt
More lightful color and shaders on the assets
User prompt
Skapa mer glada färger på assets
User prompt
Gör assets mindre så dom varje asset passar i en rutan
User prompt
Gör fyrkanterna man flyttar mindre
User prompt
Ändra tillbaka till föregående
User prompt
Gör om assets till ansikten i olika färger, lägg till blommor och även houngsburkar
User prompt
Ännu tydligare streck på rutnätet
User prompt
Fixa så man ser rutnätet
User prompt
Fixa samma asset bild på alla kuber men i olika färger
User prompt
Ändra till bakgrunden i assets
User prompt
Ändra tillbaka till föregående background
User prompt
Make more realistic background, not so blurry
User prompt
Remove the grey squares
User prompt
Set background asset to background picture
User prompt
Fix unlimited cubes
User prompt
Ändra background till finare
User prompt
Kan du göra biet större, det är för litet
User prompt
Ja
User prompt
Make the Bee bigger
User prompt
Ändra fyrkanterna till roliga fyrkanter med glada ansikten på och mer tydliga fyrkanter, bättre grafik
User prompt
Ångra till innan det publicerades
User prompt
Make all squares to Angry Birds like the red one, but all in different colors
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// --- Game Over / Reset handled by LK engine ---
// --- Block Class ---
var Block = Container.expand(function () {
var self = Container.call(this);
// Default color index (0=red, 1=green, 2=blue, 3=yellow, 4=purple, 5=white, 6=gray/locked)
self.colorIndex = 0;
self.isLocked = false;
self.isOnGrid = false;
self.gridX = -1;
self.gridY = -1;
// Attach block asset (default red, will be set by setColor)
self.blockAsset = self.attachAsset('block_red', {
anchorX: 0.5,
anchorY: 0.5
});
// Add happy face overlay (eyes and smile) - more fun, clearer, and expressive
self.faceEyeLeft = self.attachAsset('block_black', {
width: 28,
height: 28,
anchorX: 0.5,
anchorY: 0.5,
x: -36,
y: -24,
alpha: 0.92
});
self.faceEyeRight = self.attachAsset('block_black', {
width: 28,
height: 28,
anchorX: 0.5,
anchorY: 0.5,
x: 36,
y: -24,
alpha: 0.92
});
self.faceSmile = self.attachAsset('block_black', {
width: 60,
height: 18,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 36,
alpha: 0.8
});
self.faceSmile.scaleX = 1.2;
self.faceSmile.scaleY = 0.7;
// Set color and locked state
self.setColor = function (colorIdx) {
self.colorIndex = colorIdx;
self.isLocked = colorIdx === 6;
// Remove old asset if exists
if (self.blockAsset) {
self.removeChild(self.blockAsset);
}
var assetName = 'block_red';
if (colorIdx === 0) assetName = 'block_red';else if (colorIdx === 1) assetName = 'block_green';else if (colorIdx === 2) assetName = 'block_blue';else if (colorIdx === 3) assetName = 'block_yellow';else if (colorIdx === 4) assetName = 'block_purple';else if (colorIdx === 5) assetName = 'block_white';else if (colorIdx === 6) assetName = 'block_gray';else if (colorIdx === 7) assetName = 'block_rainbow';
self.blockAsset = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
// Remove old face parts if they exist
if (self.faceEyeLeft) self.removeChild(self.faceEyeLeft);
if (self.faceEyeRight) self.removeChild(self.faceEyeRight);
if (self.faceSmile) self.removeChild(self.faceSmile);
if (self.faceEyesLeft) self.removeChild(self.faceEyesLeft);
if (self.faceEyesRight) self.removeChild(self.faceEyesRight);
if (self.faceMouth) self.removeChild(self.faceMouth);
// Happy face for all colored blocks (not locked, not rainbow)
if (colorIdx !== 6 && colorIdx !== 7) {
// Fun, happy face with bigger eyes and smile
self.faceEyeLeft = self.attachAsset('block_black', {
width: 28,
height: 28,
anchorX: 0.5,
anchorY: 0.5,
x: -36,
y: -24,
alpha: 0.92
});
self.faceEyeRight = self.attachAsset('block_black', {
width: 28,
height: 28,
anchorX: 0.5,
anchorY: 0.5,
x: 36,
y: -24,
alpha: 0.92
});
self.faceSmile = self.attachAsset('block_black', {
width: 60,
height: 18,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 36,
alpha: 0.8
});
self.faceSmile.scaleX = 1.2;
self.faceSmile.scaleY = 0.7;
} else if (colorIdx === 7) {
// Rainbow block: star eyes and big smile
self.faceEyesLeft = self.attachAsset('block_yellow', {
width: 44,
height: 44,
anchorX: 0.5,
anchorY: 0.5,
x: -56,
y: -32,
alpha: 0.98
});
self.faceEyesRight = self.attachAsset('block_yellow', {
width: 44,
height: 44,
anchorX: 0.5,
anchorY: 0.5,
x: 56,
y: -32,
alpha: 0.98
});
self.faceMouth = self.attachAsset('block_red', {
width: 90,
height: 28,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 44,
alpha: 0.85
});
self.faceMouth.scaleX = 1.3;
self.faceMouth.scaleY = 0.7;
} else {
self.faceEyeLeft = null;
self.faceEyeRight = null;
self.faceSmile = null;
self.faceEyesLeft = null;
self.faceEyesRight = null;
self.faceMouth = null;
}
};
// Animate merge (scale up and back)
self.animateMerge = function (_onFinish) {
tween(self, {
scaleX: 1.25,
scaleY: 1.25
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeIn,
onFinish: function onFinish() {
if (_onFinish) _onFinish();
}
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222233
});
/****
* Game Code
****/
// More defined, fun, and clear block shapes for each color
// visually white, but will be rainbow in logic
// Sound for merge
// Merged block (final color)
// We'll use 5 colors: red, green, blue, yellow, purple
// Define block shapes for each color and merged color
// --- Game Constants ---
// locked block
var GRID_COLS = 6;
var GRID_ROWS = 7;
var CELL_SIZE = 260; // px (was 200, now bigger for larger squares)
var GRID_OFFSET_X = Math.floor((2048 - GRID_COLS * CELL_SIZE) / 2);
var GRID_OFFSET_Y = 350;
var COLORS = [0, 1, 2, 3, 4]; // 0=red, 1=green, 2=blue, 3=yellow, 4=purple
var COLOR_NAMES = ['red', 'green', 'blue', 'yellow', 'purple', 'white', 'gray', 'rainbow'];
var MAX_COLOR_INDEX = 5; // 0-4 normal, 5=white (final, can't merge further)
var RAINBOW_COLOR_INDEX = 7; // special rainbow block
var BLOCK_DROP_Y = 2200; // y position for blocks that fall off
// --- Game State ---
var grid = []; // 2D array [col][row] of Block or null
for (var c = 0; c < GRID_COLS; c++) {
grid[c] = [];
for (var r = 0; r < GRID_ROWS; r++) {
grid[c][r] = null;
}
}
var draggingBlock = null;
var dragOffsetX = 0;
var dragOffsetY = 0;
var nextBlocks = []; // Array of next blocks to place
var score = 0;
var scoreTxt = null;
var isProcessing = false; // Prevent input during merges
// --- Undo/Föregående State ---
var prevState = null;
// Helper: Deep copy grid state (only colorIndex, isLocked, isOnGrid, gridX, gridY)
function copyGridState(srcGrid) {
var arr = [];
for (var c = 0; c < GRID_COLS; c++) {
arr[c] = [];
for (var r = 0; r < GRID_ROWS; r++) {
var b = srcGrid[c][r];
if (b) {
arr[c][r] = {
colorIndex: b.colorIndex,
isLocked: b.isLocked,
isOnGrid: b.isOnGrid,
gridX: b.gridX,
gridY: b.gridY
};
} else {
arr[c][r] = null;
}
}
}
return arr;
}
// Helper: Deep copy nextBlocks state (only colorIndex)
function copyNextBlocksState(srcNextBlocks) {
var arr = [];
for (var i = 0; i < srcNextBlocks.length; i++) {
arr.push({
colorIndex: srcNextBlocks[i].colorIndex
});
}
return arr;
}
// Save current state for undo
function savePrevState() {
prevState = {
grid: copyGridState(grid),
nextBlocks: copyNextBlocksState(nextBlocks),
score: score
};
}
// Restore previous state (undo)
function restorePrevState() {
if (!prevState) return;
// Remove all blocks from game
for (var c = 0; c < GRID_COLS; c++) {
for (var r = 0; r < GRID_ROWS; r++) {
if (grid[c][r]) {
grid[c][r].destroy();
grid[c][r] = null;
}
}
}
// Restore grid
for (var c = 0; c < GRID_COLS; c++) {
for (var r = 0; r < GRID_ROWS; r++) {
var bdata = prevState.grid[c][r];
if (bdata) {
var b = new Block();
b.setColor(bdata.colorIndex);
b.isOnGrid = bdata.isOnGrid;
b.gridX = bdata.gridX;
b.gridY = bdata.gridY;
var pos = getPosForCell(c, r);
b.x = pos.x;
b.y = pos.y;
grid[c][r] = b;
game.addChild(b);
} else {
grid[c][r] = null;
}
}
}
// Remove all nextBlocks from game
for (var i = 0; i < nextBlocks.length; i++) {
if (nextBlocks[i]) nextBlocks[i].destroy();
}
nextBlocks = [];
// Restore nextBlocks
for (var i = 0; i < prevState.nextBlocks.length; i++) {
var nb = new Block();
nb.setColor(prevState.nextBlocks[i].colorIndex);
nb.x = 2048 / 2 + (nextBlocks.length - 1) * 220;
nb.y = 220;
nb.scaleX = nb.scaleY = 1;
nb.isOnGrid = false;
nb.gridX = -1;
nb.gridY = -1;
game.addChild(nb);
nextBlocks.push(nb);
}
// Reposition nextBlocks
for (var i = 0; i < nextBlocks.length; i++) {
var bx = 2048 / 2 + (i - 1) * 220;
nextBlocks[i].x = bx;
nextBlocks[i].y = 220;
}
// Restore score
score = prevState.score;
scoreTxt.setText(score);
prevState = null;
}
// Add a button for undo/föregående
var undoBtn = new Text2('⟲', {
size: 110,
fill: "#fff"
});
undoBtn.anchor.set(0.5, 0.5);
undoBtn.x = 2048 - 120;
undoBtn.y = 120;
undoBtn.interactive = true;
undoBtn.buttonMode = true;
undoBtn.down = function () {
restorePrevState();
};
LK.gui.top.addChild(undoBtn);
// --- GUI Elements ---
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- Draw Happy Skybox Background Gradient ---
var skybox = LK.getAsset('block_blue', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 1
});
game.addChild(skybox);
// Add a white "sun" circle for extra cuteness
var sun = LK.getAsset('block_white', {
width: 420,
height: 420,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 180,
alpha: 0.18
});
game.addChild(sun);
// Add some "clouds" using white blocks with low alpha
for (var i = 0; i < 4; i++) {
var cloud = LK.getAsset('block_white', {
width: 320 + Math.random() * 120,
height: 90 + Math.random() * 40,
anchorX: 0.5,
anchorY: 0.5,
x: 300 + i * 420 + Math.random() * 80,
y: 120 + Math.random() * 60,
alpha: 0.10 + Math.random() * 0.08
});
game.addChild(cloud);
}
// --- Draw Grid Background ---
for (var c = 0; c < GRID_COLS; c++) {
for (var r = 0; r < GRID_ROWS; r++) {
var cell = LK.getAsset('block_white', {
anchorX: 0.5,
anchorY: 0.5,
x: GRID_OFFSET_X + c * CELL_SIZE + CELL_SIZE / 2,
y: GRID_OFFSET_Y + r * CELL_SIZE + CELL_SIZE / 2,
alpha: 0.08
});
game.addChild(cell);
}
}
// --- Helper Functions ---
// Get grid cell from x,y (game coordinates)
function getGridCellFromPos(x, y) {
var gx = Math.floor((x - GRID_OFFSET_X) / CELL_SIZE);
var gy = Math.floor((y - GRID_OFFSET_Y) / CELL_SIZE);
if (gx < 0 || gx >= GRID_COLS || gy < 0 || gy >= GRID_ROWS) return null;
return {
col: gx,
row: gy
};
}
// Get position (x,y) for grid cell
function getPosForCell(col, row) {
return {
x: GRID_OFFSET_X + col * CELL_SIZE + CELL_SIZE / 2,
y: GRID_OFFSET_Y + row * CELL_SIZE + CELL_SIZE / 2
};
}
// Generate a random color index (0-4)
function randomColorIndex() {
return COLORS[Math.floor(Math.random() * COLORS.length)];
}
// Create a new block for the "next" area
function createNextBlock(idx) {
var block = new Block();
block.setColor(idx);
block.x = 2048 / 2 + (nextBlocks.length - 1) * 220;
block.y = 220;
block.scaleX = block.scaleY = 1;
block.isOnGrid = false;
block.gridX = -1;
block.gridY = -1;
game.addChild(block);
return block;
}
// Fill nextBlocks to always have 3 blocks
function refillNextBlocks() {
while (nextBlocks.length < 3) {
// 10% chance to spawn a locked block, 5% chance to spawn a rainbow block
var idx;
var rand = Math.random();
if (rand < 0.05) {
idx = RAINBOW_COLOR_INDEX; // rainbow
} else if (rand < 0.15) {
idx = 6; // gray/locked
} else {
idx = randomColorIndex();
}
var block = createNextBlock(idx);
nextBlocks.push(block);
}
// Position them nicely
for (var i = 0; i < nextBlocks.length; i++) {
var bx = 2048 / 2 + (i - 1) * 220;
tween(nextBlocks[i], {
x: bx,
y: 220
}, {
duration: 180,
easing: tween.easeInOut
});
}
}
// Remove a block from nextBlocks and shift others
function popNextBlock(block) {
var idx = nextBlocks.indexOf(block);
if (idx >= 0) {
nextBlocks.splice(idx, 1);
}
refillNextBlocks();
}
// Place block on grid
function placeBlockOnGrid(block, col, row) {
block.isOnGrid = true;
block.gridX = col;
block.gridY = row;
grid[col][row] = block;
var pos = getPosForCell(col, row);
tween(block, {
x: pos.x,
y: pos.y,
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
}
// Remove block from grid
function removeBlockFromGrid(col, row) {
var block = grid[col][row];
if (block) {
grid[col][row] = null;
}
}
// Find all connected blocks of the same color (DFS)
function findConnectedBlocks(col, row, colorIndex, visited) {
if (col < 0 || col >= GRID_COLS || row < 0 || row >= GRID_ROWS) return [];
if (visited[col + "," + row]) return [];
var block = grid[col][row];
if (!block || block.colorIndex !== colorIndex) return [];
visited[col + "," + row] = true;
var result = [{
col: col,
row: row,
block: block
}];
// 4 directions
var dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]];
for (var i = 0; i < dirs.length; i++) {
var nc = col + dirs[i][0];
var nr = row + dirs[i][1];
result = result.concat(findConnectedBlocks(nc, nr, colorIndex, visited));
}
return result;
}
// Check if any moves are possible (empty cell exists)
function hasMoves() {
for (var c = 0; c < GRID_COLS; c++) {
for (var r = 0; r < GRID_ROWS; r++) {
if (!grid[c][r]) return true;
}
}
return false;
}
// --- Game Logic ---
// Handle block drop onto grid
function tryPlaceBlock(block, x, y) {
if (isProcessing) return false;
var cell = getGridCellFromPos(x, y);
if (!cell) return false;
var col = cell.col,
row = cell.row;
if (grid[col][row]) return false; // occupied
if (block.isLocked) return false; // cannot place locked blocks from nextBlocks
if (grid[col][row]) return false; // cell is occupied
if (block.colorIndex === RAINBOW_COLOR_INDEX) {
// Rainbow block special checks
}
// Save state for undo before placing
savePrevState();
if (block.colorIndex === RAINBOW_COLOR_INDEX) {
// Place rainbow block and trigger effect
placeBlockOnGrid(block, col, row);
block.isOnGrid = true;
popNextBlock(block);
// Pick a random color present on the grid (not locked, not white, not rainbow)
var presentColors = {};
for (var c2 = 0; c2 < GRID_COLS; c2++) {
for (var r2 = 0; r2 < GRID_ROWS; r2++) {
var b2 = grid[c2][r2];
if (b2 && b2.colorIndex >= 0 && b2.colorIndex <= 4) {
presentColors[b2.colorIndex] = true;
}
}
}
var colorList = [];
for (var k in presentColors) {
if (presentColors.hasOwnProperty(k)) colorList.push(parseInt(k));
}
if (colorList.length > 0) {
var colorToClear = colorList[Math.floor(Math.random() * colorList.length)];
// Animate and remove all blocks of that color
for (var c2 = 0; c2 < GRID_COLS; c2++) {
for (var r2 = 0; r2 < GRID_ROWS; r2++) {
var b2 = grid[c2][r2];
if (b2 && b2.colorIndex === colorToClear) {
var tmpBlock = b2; // Store reference before nulling the grid position
grid[c2][r2] = null;
(function (bref) {
tween(bref, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 180,
easing: tween.easeIn,
onFinish: function onFinish() {
bref.destroy();
}
});
})(tmpBlock);
}
}
}
// Add bonus score for rainbow clear
score += 200;
scoreTxt.setText(score);
}
// Play a sound for rainbow effect
LK.getSound('merge').play();
// After effect, check for game over
LK.setTimeout(function () {
if (!hasMoves()) {
LK.showGameOver();
}
}, 220);
return true;
}
// Place block
placeBlockOnGrid(block, col, row);
popNextBlock(block);
// After placement, check for merges
processMerges(col, row, function () {
// After all merges and cascades, check for game over
if (!hasMoves()) {
LK.showGameOver();
}
});
return true;
}
// Process merges and cascades starting from (col,row)
function processMerges(col, row, onFinish) {
if (isProcessing) return;
isProcessing = true;
var block = grid[col][row];
if (!block || block.isLocked) {
isProcessing = false;
if (onFinish) onFinish();
return;
}
var colorIdx = block.colorIndex;
if (colorIdx >= MAX_COLOR_INDEX) {
isProcessing = false;
if (onFinish) onFinish();
return;
}
// Find all connected blocks of same color
var connected = findConnectedBlocks(col, row, colorIdx, {});
if (connected.length >= 3) {
// Play happy merge sound only on actual merge and upgrade
LK.getSound('merge').play();
// Merge!
for (var i = 0; i < connected.length; i++) {
var b = connected[i].block;
if (b !== block) {
// Animate and remove
(function (bref) {
tween(bref, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 120,
easing: tween.easeIn,
onFinish: function onFinish() {
bref.destroy();
}
});
})(b);
removeBlockFromGrid(b.gridX, b.gridY);
}
}
// Upgrade block color
var newColor = colorIdx + 1;
if (newColor > MAX_COLOR_INDEX) newColor = MAX_COLOR_INDEX;
block.setColor(newColor);
block.animateMerge(function () {
// After animation, check for further merges (cascade)
// We need to check if the upgraded block can merge again
LK.setTimeout(function () {
// Find new connected blocks after upgrade
var newConnected = findConnectedBlocks(col, row, block.colorIndex, {});
if (newConnected.length >= 3) {
// Chain reaction: process again
processMerges(col, row, onFinish);
} else {
// No more merges, finish
isProcessing = false;
if (onFinish) onFinish();
}
}, 180);
});
// Update score
var points = 10 * connected.length * (colorIdx + 1);
score += points;
scoreTxt.setText(score);
} else {
isProcessing = false;
if (onFinish) onFinish();
}
}
// --- Input Handling ---
// Only allow dragging from nextBlocks
game.down = function (x, y, obj) {
if (isProcessing) return;
for (var i = 0; i < nextBlocks.length; i++) {
var block = nextBlocks[i];
// Check if touch is inside block
var dx = x - block.x;
var dy = y - block.y;
if (Math.abs(dx) < 90 && Math.abs(dy) < 90 && !block.isLocked && !block.isOnGrid) {
draggingBlock = block;
dragOffsetX = dx;
dragOffsetY = dy;
// Play a sound when picking up a block
LK.getSound('merge').play();
// Bring to front
game.addChild(block);
tween(block, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 80,
easing: tween.easeOut
});
break;
}
}
};
game.move = function (x, y, obj) {
if (!draggingBlock) return;
draggingBlock.x = x - dragOffsetX;
draggingBlock.y = y - dragOffsetY;
};
game.up = function (x, y, obj) {
if (!draggingBlock) return;
// Try to place on grid
var placed = tryPlaceBlock(draggingBlock, draggingBlock.x, draggingBlock.y);
if (!placed) {
// Snap back to next area
var idx = nextBlocks.indexOf(draggingBlock);
var bx = 2048 / 2 + (idx - 1) * 220;
tween(draggingBlock, {
x: bx,
y: 220,
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeInOut
});
} else {
// Play a sound when block is placed on the grid
LK.getSound('merge').play();
// Block is now on grid, don't need to do anything
}
draggingBlock = null;
};
// --- Game Update Loop ---
game.update = function () {
// Animate blocks falling off (if any)
for (var c = 0; c < GRID_COLS; c++) {
for (var r = 0; r < GRID_ROWS; r++) {
var block = grid[c][r];
if (block && block.y > BLOCK_DROP_Y) {
block.destroy();
grid[c][r] = null;
}
}
}
// Occasionally spawn a locked block in a random empty cell (every 10 turns)
if (typeof game.turnsSinceLock === "undefined") game.turnsSinceLock = 0;
if (typeof game.lastBlocksOnGrid === "undefined") game.lastBlocksOnGrid = 0;
var blocksOnGrid = 0;
for (var c = 0; c < GRID_COLS; c++) {
for (var r = 0; r < GRID_ROWS; r++) {
if (grid[c][r]) blocksOnGrid++;
}
}
if (blocksOnGrid > game.lastBlocksOnGrid) {
game.turnsSinceLock++;
game.lastBlocksOnGrid = blocksOnGrid;
if (game.turnsSinceLock >= 10) {
// Find all empty cells
var emptyCells = [];
for (var c = 0; c < GRID_COLS; c++) {
for (var r = 0; r < GRID_ROWS; r++) {
if (!grid[c][r]) emptyCells.push({
col: c,
row: r
});
}
}
if (emptyCells.length > 0) {
var idx = Math.floor(Math.random() * emptyCells.length);
var cell = emptyCells[idx];
var lockedBlock = new Block();
lockedBlock.setColor(6); // gray/locked
lockedBlock.x = getPosForCell(cell.col, cell.row).x;
lockedBlock.y = getPosForCell(cell.col, cell.row).y;
lockedBlock.isOnGrid = true;
lockedBlock.gridX = cell.col;
lockedBlock.gridY = cell.row;
grid[cell.col][cell.row] = lockedBlock;
game.addChild(lockedBlock);
}
game.turnsSinceLock = 0;
}
}
};
// --- Game Start ---
score = 0;
scoreTxt.setText(score);
refillNextBlocks(); ===================================================================
--- original.js
+++ change.js
@@ -178,16 +178,16 @@
/****
* Game Code
****/
-// locked block
-// --- Game Constants ---
-// Define block shapes for each color and merged color
-// We'll use 5 colors: red, green, blue, yellow, purple
-// Merged block (final color)
-// Sound for merge
-// visually white, but will be rainbow in logic
// More defined, fun, and clear block shapes for each color
+// visually white, but will be rainbow in logic
+// Sound for merge
+// Merged block (final color)
+// We'll use 5 colors: red, green, blue, yellow, purple
+// Define block shapes for each color and merged color
+// --- Game Constants ---
+// locked block
var GRID_COLS = 6;
var GRID_ROWS = 7;
var CELL_SIZE = 260; // px (was 200, now bigger for larger squares)
var GRID_OFFSET_X = Math.floor((2048 - GRID_COLS * CELL_SIZE) / 2);