/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Palette button class var PaletteButton = Container.expand(function () { var self = Container.call(this); self.colorId = null; self.block = self.attachAsset('color_white', { anchorX: 0.5, anchorY: 0.5 }); self.block.width = paletteCellSize; self.block.height = paletteCellSize; self.setColor = function (colorId) { self.colorId = colorId; self.removeChild(self.block); self.block = self.attachAsset(colorId, { anchorX: 0.5, anchorY: 0.5 }); self.block.width = paletteCellSize; self.block.height = paletteCellSize; }; // Touch event self.down = function (x, y, obj) { selectColor(self.colorId); }; return self; }); // Pixel cell class for the drawing grid var PixelCell = Container.expand(function () { var self = Container.call(this); self.colorId = null; // Current color id (e.g. 'color_yellow') self.gridX = 0; self.gridY = 0; // The colored block self.block = self.attachAsset('color_white', { anchorX: 0.5, anchorY: 0.5 }); self.block.width = cellSize; self.block.height = cellSize; // Draws the cell with the given color id self.setColor = function (colorId) { self.colorId = colorId; self.removeChild(self.block); self.block = self.attachAsset(colorId, { anchorX: 0.5, anchorY: 0.5 }); self.block.width = cellSize; self.block.height = cellSize; }; // For checking if the cell is filled with the correct color self.getColorId = function () { return self.colorId; }; // Touch event self.down = function (x, y, obj) { if (!selectedColorId) return; // Find grid coordinates of this cell var gx = self.gridX; var gy = self.gridY; if (fillMode) { // --- FILL TOOL --- var targetColor = self.getColorId(); if (targetColor === selectedColorId) return; // Already filled // Flood fill algorithm (non-recursive, stack-based) var stack = []; stack.push([gx, gy]); var visited = {}; while (stack.length > 0) { var pos = stack.pop(); var px = pos[0]; var py = pos[1]; var key = px + ',' + py; if (visited[key]) continue; visited[key] = true; if (px >= 0 && px < gridCols && py >= 0 && py < gridRows && gridCells[py][px].getColorId() === targetColor) { gridCells[py][px].setColor(selectedColorId); // Add neighbors stack.push([px - 1, py]); stack.push([px + 1, py]); stack.push([px, py - 1]); stack.push([px, py + 1]); } } checkIfComplete(); return; } // --- BRUSH TOOL --- var size = brushSize; for (var dy = 0; dy < size; dy++) { for (var dx = 0; dx < size; dx++) { var px = gx + dx; var py = gy + dy; if (px < gridCols && py < gridRows) { gridCells[py][px].setColor(selectedColorId); } } } checkIfComplete(); }; return self; }); // Reference cell class (non-interactive, just for showing the reference) var ReferenceCell = Container.expand(function () { var self = Container.call(this); self.block = self.attachAsset('color_white', { anchorX: 0.5, anchorY: 0.5 }); self.block.width = cellSize; self.block.height = cellSize; self.setColor = function (colorId) { self.removeChild(self.block); self.block = self.attachAsset(colorId, { anchorX: 0.5, anchorY: 0.5 }); self.block.width = cellSize; self.block.height = cellSize; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xE0E0E0 }); /**** * Game Code ****/ // This block is moved to ensure correct data initialization. // --- CONFIGURATION --- // Define color palette for SpongeBob pixel art (approximate colors) // Reference image: We'll use a grid of colored blocks as a reference (not an actual image asset, but a grid rendered in-game). var gridCols = 12; var gridRows = 16; var cellSize = 90; // px, for main grid var paletteCellSize = 80; // px, for palette // Center the grid var gridStartX = Math.floor((2048 - gridCols * cellSize) / 2); var gridStartY = 350; // Reference grid (smaller, at top) var refCellSize = 40; var refGridStartX = Math.floor((2048 - gridCols * refCellSize) / 2); var refGridStartY = 120; // Palette bar var paletteStartY = 2732 - 220; // Color palette (order matters for palette bar) var colorPalette = ['color_yellow', 'color_white', 'color_black', 'color_brown', 'color_blue', 'color_red', 'color_pink', 'color_green']; // Map colorId to color name for display var colorNames = { 'color_yellow': 'Yellow', 'color_white': 'White', 'color_black': 'Black', 'color_brown': 'Brown', 'color_blue': 'Blue', 'color_red': 'Red', 'color_pink': 'Pink', 'color_green': 'Green' }; // The reference pixel art for SpongeBob (12x16 grid, using colorPalette indices) // 0: yellow, 1: white, 2: black, 3: brown, 4: blue, 5: red, 6: pink, 7: green // Improved SpongeBob reference pixel art (12x16 grid) // 0: yellow, 1: white, 2: black, 3: brown, 4: blue, 5: red, 6: pink, 7: green var spongebobReference = [[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2], [2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2], [2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2], [2, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 2], [2, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2], [2, 0, 4, 4, 1, 1, 1, 1, 4, 4, 0, 2], [2, 0, 4, 4, 1, 1, 1, 1, 4, 4, 0, 2], [2, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 2], [2, 0, 0, 7, 7, 0, 0, 7, 7, 0, 0, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]]; // Convert indices to colorIds for easier comparison function getColorIdByIndex(idx) { return colorPalette[idx]; } var spongebobReferenceColorIds = []; for (var y = 0; y < gridRows; y++) { var row = []; for (var x = 0; x < gridCols; x++) { row.push(getColorIdByIndex(spongebobReference[y][x])); } spongebobReferenceColorIds.push(row); } // spongebobReferenceColorIds array creation moved after spongebobReference definition is finalized. // --- STATE --- var gridCells = []; // 2D array of PixelCell var selectedColorId = colorPalette[0]; // Default selected color var paletteButtons = []; var isComplete = false; // --- UI --- // Title var titleText = new Text2('SpongeBob Pixel Art', { size: 90, fill: 0x222222 }); titleText.anchor.set(0.5, 0); LK.gui.top.addChild(titleText); // Instructions var instrText = new Text2('Tap a color, then tap the grid to fill. Try to match the reference above!', { size: 48, fill: 0x444444 }); instrText.anchor.set(0.5, 0); LK.gui.top.addChild(instrText); instrText.y = 110; // --- REFERENCE GRID --- var referenceCells = []; for (var y = 0; y < gridRows; y++) { var row = []; for (var x = 0; x < gridCols; x++) { var refCell = new ReferenceCell(); refCell.setColor(spongebobReferenceColorIds[y][x]); refCell.x = refGridStartX + x * refCellSize + refCellSize / 2; refCell.y = refGridStartY + y * refCellSize + refCellSize / 2; game.addChild(refCell); row.push(refCell); } referenceCells.push(row); } // --- MAIN DRAWING GRID --- for (var y = 0; y < gridRows; y++) { var row = []; for (var x = 0; x < gridCols; x++) { var cell = new PixelCell(); cell.x = gridStartX + x * cellSize + cellSize / 2; cell.y = gridStartY + y * cellSize + cellSize / 2; cell.gridX = x; cell.gridY = y; cell.setColor('color_white'); game.addChild(cell); row.push(cell); } gridCells.push(row); } // --- PALETTE BAR --- var paletteBarWidth = colorPalette.length * (paletteCellSize + 24) - 24; var paletteBarStartX = Math.floor((2048 - paletteBarWidth) / 2); for (var i = 0; i < colorPalette.length; i++) { var colorId = colorPalette[i]; var btn = new PaletteButton(); btn.setColor(colorId); btn.x = paletteBarStartX + i * (paletteCellSize + 24) + paletteCellSize / 2; btn.y = paletteStartY + paletteCellSize / 2; game.addChild(btn); paletteButtons.push(btn); } // --- BRUSH SIZE & FILL TOOL UI --- // Place these tools vertically on the right side of the screen, above the palette bar var toolButtonSize = 100; var toolButtonMargin = 32; var toolStartX = 2048 - toolButtonSize - 40; var toolStartY = paletteStartY - (toolButtonSize + toolButtonMargin) * 2; // Brush size state: 1 or 2 (for 1x1 or 2x2) var brushSize = 1; var fillMode = false; // Brush 1x1 button var brush1Btn = LK.getAsset('color_black', { anchorX: 0.5, anchorY: 0.5 }); brush1Btn.width = toolButtonSize; brush1Btn.height = toolButtonSize; brush1Btn.alpha = 0.18; brush1Btn.x = toolStartX + toolButtonSize / 2; brush1Btn.y = toolStartY + toolButtonSize / 2; game.addChild(brush1Btn); var brush1Icon = new Text2('1x1', { size: 44, fill: 0x222222 }); brush1Icon.anchor.set(0.5, 0.5); brush1Icon.x = brush1Btn.x; brush1Icon.y = brush1Btn.y; game.addChild(brush1Icon); // Brush 2x2 button var brush2Btn = LK.getAsset('color_black', { anchorX: 0.5, anchorY: 0.5 }); brush2Btn.width = toolButtonSize; brush2Btn.height = toolButtonSize; brush2Btn.alpha = 0.18; brush2Btn.x = toolStartX + toolButtonSize / 2; brush2Btn.y = toolStartY + toolButtonSize * 1.5 + toolButtonMargin; game.addChild(brush2Btn); var brush2Icon = new Text2('2x2', { size: 44, fill: 0x222222 }); brush2Icon.anchor.set(0.5, 0.5); brush2Icon.x = brush2Btn.x; brush2Icon.y = brush2Btn.y; game.addChild(brush2Icon); // Fill tool button var fillBtn = LK.getAsset('color_black', { anchorX: 0.5, anchorY: 0.5 }); fillBtn.width = toolButtonSize; fillBtn.height = toolButtonSize; fillBtn.alpha = 0.18; fillBtn.x = toolStartX + toolButtonSize / 2; fillBtn.y = toolStartY + toolButtonSize * 2.5 + toolButtonMargin * 2; game.addChild(fillBtn); var fillIcon = new Text2('Fill', { size: 44, fill: 0x222222 }); fillIcon.anchor.set(0.5, 0.5); fillIcon.x = fillBtn.x; fillIcon.y = fillBtn.y; game.addChild(fillIcon); // Tool selection indicator var toolIndicator = LK.getAsset('color_blue', { anchorX: 0.5, anchorY: 0.5 }); toolIndicator.width = toolButtonSize + 16; toolIndicator.height = toolButtonSize + 16; toolIndicator.alpha = 0.22; game.addChild(toolIndicator); // Set initial tool indicator position function updateToolIndicator() { if (fillMode) { toolIndicator.x = fillBtn.x; toolIndicator.y = fillBtn.y; } else if (brushSize === 2) { toolIndicator.x = brush2Btn.x; toolIndicator.y = brush2Btn.y; } else { toolIndicator.x = brush1Btn.x; toolIndicator.y = brush1Btn.y; } } updateToolIndicator(); // Tool button events brush1Btn.down = function () { brushSize = 1; fillMode = false; updateToolIndicator(); }; brush2Btn.down = function () { brushSize = 2; fillMode = false; updateToolIndicator(); }; fillBtn.down = function () { fillMode = true; updateToolIndicator(); }; // --- PALETTE SELECTION INDICATOR --- var paletteIndicator = LK.getAsset('color_black', { anchorX: 0.5, anchorY: 0.5 }); paletteIndicator.width = paletteCellSize + 16; paletteIndicator.height = paletteCellSize + 16; paletteIndicator.alpha = 0.25; game.addChild(paletteIndicator); // --- MINI SPONGEBOB REFERENCE AT BOTTOM --- // Use the SpongeBobReference image asset at the bottom center as a reference // Set the mini reference image to be a square aspect ratio var miniRefImageSize = 384; // Make it a square, same as previous height var miniRefGridMarginAbovePalette = 40; // Margin between top of palette and bottom of mini-grid var miniRefImageBottomY = paletteStartY - miniRefGridMarginAbovePalette; var miniRefImageStartX = Math.floor((2048 - miniRefImageSize) / 2); var miniRefImageStartY = miniRefImageBottomY - miniRefImageSize; // Add the reference image asset as a square var miniRefImage = LK.getAsset('SpongeBobReference', { anchorX: 0, anchorY: 0, x: miniRefImageStartX, y: miniRefImageStartY, width: miniRefImageSize, height: miniRefImageSize, alpha: 0.95 }); game.addChild(miniRefImage); // --- PALETTE SELECTION LOGIC --- // Play and loop the music asset named Music on first user interaction (to comply with browser autoplay policies) var musicStarted = false; function startMusicIfNeeded() { if (!musicStarted) { LK.playMusic('Music', { loop: true }); musicStarted = true; } } // Listen for first interaction to start music game.down = function (x, y, obj) { startMusicIfNeeded(); // If a palette button or grid cell is pressed, their own .down will also be called }; function selectColor(colorId) { selectedColorId = colorId; // Move indicator to selected button for (var i = 0; i < paletteButtons.length; i++) { if (paletteButtons[i].colorId === colorId) { paletteIndicator.x = paletteButtons[i].x; paletteIndicator.y = paletteButtons[i].y; break; } } } selectColor(selectedColorId); // --- COMPLETION CHECK --- function checkIfComplete() { if (isComplete) return; for (var y = 0; y < gridRows; y++) { for (var x = 0; x < gridCols; x++) { if (gridCells[y][x].getColorId() !== spongebobReferenceColorIds[y][x]) { return; } } } // All cells match! isComplete = true; showCompletion(); } // --- COMPLETION UI --- function showCompletion() { // Flash green LK.effects.flashScreen(0x7ED957, 800); // Show "You did it!" message var winText = new Text2('You did it!', { size: 120, fill: 0x7ED957 }); winText.anchor.set(0.5, 0.5); winText.x = 2048 / 2; winText.y = 2732 / 2 - 100; game.addChild(winText); var compareText = new Text2('Your SpongeBob matches the reference!', { size: 60, fill: 0x222222 }); compareText.anchor.set(0.5, 0.5); compareText.x = 2048 / 2; compareText.y = 2732 / 2 + 40; game.addChild(compareText); // Animate winText tween(winText, { scaleX: 1.2, scaleY: 1.2 }, { duration: 400, easing: tween.elasticOut, onFinish: function onFinish() { tween(winText, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); } }); } // --- GAME UPDATE --- game.update = function () { // No per-frame logic needed for this game }; // --- DRAG PREVENTION --- // No drag logic needed; all interaction is tap/click // --- GUI LAYOUT --- // Position title and instructions titleText.x = 2048 / 2; titleText.y = 20; instrText.x = 2048 / 2; instrText.y = 120; // --- END OF GAME CODE ---
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Palette button class
var PaletteButton = Container.expand(function () {
var self = Container.call(this);
self.colorId = null;
self.block = self.attachAsset('color_white', {
anchorX: 0.5,
anchorY: 0.5
});
self.block.width = paletteCellSize;
self.block.height = paletteCellSize;
self.setColor = function (colorId) {
self.colorId = colorId;
self.removeChild(self.block);
self.block = self.attachAsset(colorId, {
anchorX: 0.5,
anchorY: 0.5
});
self.block.width = paletteCellSize;
self.block.height = paletteCellSize;
};
// Touch event
self.down = function (x, y, obj) {
selectColor(self.colorId);
};
return self;
});
// Pixel cell class for the drawing grid
var PixelCell = Container.expand(function () {
var self = Container.call(this);
self.colorId = null; // Current color id (e.g. 'color_yellow')
self.gridX = 0;
self.gridY = 0;
// The colored block
self.block = self.attachAsset('color_white', {
anchorX: 0.5,
anchorY: 0.5
});
self.block.width = cellSize;
self.block.height = cellSize;
// Draws the cell with the given color id
self.setColor = function (colorId) {
self.colorId = colorId;
self.removeChild(self.block);
self.block = self.attachAsset(colorId, {
anchorX: 0.5,
anchorY: 0.5
});
self.block.width = cellSize;
self.block.height = cellSize;
};
// For checking if the cell is filled with the correct color
self.getColorId = function () {
return self.colorId;
};
// Touch event
self.down = function (x, y, obj) {
if (!selectedColorId) return;
// Find grid coordinates of this cell
var gx = self.gridX;
var gy = self.gridY;
if (fillMode) {
// --- FILL TOOL ---
var targetColor = self.getColorId();
if (targetColor === selectedColorId) return; // Already filled
// Flood fill algorithm (non-recursive, stack-based)
var stack = [];
stack.push([gx, gy]);
var visited = {};
while (stack.length > 0) {
var pos = stack.pop();
var px = pos[0];
var py = pos[1];
var key = px + ',' + py;
if (visited[key]) continue;
visited[key] = true;
if (px >= 0 && px < gridCols && py >= 0 && py < gridRows && gridCells[py][px].getColorId() === targetColor) {
gridCells[py][px].setColor(selectedColorId);
// Add neighbors
stack.push([px - 1, py]);
stack.push([px + 1, py]);
stack.push([px, py - 1]);
stack.push([px, py + 1]);
}
}
checkIfComplete();
return;
}
// --- BRUSH TOOL ---
var size = brushSize;
for (var dy = 0; dy < size; dy++) {
for (var dx = 0; dx < size; dx++) {
var px = gx + dx;
var py = gy + dy;
if (px < gridCols && py < gridRows) {
gridCells[py][px].setColor(selectedColorId);
}
}
}
checkIfComplete();
};
return self;
});
// Reference cell class (non-interactive, just for showing the reference)
var ReferenceCell = Container.expand(function () {
var self = Container.call(this);
self.block = self.attachAsset('color_white', {
anchorX: 0.5,
anchorY: 0.5
});
self.block.width = cellSize;
self.block.height = cellSize;
self.setColor = function (colorId) {
self.removeChild(self.block);
self.block = self.attachAsset(colorId, {
anchorX: 0.5,
anchorY: 0.5
});
self.block.width = cellSize;
self.block.height = cellSize;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xE0E0E0
});
/****
* Game Code
****/
// This block is moved to ensure correct data initialization.
// --- CONFIGURATION ---
// Define color palette for SpongeBob pixel art (approximate colors)
// Reference image: We'll use a grid of colored blocks as a reference (not an actual image asset, but a grid rendered in-game).
var gridCols = 12;
var gridRows = 16;
var cellSize = 90; // px, for main grid
var paletteCellSize = 80; // px, for palette
// Center the grid
var gridStartX = Math.floor((2048 - gridCols * cellSize) / 2);
var gridStartY = 350;
// Reference grid (smaller, at top)
var refCellSize = 40;
var refGridStartX = Math.floor((2048 - gridCols * refCellSize) / 2);
var refGridStartY = 120;
// Palette bar
var paletteStartY = 2732 - 220;
// Color palette (order matters for palette bar)
var colorPalette = ['color_yellow', 'color_white', 'color_black', 'color_brown', 'color_blue', 'color_red', 'color_pink', 'color_green'];
// Map colorId to color name for display
var colorNames = {
'color_yellow': 'Yellow',
'color_white': 'White',
'color_black': 'Black',
'color_brown': 'Brown',
'color_blue': 'Blue',
'color_red': 'Red',
'color_pink': 'Pink',
'color_green': 'Green'
};
// The reference pixel art for SpongeBob (12x16 grid, using colorPalette indices)
// 0: yellow, 1: white, 2: black, 3: brown, 4: blue, 5: red, 6: pink, 7: green
// Improved SpongeBob reference pixel art (12x16 grid)
// 0: yellow, 1: white, 2: black, 3: brown, 4: blue, 5: red, 6: pink, 7: green
var spongebobReference = [[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2], [2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], [2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2], [2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2], [2, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 2], [2, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2], [2, 0, 4, 4, 1, 1, 1, 1, 4, 4, 0, 2], [2, 0, 4, 4, 1, 1, 1, 1, 4, 4, 0, 2], [2, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 2], [2, 0, 0, 7, 7, 0, 0, 7, 7, 0, 0, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]];
// Convert indices to colorIds for easier comparison
function getColorIdByIndex(idx) {
return colorPalette[idx];
}
var spongebobReferenceColorIds = [];
for (var y = 0; y < gridRows; y++) {
var row = [];
for (var x = 0; x < gridCols; x++) {
row.push(getColorIdByIndex(spongebobReference[y][x]));
}
spongebobReferenceColorIds.push(row);
}
// spongebobReferenceColorIds array creation moved after spongebobReference definition is finalized.
// --- STATE ---
var gridCells = []; // 2D array of PixelCell
var selectedColorId = colorPalette[0]; // Default selected color
var paletteButtons = [];
var isComplete = false;
// --- UI ---
// Title
var titleText = new Text2('SpongeBob Pixel Art', {
size: 90,
fill: 0x222222
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
// Instructions
var instrText = new Text2('Tap a color, then tap the grid to fill. Try to match the reference above!', {
size: 48,
fill: 0x444444
});
instrText.anchor.set(0.5, 0);
LK.gui.top.addChild(instrText);
instrText.y = 110;
// --- REFERENCE GRID ---
var referenceCells = [];
for (var y = 0; y < gridRows; y++) {
var row = [];
for (var x = 0; x < gridCols; x++) {
var refCell = new ReferenceCell();
refCell.setColor(spongebobReferenceColorIds[y][x]);
refCell.x = refGridStartX + x * refCellSize + refCellSize / 2;
refCell.y = refGridStartY + y * refCellSize + refCellSize / 2;
game.addChild(refCell);
row.push(refCell);
}
referenceCells.push(row);
}
// --- MAIN DRAWING GRID ---
for (var y = 0; y < gridRows; y++) {
var row = [];
for (var x = 0; x < gridCols; x++) {
var cell = new PixelCell();
cell.x = gridStartX + x * cellSize + cellSize / 2;
cell.y = gridStartY + y * cellSize + cellSize / 2;
cell.gridX = x;
cell.gridY = y;
cell.setColor('color_white');
game.addChild(cell);
row.push(cell);
}
gridCells.push(row);
}
// --- PALETTE BAR ---
var paletteBarWidth = colorPalette.length * (paletteCellSize + 24) - 24;
var paletteBarStartX = Math.floor((2048 - paletteBarWidth) / 2);
for (var i = 0; i < colorPalette.length; i++) {
var colorId = colorPalette[i];
var btn = new PaletteButton();
btn.setColor(colorId);
btn.x = paletteBarStartX + i * (paletteCellSize + 24) + paletteCellSize / 2;
btn.y = paletteStartY + paletteCellSize / 2;
game.addChild(btn);
paletteButtons.push(btn);
}
// --- BRUSH SIZE & FILL TOOL UI ---
// Place these tools vertically on the right side of the screen, above the palette bar
var toolButtonSize = 100;
var toolButtonMargin = 32;
var toolStartX = 2048 - toolButtonSize - 40;
var toolStartY = paletteStartY - (toolButtonSize + toolButtonMargin) * 2;
// Brush size state: 1 or 2 (for 1x1 or 2x2)
var brushSize = 1;
var fillMode = false;
// Brush 1x1 button
var brush1Btn = LK.getAsset('color_black', {
anchorX: 0.5,
anchorY: 0.5
});
brush1Btn.width = toolButtonSize;
brush1Btn.height = toolButtonSize;
brush1Btn.alpha = 0.18;
brush1Btn.x = toolStartX + toolButtonSize / 2;
brush1Btn.y = toolStartY + toolButtonSize / 2;
game.addChild(brush1Btn);
var brush1Icon = new Text2('1x1', {
size: 44,
fill: 0x222222
});
brush1Icon.anchor.set(0.5, 0.5);
brush1Icon.x = brush1Btn.x;
brush1Icon.y = brush1Btn.y;
game.addChild(brush1Icon);
// Brush 2x2 button
var brush2Btn = LK.getAsset('color_black', {
anchorX: 0.5,
anchorY: 0.5
});
brush2Btn.width = toolButtonSize;
brush2Btn.height = toolButtonSize;
brush2Btn.alpha = 0.18;
brush2Btn.x = toolStartX + toolButtonSize / 2;
brush2Btn.y = toolStartY + toolButtonSize * 1.5 + toolButtonMargin;
game.addChild(brush2Btn);
var brush2Icon = new Text2('2x2', {
size: 44,
fill: 0x222222
});
brush2Icon.anchor.set(0.5, 0.5);
brush2Icon.x = brush2Btn.x;
brush2Icon.y = brush2Btn.y;
game.addChild(brush2Icon);
// Fill tool button
var fillBtn = LK.getAsset('color_black', {
anchorX: 0.5,
anchorY: 0.5
});
fillBtn.width = toolButtonSize;
fillBtn.height = toolButtonSize;
fillBtn.alpha = 0.18;
fillBtn.x = toolStartX + toolButtonSize / 2;
fillBtn.y = toolStartY + toolButtonSize * 2.5 + toolButtonMargin * 2;
game.addChild(fillBtn);
var fillIcon = new Text2('Fill', {
size: 44,
fill: 0x222222
});
fillIcon.anchor.set(0.5, 0.5);
fillIcon.x = fillBtn.x;
fillIcon.y = fillBtn.y;
game.addChild(fillIcon);
// Tool selection indicator
var toolIndicator = LK.getAsset('color_blue', {
anchorX: 0.5,
anchorY: 0.5
});
toolIndicator.width = toolButtonSize + 16;
toolIndicator.height = toolButtonSize + 16;
toolIndicator.alpha = 0.22;
game.addChild(toolIndicator);
// Set initial tool indicator position
function updateToolIndicator() {
if (fillMode) {
toolIndicator.x = fillBtn.x;
toolIndicator.y = fillBtn.y;
} else if (brushSize === 2) {
toolIndicator.x = brush2Btn.x;
toolIndicator.y = brush2Btn.y;
} else {
toolIndicator.x = brush1Btn.x;
toolIndicator.y = brush1Btn.y;
}
}
updateToolIndicator();
// Tool button events
brush1Btn.down = function () {
brushSize = 1;
fillMode = false;
updateToolIndicator();
};
brush2Btn.down = function () {
brushSize = 2;
fillMode = false;
updateToolIndicator();
};
fillBtn.down = function () {
fillMode = true;
updateToolIndicator();
};
// --- PALETTE SELECTION INDICATOR ---
var paletteIndicator = LK.getAsset('color_black', {
anchorX: 0.5,
anchorY: 0.5
});
paletteIndicator.width = paletteCellSize + 16;
paletteIndicator.height = paletteCellSize + 16;
paletteIndicator.alpha = 0.25;
game.addChild(paletteIndicator);
// --- MINI SPONGEBOB REFERENCE AT BOTTOM ---
// Use the SpongeBobReference image asset at the bottom center as a reference
// Set the mini reference image to be a square aspect ratio
var miniRefImageSize = 384; // Make it a square, same as previous height
var miniRefGridMarginAbovePalette = 40; // Margin between top of palette and bottom of mini-grid
var miniRefImageBottomY = paletteStartY - miniRefGridMarginAbovePalette;
var miniRefImageStartX = Math.floor((2048 - miniRefImageSize) / 2);
var miniRefImageStartY = miniRefImageBottomY - miniRefImageSize;
// Add the reference image asset as a square
var miniRefImage = LK.getAsset('SpongeBobReference', {
anchorX: 0,
anchorY: 0,
x: miniRefImageStartX,
y: miniRefImageStartY,
width: miniRefImageSize,
height: miniRefImageSize,
alpha: 0.95
});
game.addChild(miniRefImage);
// --- PALETTE SELECTION LOGIC ---
// Play and loop the music asset named Music on first user interaction (to comply with browser autoplay policies)
var musicStarted = false;
function startMusicIfNeeded() {
if (!musicStarted) {
LK.playMusic('Music', {
loop: true
});
musicStarted = true;
}
}
// Listen for first interaction to start music
game.down = function (x, y, obj) {
startMusicIfNeeded();
// If a palette button or grid cell is pressed, their own .down will also be called
};
function selectColor(colorId) {
selectedColorId = colorId;
// Move indicator to selected button
for (var i = 0; i < paletteButtons.length; i++) {
if (paletteButtons[i].colorId === colorId) {
paletteIndicator.x = paletteButtons[i].x;
paletteIndicator.y = paletteButtons[i].y;
break;
}
}
}
selectColor(selectedColorId);
// --- COMPLETION CHECK ---
function checkIfComplete() {
if (isComplete) return;
for (var y = 0; y < gridRows; y++) {
for (var x = 0; x < gridCols; x++) {
if (gridCells[y][x].getColorId() !== spongebobReferenceColorIds[y][x]) {
return;
}
}
}
// All cells match!
isComplete = true;
showCompletion();
}
// --- COMPLETION UI ---
function showCompletion() {
// Flash green
LK.effects.flashScreen(0x7ED957, 800);
// Show "You did it!" message
var winText = new Text2('You did it!', {
size: 120,
fill: 0x7ED957
});
winText.anchor.set(0.5, 0.5);
winText.x = 2048 / 2;
winText.y = 2732 / 2 - 100;
game.addChild(winText);
var compareText = new Text2('Your SpongeBob matches the reference!', {
size: 60,
fill: 0x222222
});
compareText.anchor.set(0.5, 0.5);
compareText.x = 2048 / 2;
compareText.y = 2732 / 2 + 40;
game.addChild(compareText);
// Animate winText
tween(winText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(winText, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
// --- GAME UPDATE ---
game.update = function () {
// No per-frame logic needed for this game
};
// --- DRAG PREVENTION ---
// No drag logic needed; all interaction is tap/click
// --- GUI LAYOUT ---
// Position title and instructions
titleText.x = 2048 / 2;
titleText.y = 20;
instrText.x = 2048 / 2;
instrText.y = 120;
// --- END OF GAME CODE ---