User prompt
make the tile a little more vibrant ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add rainbow color
User prompt
remove the color yellow and a rainbow
User prompt
make the color more vibrante ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when you open the menu make it bigger
User prompt
give more color choices
User prompt
the background is not changing
User prompt
make a menu button to change the background
User prompt
remove the bug in the tutorial
User prompt
only solve the first row
User prompt
there is a bug in the tutorial
User prompt
there is a bug
User prompt
there is a bug
User prompt
make the tutorial move the block until it is complete in the first level ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
there is a bug when the tutorial move the block in the first level ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the tutorial move the block step by step ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the got it button a little bigger
User prompt
there is a bug the tutorial button does not work
User prompt
make the tutorial button work
User prompt
make the tutorial button smaller
User prompt
put the the welcome to puzzle it button in the middle and make it small
User prompt
make a tutorial in the first level
User prompt
when level compele show new round button
User prompt
move the moves: block to the up left
User prompt
add a remix button t remix the block
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // PuzzleTile: Represents a single tile in the puzzle grid. var PuzzleTile = Container.expand(function () { var self = Container.call(this); // Properties self.gridX = 0; // grid position x self.gridY = 0; // grid position y self.correctX = 0; // correct grid position x self.correctY = 0; // correct grid position y self.tileIndex = 0; // index in the tile array self.isEmpty = false; // is this the empty tile? // The tile's visual var tileAsset = self.attachAsset('tile', { anchorX: 0, anchorY: 0 }); // For MVP, we color each tile differently for visual distinction self.setColor = function (color) { tileAsset.color = color; tileAsset.tint = color; }; // Set the label (number) for the tile self.setLabel = function (label) { if (self.labelText) { self.labelText.setText(label); } else { var txt = new Text2(label + '', { size: 120, fill: 0x222222 }); txt.anchor.set(0.5, 0.5); txt.x = tileAsset.width / 2; txt.y = tileAsset.height / 2; self.addChild(txt); self.labelText = txt; } }; // Hide label for empty tile self.hideLabel = function () { if (self.labelText) { self.labelText.visible = false; } }; // Show label self.showLabel = function () { if (self.labelText) { self.labelText.visible = true; } }; // Animate to a new position self.moveTo = function (x, y, duration) { tween(self, { x: x, y: y }, { duration: duration || 200, easing: tween.cubicOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // In the future, this can be replaced with a real image or a procedurally generated pattern. // For MVP, we use a colored box as a placeholder for each tile, with a random color per game. // We'll use a single image asset for the puzzle, which will be randomly generated each game. // --- Puzzle Settings --- var gridSize = 4; // 4x4 grid (15-puzzle style) var tileSize = 400; // px, will be scaled to fit screen var tileSpacing = 12; // px gap between tiles var puzzleOffsetX = 0; var puzzleOffsetY = 0; var puzzleWidth = gridSize * tileSize + (gridSize - 1) * tileSpacing; var puzzleHeight = gridSize * tileSize + (gridSize - 1) * tileSpacing; // --- State --- var tiles = []; // 2D array [y][x] of PuzzleTile var tileList = []; // flat array of all PuzzleTile var emptyTile = null; // reference to the empty tile var moveCount = 0; var startTime = 0; var timerInterval = null; var isSolved = false; // --- UI --- var moveText = new Text2('Moves: 0', { size: 90, fill: 0xFFFFFF }); moveText.anchor.set(0, 0); // Anchor to top-left for easier positioning LK.gui.topLeft.addChild(moveText); // Add to topLeft GUI container var timeText = new Text2('Time: 0s', { size: 90, fill: 0xFFFFFF }); timeText.anchor.set(0.5, 0); LK.gui.top.addChild(timeText); // Keep timeText in the top-center // Position UI moveText.x = 20; // Small margin from the left edge moveText.y = 120; // Position below the platform menu icon area timeText.x = LK.gui.top.width / 2; // Center timeText timeText.y = 20; // --- Remix Button --- var remixBtn = new Text2('Remix', { size: 90, fill: 0xFFD700 }); remixBtn.anchor.set(0.5, 0); remixBtn.x = LK.gui.top.width / 2; remixBtn.y = 120; remixBtn.interactive = true; remixBtn.buttonMode = true; remixBtn.down = function (x, y, obj) { if (isSolved) return; shufflePuzzle(); moveCount = 0; startTime = Date.now(); updateUI(); }; LK.gui.top.addChild(remixBtn); // --- New Round Button --- var newRoundBtn = new Text2('New Round', { size: 90, fill: 0x4CAF50 // A nice green color for the new round button }); newRoundBtn.anchor.set(0.5, 0); newRoundBtn.x = LK.gui.top.width / 2; newRoundBtn.y = remixBtn.y + remixBtn.height + 30; // Position below the Remix button with some padding newRoundBtn.interactive = true; newRoundBtn.buttonMode = true; newRoundBtn.visible = false; // Initially hidden newRoundBtn.down = function (x, y, obj) { createPuzzle(); // This will re-initialize the game, hide this button, and reset isSolved }; LK.gui.top.addChild(newRoundBtn); // --- Helper Functions --- // Generate a random color palette for the puzzle function generateColorPalette(n) { var colors = []; var baseHue = Math.floor(Math.random() * 360); for (var i = 0; i < n; i++) { // HSL to RGB conversion var hue = (baseHue + i * (360 / n)) % 360; var rgb = hslToRgb(hue / 360, 0.6, 0.6); var color = rgb[0] << 16 | rgb[1] << 8 | rgb[2]; colors.push(color); } return colors; } // HSL to RGB helper function hslToRgb(h, s, l) { var r, g, b; if (s == 0) { r = g = b = l; } else { var hue2rgb = function hue2rgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; }; var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; } // Shuffle an array in-place function shuffleArray(arr) { for (var i = arr.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } // Check if the puzzle is solved function checkSolved() { for (var y = 0; y < gridSize; y++) { for (var x = 0; x < gridSize; x++) { var tile = tiles[y][x]; if (tile.gridX !== tile.correctX || tile.gridY !== tile.correctY) { return false; } } } return true; } // Update move and time UI function updateUI() { moveText.setText('Moves: ' + moveCount); var elapsed = Math.floor((Date.now() - startTime) / 1000); timeText.setText('Time: ' + elapsed + 's'); } // --- Puzzle Generation --- function createPuzzle() { if (typeof newRoundBtn !== 'undefined' && newRoundBtn) { newRoundBtn.visible = false; } if (typeof hideTutorial === 'function') { hideTutorial(); } // Remove old tiles for (var i = 0; i < tileList.length; i++) { tileList[i].destroy(); } tiles = []; tileList = []; emptyTile = null; isSolved = false; moveCount = 0; updateUI(); // Generate color palette var numTiles = gridSize * gridSize; var colors = generateColorPalette(numTiles - 1); // Calculate tile size to fit screen var maxWidth = 2048 - 200; var maxHeight = 2732 - 400; tileSize = Math.floor(Math.min((maxWidth - (gridSize - 1) * tileSpacing) / gridSize, (maxHeight - (gridSize - 1) * tileSpacing) / gridSize)); puzzleWidth = gridSize * tileSize + (gridSize - 1) * tileSpacing; puzzleHeight = gridSize * tileSize + (gridSize - 1) * tileSpacing; puzzleOffsetX = Math.floor((2048 - puzzleWidth) / 2); puzzleOffsetY = Math.floor((2732 - puzzleHeight) / 2) + 80; // Create tiles in solved order var idx = 0; for (var y = 0; y < gridSize; y++) { tiles[y] = []; for (var x = 0; x < gridSize; x++) { var tile = new PuzzleTile(); tile.gridX = x; tile.gridY = y; tile.correctX = x; tile.correctY = y; tile.tileIndex = idx; tile.x = puzzleOffsetX + x * (tileSize + tileSpacing); tile.y = puzzleOffsetY + y * (tileSize + tileSpacing); tile.width = tileSize; tile.height = tileSize; tile.setColor(colors[idx] || 0x222222); tile.setLabel(idx + 1); tile.isEmpty = false; tileList.push(tile); tiles[y][x] = tile; game.addChild(tile); idx++; } } // Make last tile the empty tile var lastTile = tiles[gridSize - 1][gridSize - 1]; lastTile.isEmpty = true; lastTile.setColor(0x222222); lastTile.hideLabel(); emptyTile = lastTile; // Shuffle tiles shufflePuzzle(); // Start timer startTime = Date.now(); if (timerInterval) LK.clearInterval(timerInterval); timerInterval = LK.setInterval(updateUI, 500); } // Shuffle the puzzle by simulating random valid moves function shufflePuzzle() { var moves = [[0, 1], [1, 0], [0, -1], [-1, 0]]; var prevX = emptyTile.gridX, prevY = emptyTile.gridY; var shuffleCount = 200 + Math.floor(Math.random() * 100); for (var i = 0; i < shuffleCount; i++) { var possible = []; for (var d = 0; d < moves.length; d++) { var nx = emptyTile.gridX + moves[d][0]; var ny = emptyTile.gridY + moves[d][1]; if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize) { if (!(nx === prevX && ny === prevY)) { possible.push([nx, ny]); } } } if (possible.length === 0) continue; var pick = possible[Math.floor(Math.random() * possible.length)]; var tile = tiles[pick[1]][pick[0]]; swapWithEmpty(tile, false); prevX = emptyTile.gridX; prevY = emptyTile.gridY; } // After shuffling, update all tile positions visually for (var y = 0; y < gridSize; y++) { for (var x = 0; x < gridSize; x++) { var tile = tiles[y][x]; tile.x = puzzleOffsetX + x * (tileSize + tileSpacing); tile.y = puzzleOffsetY + y * (tileSize + tileSpacing); tile.gridX = x; tile.gridY = y; } } } // Swap a tile with the empty tile (if adjacent) function swapWithEmpty(tile, animate) { if (tile.isEmpty) return false; var dx = Math.abs(tile.gridX - emptyTile.gridX); var dy = Math.abs(tile.gridY - emptyTile.gridY); if (dx === 1 && dy === 0 || dx === 0 && dy === 1) { // Swap in tiles array var tx = tile.gridX, ty = tile.gridY; var ex = emptyTile.gridX, ey = emptyTile.gridY; tiles[ty][tx] = emptyTile; tiles[ey][ex] = tile; // Swap grid positions var tmpX = tile.gridX, tmpY = tile.gridY; tile.gridX = emptyTile.gridX; tile.gridY = emptyTile.gridY; emptyTile.gridX = tmpX; emptyTile.gridY = tmpY; // Animate movement var tileTargetX = puzzleOffsetX + tile.gridX * (tileSize + tileSpacing); var tileTargetY = puzzleOffsetY + tile.gridY * (tileSize + tileSpacing); var emptyTargetX = puzzleOffsetX + emptyTile.gridX * (tileSize + tileSpacing); var emptyTargetY = puzzleOffsetY + emptyTile.gridY * (tileSize + tileSpacing); if (animate !== false) { tile.moveTo(tileTargetX, tileTargetY, 120); emptyTile.moveTo(emptyTargetX, emptyTargetY, 120); } else { tile.x = tileTargetX; tile.y = tileTargetY; emptyTile.x = emptyTargetX; emptyTile.y = emptyTargetY; } return true; } return false; } // --- Input Handling --- // Find which tile was pressed function getTileAtPos(x, y) { for (var i = 0; i < tileList.length; i++) { var tile = tileList[i]; if (tile.isEmpty) continue; var tx = tile.x, ty = tile.y; var tw = tile.width, th = tile.height; if (x >= tx && x <= tx + tw && y >= ty && y <= ty + th) { return tile; } } return null; } // Handle tap/click on the puzzle game.down = function (x, y, obj) { if (isSolved) return; var tile = getTileAtPos(x, y); if (!tile) return; var moved = swapWithEmpty(tile, true); if (moved) { moveCount++; updateUI(); if (checkSolved()) { isSolved = true; updateUI(); LK.effects.flashScreen(0x44ff44, 800); // Instead of showing YouWin screen, show the New Round button if (typeof newRoundBtn !== 'undefined' && newRoundBtn) { newRoundBtn.visible = true; } // LK.setTimeout(function () { // Original YouWin call removed // LK.showYouWin(); // }, 900); } } }; // --- Game Update --- game.update = function () { // No per-frame logic needed for MVP }; // --- Tutorial Overlay --- var tutorialOverlay = null; var tutorialStep = 0; var tutorialActive = false; // Show tutorial overlay for the first level function showTutorial() { tutorialActive = true; tutorialStep = 0; if (tutorialOverlay) { tutorialOverlay.destroy(); tutorialOverlay = null; } tutorialOverlay = new Container(); var bg = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 20, x: 2048 / 2, y: 2732 / 2 }); bg.alpha = 0.7; tutorialOverlay.addChild(bg); var tutText = new Text2("Welcome to Puzzle It!\n\nWatch how to move the tiles...", { size: 100, fill: 0xffffff }); tutText.anchor.set(0.5, 0.5); tutText.x = 2048 / 2; tutText.y = 2732 / 2 - 200; tutorialOverlay.addChild(tutText); var tutBtn = new Text2("Got it!", { size: 80, fill: 0x4CAF50 }); tutBtn.anchor.set(0.5, 0.5); tutBtn.x = 2048 / 2; tutBtn.y = 2732 / 2 + 300; tutBtn.interactive = true; tutBtn.buttonMode = true; tutBtn.visible = false; // Hide button initially tutorialOverlay.addChild(tutBtn); // Add the tutorial overlay to the game directly instead of LK.gui.center game.addChild(tutorialOverlay); // Set up the button's click handler after it's added to the display tree tutBtn.down = function (x, y, obj) { hideTutorial(); }; // Start the step-by-step tutorial startTutorialSteps(tutText, tutBtn); } // Start step-by-step tutorial movements function startTutorialSteps(tutText, tutBtn) { var stepDelay = 1500; // 1.5 seconds between steps var moveDelay = 800; // 0.8 second to show movement var currentStep = 0; function findMoveableTile() { // Find a tile that can be moved (adjacent to empty space) var moves = [[0, 1], [1, 0], [0, -1], [-1, 0]]; for (var d = 0; d < moves.length; d++) { var nx = emptyTile.gridX + moves[d][0]; var ny = emptyTile.gridY + moves[d][1]; if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize) { var tile = tiles[ny][nx]; if (!tile.isEmpty) { return tile; } } } return null; } function performNextStep() { // Check if puzzle is solved if (checkSolved()) { // Tutorial complete - puzzle is solved tutText.setText("Perfect! You've solved the puzzle!\n\nThis is how you play Puzzle It.\n\nNow try on your own!"); tutBtn.visible = true; return; } var stepNum = currentStep + 1; tutText.setText("Step " + stepNum + ": Watch this tile move..."); // Wait a moment, then perform the move LK.setTimeout(function () { var tile = findMoveableTile(); if (tile && swapWithEmpty(tile, true)) { // Move was successful, wait for animation then continue LK.setTimeout(function () { currentStep++; performNextStep(); }, moveDelay); } else { // Move failed, skip to next step currentStep++; performNextStep(); } }, stepDelay); } // Start the tutorial steps performNextStep(); } // Hide tutorial overlay function hideTutorial() { tutorialActive = false; if (tutorialOverlay) { game.removeChild(tutorialOverlay); tutorialOverlay.destroy(); tutorialOverlay = null; } } // --- Start Game --- createPuzzle(); ; // Show tutorial only for the first level (first time game is loaded) showTutorial(); // Block input while tutorial is active var origGameDown = game.down; game.down = function (x, y, obj) { if (tutorialActive) return; origGameDown(x, y, obj); };
===================================================================
--- original.js
+++ change.js
@@ -444,11 +444,10 @@
startTutorialSteps(tutText, tutBtn);
}
// Start step-by-step tutorial movements
function startTutorialSteps(tutText, tutBtn) {
- var stepDelay = 2000; // 2 seconds between steps
- var moveDelay = 1000; // 1 second to show movement
- var maxSteps = 3;
+ var stepDelay = 1500; // 1.5 seconds between steps
+ var moveDelay = 800; // 0.8 second to show movement
var currentStep = 0;
function findMoveableTile() {
// Find a tile that can be moved (adjacent to empty space)
var moves = [[0, 1], [1, 0], [0, -1], [-1, 0]];
@@ -464,11 +463,12 @@
}
return null;
}
function performNextStep() {
- if (currentStep >= maxSteps) {
- // Tutorial complete
- tutText.setText("Great! Now you try.\n\nTap a tile next to the empty space to move it.\n\nPut the numbers in order to win.");
+ // Check if puzzle is solved
+ if (checkSolved()) {
+ // Tutorial complete - puzzle is solved
+ tutText.setText("Perfect! You've solved the puzzle!\n\nThis is how you play Puzzle It.\n\nNow try on your own!");
tutBtn.visible = true;
return;
}
var stepNum = currentStep + 1;