User prompt
adapt this game to mobile
User prompt
gradually offer 3-4-5 options as the levels progress
User prompt
if it goes to the wrong option, start from level 1
User prompt
if we move the shapes to different shapes, let the section reset, I don't want the fake shape thing
User prompt
add one fake option to each section, so that the sections are reset if the shape leads to it
User prompt
add Octagon
User prompt
round,triangular.add pentagonal, hexagonal, sevenfold and Octagonal shapes as well
User prompt
let the background be black
User prompt
let the shapes be in different places in each section
User prompt
add 5 more different shapes
User prompt
let there be 200 levels, let there be different combinations in each level
User prompt
Please fix the bug: 'TypeError: Cannot use 'in' operator to search for 'scaleX' in null' in or related to this line: 'tween(dragNode, {' Line Number: 304
Code edit (1 edits merged)
Please save this source code
User prompt
Color Match Puzzle
Initial prompt
a very simple puzzle game for children
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Draggable Shape
var DraggableShape = Container.expand(function () {
var self = Container.call(this);
self.shapeType = null; // 'redSquare', etc
self.matchOutline = null; // Reference to the matching outline
self.isMatched = false;
self.asset = null; // The shape asset
self.init = function (shapeType) {
self.shapeType = shapeType;
self.isMatched = false;
// Remove previous asset if any
if (self.asset) self.removeChild(self.asset);
// Attach asset
self.asset = self.attachAsset(shapeType, {
anchorX: 0.5,
anchorY: 0.5
});
// Apply mask if needed
if (shapeType === 'greenTriangle') {
applyTriangleMask(self.asset, 320);
}
if (shapeType === 'yellowStar') {
applyStarMask(self.asset, 320);
}
};
// Animate to position
self.moveTo = function (x, y, duration, onFinish) {
tween(self, {
x: x,
y: y
}, {
duration: duration || 400,
easing: tween.easeInOut,
onFinish: onFinish
});
};
return self;
});
// Outline Target
var OutlineTarget = Container.expand(function () {
var self = Container.call(this);
self.shapeType = null; // 'redSquareOutline', etc
self.asset = null;
self.init = function (shapeType) {
self.shapeType = shapeType;
if (self.asset) self.removeChild(self.asset);
self.asset = self.attachAsset(shapeType, {
anchorX: 0.5,
anchorY: 0.5
});
// Make outline semi-transparent
self.asset.alpha = 0.35;
// Apply mask if needed
if (shapeType === 'greenTriangleOutline') {
applyTriangleMask(self.asset, 340);
}
if (shapeType === 'yellowStarOutline') {
applyStarMask(self.asset, 340);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
// Helper: Triangle Mask
// Sound for correct match
// Outlines (use transparent fill, colored border)
// We'll mask this to star
// We'll mask this to triangle
// Shapes: Red Square, Blue Circle, Green Triangle, Yellow Star
// --- Level Data ---
function applyTriangleMask(container, size) {
// Create a triangle mask using a box and set its visible area
// Since we can't draw, we use scale/skew to fake a triangle
// We'll just scaleY to 0.5 and rotate
container.rotation = Math.PI / 4;
container.scaleY = 0.58;
}
// Helper: Star Mask
function applyStarMask(container, size) {
// We can't draw a star, so we just use a box for now
// In future, swap to a star asset if available
}
var levels = [
// Level 1: 2 shapes
[{
shape: 'redSquare',
outline: 'redSquareOutline'
}, {
shape: 'blueCircle',
outline: 'blueCircleOutline'
}],
// Level 2: 3 shapes
[{
shape: 'redSquare',
outline: 'redSquareOutline'
}, {
shape: 'blueCircle',
outline: 'blueCircleOutline'
}, {
shape: 'greenTriangle',
outline: 'greenTriangleOutline'
}],
// Level 3: 4 shapes
[{
shape: 'redSquare',
outline: 'redSquareOutline'
}, {
shape: 'blueCircle',
outline: 'blueCircleOutline'
}, {
shape: 'greenTriangle',
outline: 'greenTriangleOutline'
}, {
shape: 'yellowStar',
outline: 'yellowStarOutline'
}]];
var currentLevel = 0;
var draggableShapes = [];
var outlineTargets = [];
var dragNode = null;
var dragOffsetX = 0;
var dragOffsetY = 0;
var matchedCount = 0;
// --- GUI: Level Text ---
var levelTxt = new Text2('Level 1', {
size: 120,
fill: 0x333333
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
// --- Helper: Layout ---
function layoutLevel(shapes) {
// Remove previous
for (var i = 0; i < draggableShapes.length; ++i) draggableShapes[i].destroy();
for (var i = 0; i < outlineTargets.length; ++i) outlineTargets[i].destroy();
draggableShapes = [];
outlineTargets = [];
matchedCount = 0;
// Layout outlines in a row near the top
var n = shapes.length;
var spacing = 420;
var startX = 2048 / 2 - (n - 1) * spacing / 2;
var outlineY = 700;
for (var i = 0; i < n; ++i) {
var outline = new OutlineTarget();
outline.init(shapes[i].outline);
outline.x = startX + i * spacing;
outline.y = outlineY;
game.addChild(outline);
outlineTargets.push(outline);
}
// Layout shapes in a row near the bottom, shuffled
var shapeOrder = [];
for (var i = 0; i < n; ++i) shapeOrder.push(i);
// Shuffle
for (var i = n - 1; i > 0; --i) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = shapeOrder[i];
shapeOrder[i] = shapeOrder[j];
shapeOrder[j] = tmp;
}
var shapeY = 2000;
for (var i = 0; i < n; ++i) {
var idx = shapeOrder[i];
var shape = new DraggableShape();
shape.init(shapes[idx].shape);
shape.x = startX + i * spacing;
shape.y = shapeY;
shape.matchOutline = outlineTargets[idx];
game.addChild(shape);
draggableShapes.push(shape);
}
}
// --- Helper: Start Level ---
function startLevel(levelIdx) {
currentLevel = levelIdx;
levelTxt.setText('Level ' + (currentLevel + 1));
layoutLevel(levels[currentLevel]);
}
// --- Helper: Next Level or Win ---
function nextLevelOrWin() {
if (currentLevel + 1 < levels.length) {
LK.setTimeout(function () {
startLevel(currentLevel + 1);
}, 900);
} else {
LK.setTimeout(function () {
LK.showYouWin();
}, 900);
}
}
// --- Dragging Logic ---
function getShapeAt(x, y) {
for (var i = 0; i < draggableShapes.length; ++i) {
var s = draggableShapes[i];
if (s.isMatched) continue;
var dx = x - s.x;
var dy = y - s.y;
var r = 160;
if (dx * dx + dy * dy < r * r) return s;
}
return null;
}
// --- Event Handlers ---
game.down = function (x, y, obj) {
// Only allow one drag at a time
if (dragNode) return;
var shape = getShapeAt(x, y);
if (shape && !shape.isMatched) {
dragNode = shape;
dragOffsetX = x - shape.x;
dragOffsetY = y - shape.y;
// Bring to front
game.removeChild(shape);
game.addChild(shape);
}
};
game.move = function (x, y, obj) {
if (dragNode && !dragNode.isMatched) {
dragNode.x = x - dragOffsetX;
dragNode.y = y - dragOffsetY;
}
};
game.up = function (x, y, obj) {
if (!dragNode) return;
if (dragNode.isMatched) {
dragNode = null;
return;
}
// Check if close to its outline
var outline = dragNode.matchOutline;
var dx = dragNode.x - outline.x;
var dy = dragNode.y - outline.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 100) {
// Snap to outline, mark as matched
dragNode.isMatched = true;
dragNode.moveTo(outline.x, outline.y, 200, function () {
// Animate outline to full alpha
tween(outline.asset, {
alpha: 0.7
}, {
duration: 200
});
});
LK.getSound('match').play();
matchedCount++;
// Animate shape scale
if (dragNode) {
tween(dragNode, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 120,
onFinish: function onFinish() {
if (dragNode) {
tween(dragNode, {
scaleX: 1,
scaleY: 1
}, {
duration: 120
});
}
}
});
}
// All matched?
if (matchedCount === draggableShapes.length) {
// Animate all shapes up
for (var i = 0; i < draggableShapes.length; ++i) {
tween(draggableShapes[i], {
y: draggableShapes[i].y - 120
}, {
duration: 200
});
}
nextLevelOrWin();
}
} else {
// Animate back to start
var n = draggableShapes.length;
var spacing = 420;
var startX = 2048 / 2 - (n - 1) * spacing / 2;
var shapeY = 2000;
var idx = draggableShapes.indexOf(dragNode);
dragNode.moveTo(startX + idx * spacing, shapeY, 200);
}
dragNode = null;
};
// --- Start Game ---
startLevel(0); ===================================================================
--- original.js
+++ change.js
@@ -263,22 +263,26 @@
});
LK.getSound('match').play();
matchedCount++;
// Animate shape scale
- tween(dragNode, {
- scaleX: 1.15,
- scaleY: 1.15
- }, {
- duration: 120,
- onFinish: function onFinish() {
- tween(dragNode, {
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 120
- });
- }
- });
+ if (dragNode) {
+ tween(dragNode, {
+ scaleX: 1.15,
+ scaleY: 1.15
+ }, {
+ duration: 120,
+ onFinish: function onFinish() {
+ if (dragNode) {
+ tween(dragNode, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 120
+ });
+ }
+ }
+ });
+ }
// All matched?
if (matchedCount === draggableShapes.length) {
// Animate all shapes up
for (var i = 0; i < draggableShapes.length; ++i) {