User prompt
change level 6
Code edit (11 edits merged)
Please save this source code
User prompt
add 5 more level
User prompt
draw the grid
Code edit (1 edits merged)
Please save this source code
User prompt
when we load level 2 game is crash
Code edit (1 edits merged)
Please save this source code
User prompt
increase save before showing you win ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'storage.getItem is not a function' in or related to this line: 'var saved = storage.getItem('slidecubes_save');' Line Number: 480 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
add storage to last played level ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'storage.load is not a function' in or related to this line: 'var saved = storage.load('slidecubes_save');' Line Number: 476
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var saved = storage.get('slidecubes_save');' Line Number: 476
User prompt
Please fix the bug: 'storage.load is not a function' in or related to this line: 'var saved = storage.load('slidecubes_save');' Line Number: 476
User prompt
if there is no save start with level 1
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var saved = storage.get('slidecubes_save');' Line Number: 476
User prompt
Please fix the bug: 'storage.getItem is not a function' in or related to this line: 'var saved = storage.getItem('slidecubes_save');' Line Number: 476
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var saved = storage.get('slidecubes_save');' Line Number: 476
User prompt
check for save when load the game
User prompt
each level show you win after playagain load another level
Code edit (2 edits merged)
Please save this source code
User prompt
in level 2 cant click objects
Code edit (3 edits merged)
Please save this source code
User prompt
before create another level destroy all old one data and objects
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'arrow')' in or related to this line: 'self.arrowGfx = self.attachAsset(dir.arrow, {' Line Number: 42
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Cube class var Cube = Container.expand(function () { var self = Container.call(this); // Cube base var cubeGfx = self.attachAsset('cube', { anchorX: 0.5, anchorY: 0.5 }); // Arrow overlay self.arrowGfx = null; // Grid position self.gridX = 0; self.gridY = 0; // Direction index (0:up, 1:down, 2:left, 3:right) self.dir = 0; // Is this cube currently animating? self.isSliding = false; // Set direction and update arrow self.setDirection = function (dirIdx) { self.dir = dirIdx; if (self.arrowGfx) { self.removeChild(self.arrowGfx); } // Defensive: Only set arrow if dirIdx is valid if (dirIdx >= 0 && dirIdx < DIRS.length) { var dir = DIRS[dirIdx]; self.arrowGfx = self.attachAsset(dir.arrow, { anchorX: 0.5, anchorY: 0.5 }); // For left/right, rotate arrow to point correctly if (dir.name === 'left') { self.arrowGfx.rotation = Math.PI; } else if (dir.name === 'up') { self.arrowGfx.rotation = -Math.PI / 2; } else if (dir.name === 'down') { self.arrowGfx.rotation = Math.PI / 2; } else { self.arrowGfx.rotation = 0; } } else { // Fallback: show no arrow if direction is invalid self.arrowGfx = null; } }; // Called when tapped self.down = function (x, y, obj) { if (self.isSliding) { return; } if (game.isAnimating) { return; } game.trySlideCube(self); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222831 }); /**** * Game Code ****/ // Cube directions // Tween for sliding animation // Arrow assets: 120x60, colored arrows for each direction // Cube asset: 200x200, white box // Grid config var DIRS = [{ name: 'up', dx: 0, dy: -1, arrow: 'arrow_up', rot: 0 }, { name: 'down', dx: 0, dy: 1, arrow: 'arrow_down', rot: 0 }, { name: 'left', dx: -1, dy: 0, arrow: 'arrow_left', rot: 0 }, { name: 'right', dx: 1, dy: 0, arrow: 'arrow_right', rot: 0 }]; var GRID_SIZE = 4; var CELL_SIZE = 260; // 200px cube + 60px gap var GRID_ORIGIN_X = Math.floor((2048 - GRID_SIZE * CELL_SIZE) / 2) + CELL_SIZE / 2; var GRID_ORIGIN_Y = Math.floor((2732 - GRID_SIZE * CELL_SIZE) / 2) + CELL_SIZE / 2; // Game state var cubes = []; // 2D array [y][x] of Cube or null var cubeList = []; // Flat list of all Cube objects var isAnimating = false; // Score text var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Helper: get grid cell center position function gridToPos(gx, gy) { return { x: GRID_ORIGIN_X + gx * CELL_SIZE, y: GRID_ORIGIN_Y + gy * CELL_SIZE }; } // Helper: check if (gx,gy) is inside grid function inGrid(gx, gy) { return gx >= 0 && gx < GRID_SIZE && gy >= 0 && gy < GRID_SIZE; } // Helper: update score display function updateScore() { var left = 0; for (var y = 0; y < GRID_SIZE; ++y) { for (var x = 0; x < GRID_SIZE; ++x) { if (cubes[y][x]) { left++; } } } scoreTxt.setText(left + ""); } // Try to slide a cube in its direction game.trySlideCube = function (cube) { // Only allow one animation at a time if (game.isAnimating) { return; } if (cube.isSliding) { return; } var dir = DIRS[cube.dir]; var gx = cube.gridX; var gy = cube.gridY; var dx = dir.dx; var dy = dir.dy; // Find farthest empty cell in direction var nx = gx; var ny = gy; while (true) { var tx = nx + dx; var ty = ny + dy; if (!inGrid(tx, ty)) { // Out of grid, can slide out break; } if (cubes[ty][tx]) { // Blocked by another cube // Can't move return; } nx = tx; ny = ty; } // If not moving, do nothing if (nx === gx && ny === gy) { return; } // Mark animating cube.isSliding = true; game.isAnimating = true; // Remove from grid cubes[gy][gx] = null; // Animate to out-of-grid position var endPos; if (inGrid(nx, ny)) { // Should not happen, but fallback endPos = gridToPos(nx, ny); } else { // Compute position just outside grid var outX = nx; var outY = ny; // If moving right, outX is GRID_SIZE, left: -1 // If moving down, outY is GRID_SIZE, up: -1 endPos = { x: GRID_ORIGIN_X + nx * CELL_SIZE, y: GRID_ORIGIN_Y + ny * CELL_SIZE }; } // Animate slide tween(cube, { x: endPos.x, y: endPos.y }, { duration: 300, onFinish: function onFinish() { // Remove cube from scene and list cube.destroy(); var idx = cubeList.indexOf(cube); if (idx !== -1) { cubeList.splice(idx, 1); } cube.isSliding = false; game.isAnimating = false; updateScore(); // Check win var left = 0; for (var y = 0; y < GRID_SIZE; ++y) { for (var x = 0; x < GRID_SIZE; ++x) { if (cubes[y][x]) { left++; } } } if (left === 0) { if (currentLevel < LEVELS.length - 1) { buildLevel(currentLevel + 1); } else { LK.showYouWin(); } } } }); }; // --- Level definitions --- var LEVELS = [ // Level 1: Simple, 3 cubes [{ x: 0, y: 0, dir: 3 }, // right { x: 1, y: 1, dir: 1 }, // down { x: 2, y: 2, dir: 0 } // up ], // Level 2: 4 cubes, corners (fixed directions to make passable) [{ x: 0, y: 0, dir: 4 }, // right { x: 3, y: 0, dir: 1 }, // down { x: 3, y: 3, dir: 2 }, // left { x: 0, y: 3, dir: 1 } // down (changed from up to down) ], // Level 3: 5 cubes, cross [{ x: 1, y: 0, dir: 1 }, // down { x: 2, y: 1, dir: 2 }, // left { x: 1, y: 2, dir: 3 }, // right { x: 2, y: 3, dir: 0 }, // up { x: 1, y: 1, dir: 1 } // down ], // Level 4: 6 cubes, more complex [{ x: 0, y: 1, dir: 3 }, // right { x: 1, y: 0, dir: 1 }, // down { x: 2, y: 1, dir: 2 }, // left { x: 3, y: 2, dir: 0 }, // up { x: 2, y: 3, dir: 2 }, // left { x: 1, y: 2, dir: 3 } // right ], // Level 5: 7 cubes, challenge [{ x: 0, y: 0, dir: 3 }, // right { x: 1, y: 0, dir: 1 }, // down { x: 2, y: 0, dir: 1 }, // down { x: 3, y: 1, dir: 2 }, // left { x: 3, y: 2, dir: 0 }, // up { x: 2, y: 3, dir: 2 }, // left { x: 0, y: 2, dir: 0 } // up ]]; var currentLevel = 0; // Level indicator text var levelTxt = new Text2('Level 1', { size: 90, fill: 0xFFD700 }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); // Build a level by index function buildLevel(idx) { // Clamp level index if (idx < 0) { idx = 0; } if (idx >= LEVELS.length) { idx = LEVELS.length - 1; } currentLevel = idx; // Reset animation state game.isAnimating = false; // Clear previous for (var i = 0; i < cubeList.length; ++i) { cubeList[i].isSliding = false; // Reset sliding state in case any cube is still flagged cubeList[i].destroy(); } cubeList = []; cubes = []; for (var y = 0; y < GRID_SIZE; ++y) { var row = []; for (var x = 0; x < GRID_SIZE; ++x) { row.push(null); } cubes.push(row); } // Place cubes for this level var levelCubes = LEVELS[idx]; for (var i = 0; i < levelCubes.length; ++i) { var c = levelCubes[i]; var cube = new Cube(); cube.gridX = c.x; cube.gridY = c.y; cube.setDirection(c.dir); var pos = gridToPos(c.x, c.y); cube.x = pos.x; cube.y = pos.y; cubes[c.y][c.x] = cube; cubeList.push(cube); game.addChild(cube); } updateScore(); levelTxt.setText("Level " + (currentLevel + 1)); game.isAnimating = false; } // Prevent accidental drag game.move = function (x, y, obj) {}; // No drag game.down = function (x, y, obj) {}; game.up = function (x, y, obj) {}; // No per-tick logic needed game.update = function () {}; // Start game at level 1 buildLevel(0);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Cube class
var Cube = Container.expand(function () {
var self = Container.call(this);
// Cube base
var cubeGfx = self.attachAsset('cube', {
anchorX: 0.5,
anchorY: 0.5
});
// Arrow overlay
self.arrowGfx = null;
// Grid position
self.gridX = 0;
self.gridY = 0;
// Direction index (0:up, 1:down, 2:left, 3:right)
self.dir = 0;
// Is this cube currently animating?
self.isSliding = false;
// Set direction and update arrow
self.setDirection = function (dirIdx) {
self.dir = dirIdx;
if (self.arrowGfx) {
self.removeChild(self.arrowGfx);
}
// Defensive: Only set arrow if dirIdx is valid
if (dirIdx >= 0 && dirIdx < DIRS.length) {
var dir = DIRS[dirIdx];
self.arrowGfx = self.attachAsset(dir.arrow, {
anchorX: 0.5,
anchorY: 0.5
});
// For left/right, rotate arrow to point correctly
if (dir.name === 'left') {
self.arrowGfx.rotation = Math.PI;
} else if (dir.name === 'up') {
self.arrowGfx.rotation = -Math.PI / 2;
} else if (dir.name === 'down') {
self.arrowGfx.rotation = Math.PI / 2;
} else {
self.arrowGfx.rotation = 0;
}
} else {
// Fallback: show no arrow if direction is invalid
self.arrowGfx = null;
}
};
// Called when tapped
self.down = function (x, y, obj) {
if (self.isSliding) {
return;
}
if (game.isAnimating) {
return;
}
game.trySlideCube(self);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222831
});
/****
* Game Code
****/
// Cube directions
// Tween for sliding animation
// Arrow assets: 120x60, colored arrows for each direction
// Cube asset: 200x200, white box
// Grid config
var DIRS = [{
name: 'up',
dx: 0,
dy: -1,
arrow: 'arrow_up',
rot: 0
}, {
name: 'down',
dx: 0,
dy: 1,
arrow: 'arrow_down',
rot: 0
}, {
name: 'left',
dx: -1,
dy: 0,
arrow: 'arrow_left',
rot: 0
}, {
name: 'right',
dx: 1,
dy: 0,
arrow: 'arrow_right',
rot: 0
}];
var GRID_SIZE = 4;
var CELL_SIZE = 260; // 200px cube + 60px gap
var GRID_ORIGIN_X = Math.floor((2048 - GRID_SIZE * CELL_SIZE) / 2) + CELL_SIZE / 2;
var GRID_ORIGIN_Y = Math.floor((2732 - GRID_SIZE * CELL_SIZE) / 2) + CELL_SIZE / 2;
// Game state
var cubes = []; // 2D array [y][x] of Cube or null
var cubeList = []; // Flat list of all Cube objects
var isAnimating = false;
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: get grid cell center position
function gridToPos(gx, gy) {
return {
x: GRID_ORIGIN_X + gx * CELL_SIZE,
y: GRID_ORIGIN_Y + gy * CELL_SIZE
};
}
// Helper: check if (gx,gy) is inside grid
function inGrid(gx, gy) {
return gx >= 0 && gx < GRID_SIZE && gy >= 0 && gy < GRID_SIZE;
}
// Helper: update score display
function updateScore() {
var left = 0;
for (var y = 0; y < GRID_SIZE; ++y) {
for (var x = 0; x < GRID_SIZE; ++x) {
if (cubes[y][x]) {
left++;
}
}
}
scoreTxt.setText(left + "");
}
// Try to slide a cube in its direction
game.trySlideCube = function (cube) {
// Only allow one animation at a time
if (game.isAnimating) {
return;
}
if (cube.isSliding) {
return;
}
var dir = DIRS[cube.dir];
var gx = cube.gridX;
var gy = cube.gridY;
var dx = dir.dx;
var dy = dir.dy;
// Find farthest empty cell in direction
var nx = gx;
var ny = gy;
while (true) {
var tx = nx + dx;
var ty = ny + dy;
if (!inGrid(tx, ty)) {
// Out of grid, can slide out
break;
}
if (cubes[ty][tx]) {
// Blocked by another cube
// Can't move
return;
}
nx = tx;
ny = ty;
}
// If not moving, do nothing
if (nx === gx && ny === gy) {
return;
}
// Mark animating
cube.isSliding = true;
game.isAnimating = true;
// Remove from grid
cubes[gy][gx] = null;
// Animate to out-of-grid position
var endPos;
if (inGrid(nx, ny)) {
// Should not happen, but fallback
endPos = gridToPos(nx, ny);
} else {
// Compute position just outside grid
var outX = nx;
var outY = ny;
// If moving right, outX is GRID_SIZE, left: -1
// If moving down, outY is GRID_SIZE, up: -1
endPos = {
x: GRID_ORIGIN_X + nx * CELL_SIZE,
y: GRID_ORIGIN_Y + ny * CELL_SIZE
};
}
// Animate slide
tween(cube, {
x: endPos.x,
y: endPos.y
}, {
duration: 300,
onFinish: function onFinish() {
// Remove cube from scene and list
cube.destroy();
var idx = cubeList.indexOf(cube);
if (idx !== -1) {
cubeList.splice(idx, 1);
}
cube.isSliding = false;
game.isAnimating = false;
updateScore();
// Check win
var left = 0;
for (var y = 0; y < GRID_SIZE; ++y) {
for (var x = 0; x < GRID_SIZE; ++x) {
if (cubes[y][x]) {
left++;
}
}
}
if (left === 0) {
if (currentLevel < LEVELS.length - 1) {
buildLevel(currentLevel + 1);
} else {
LK.showYouWin();
}
}
}
});
};
// --- Level definitions ---
var LEVELS = [
// Level 1: Simple, 3 cubes
[{
x: 0,
y: 0,
dir: 3
},
// right
{
x: 1,
y: 1,
dir: 1
},
// down
{
x: 2,
y: 2,
dir: 0
} // up
],
// Level 2: 4 cubes, corners (fixed directions to make passable)
[{
x: 0,
y: 0,
dir: 4
},
// right
{
x: 3,
y: 0,
dir: 1
},
// down
{
x: 3,
y: 3,
dir: 2
},
// left
{
x: 0,
y: 3,
dir: 1
} // down (changed from up to down)
],
// Level 3: 5 cubes, cross
[{
x: 1,
y: 0,
dir: 1
},
// down
{
x: 2,
y: 1,
dir: 2
},
// left
{
x: 1,
y: 2,
dir: 3
},
// right
{
x: 2,
y: 3,
dir: 0
},
// up
{
x: 1,
y: 1,
dir: 1
} // down
],
// Level 4: 6 cubes, more complex
[{
x: 0,
y: 1,
dir: 3
},
// right
{
x: 1,
y: 0,
dir: 1
},
// down
{
x: 2,
y: 1,
dir: 2
},
// left
{
x: 3,
y: 2,
dir: 0
},
// up
{
x: 2,
y: 3,
dir: 2
},
// left
{
x: 1,
y: 2,
dir: 3
} // right
],
// Level 5: 7 cubes, challenge
[{
x: 0,
y: 0,
dir: 3
},
// right
{
x: 1,
y: 0,
dir: 1
},
// down
{
x: 2,
y: 0,
dir: 1
},
// down
{
x: 3,
y: 1,
dir: 2
},
// left
{
x: 3,
y: 2,
dir: 0
},
// up
{
x: 2,
y: 3,
dir: 2
},
// left
{
x: 0,
y: 2,
dir: 0
} // up
]];
var currentLevel = 0;
// Level indicator text
var levelTxt = new Text2('Level 1', {
size: 90,
fill: 0xFFD700
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
// Build a level by index
function buildLevel(idx) {
// Clamp level index
if (idx < 0) {
idx = 0;
}
if (idx >= LEVELS.length) {
idx = LEVELS.length - 1;
}
currentLevel = idx;
// Reset animation state
game.isAnimating = false;
// Clear previous
for (var i = 0; i < cubeList.length; ++i) {
cubeList[i].isSliding = false; // Reset sliding state in case any cube is still flagged
cubeList[i].destroy();
}
cubeList = [];
cubes = [];
for (var y = 0; y < GRID_SIZE; ++y) {
var row = [];
for (var x = 0; x < GRID_SIZE; ++x) {
row.push(null);
}
cubes.push(row);
}
// Place cubes for this level
var levelCubes = LEVELS[idx];
for (var i = 0; i < levelCubes.length; ++i) {
var c = levelCubes[i];
var cube = new Cube();
cube.gridX = c.x;
cube.gridY = c.y;
cube.setDirection(c.dir);
var pos = gridToPos(c.x, c.y);
cube.x = pos.x;
cube.y = pos.y;
cubes[c.y][c.x] = cube;
cubeList.push(cube);
game.addChild(cube);
}
updateScore();
levelTxt.setText("Level " + (currentLevel + 1));
game.isAnimating = false;
}
// Prevent accidental drag
game.move = function (x, y, obj) {};
// No drag
game.down = function (x, y, obj) {};
game.up = function (x, y, obj) {};
// No per-tick logic needed
game.update = function () {};
// Start game at level 1
buildLevel(0);