User prompt
in frist level dont add all the colours and as the level up add one more colour make 7 levels and dont reapeat the colours
User prompt
add 50 levels in it in frist level have 3 clours then add 3 more colours in father level add one more colours as the level is up .inc speed by 4 make road map of level which unlocks when you play previous one and if gamer win the level there is a popup appear then next level start
User prompt
add black blue and purple colours and more colours in anothor levels
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'expand')' in or related to this line: 'var Gem = Container.expand(function (type, speed) {' Line Number: 30
Code edit (1 edits merged)
Please save this source code
User prompt
Gem Sorter: Color Match Mania
User prompt
Please continue polishing my design document.
Initial prompt
Sort different colored gems into the right slots.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var CustomContainer = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'red'; var baseContainer = self.attachAsset('container', { anchorX: 0.5, anchorY: 0.5 }); var colorIndicator = self.attachAsset('container_' + self.type, { anchorX: 0.5, anchorY: 0.5, y: -15, scaleX: 0.8, scaleY: 0.5 }); return self; }); var Gem = Container.expand(function (type, speed) { var self = Container.call(this); self.type = type || 'red'; self.speed = speed || 3; self.matched = false; self.isSpecial = false; var assetId = 'gem_' + self.type; var gemGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (!self.matched) { self.y += self.speed; } }; self.down = function (x, y, obj) { // This gem is being dragged if (!self.matched) { currentDraggedGem = self; } }; self.makeSpecial = function () { self.isSpecial = true; tween(gemGraphics, { alpha: 0.5 }, { duration: 500, easing: tween.easeInOut }); tween.stop(gemGraphics, { alpha: true }); tween(gemGraphics, { alpha: 1 }, { duration: 500, easing: tween.easeInOut }); var specialGfx = self.attachAsset('special_gem', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x333333 }); /**** * Game Code ****/ // Game configuration var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var CONTAINER_Y = GAME_HEIGHT - 100; var MAX_LIVES = 3; var SPECIAL_GEM_CHANCE = 0.1; // Game state variables var score = 0; var lives = MAX_LIVES; var level = 1; var maxLevels = 50; var gameActive = true; var gems = []; var containers = []; var currentDraggedGem = null; var gemSpawnInterval = 2000; // milliseconds var gemSpeed = 3; var availableColors = ['red', 'blue', 'green']; // Start with 3 colors // UI elements var scoreTxt = new Text2('Score: 0', { size: 70, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.y = 100; var levelTxt = new Text2('Level: 1', { size: 70, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); LK.gui.topRight.addChild(levelTxt); levelTxt.x = -250; levelTxt.y = 100; var livesContainer = new Container(); livesContainer.x = 200; livesContainer.y = 120; LK.gui.topLeft.addChild(livesContainer); // Initialize lives display function updateLivesDisplay() { // Clear existing lives while (livesContainer.children.length > 0) { livesContainer.removeChildAt(0); } // Add life icons for (var i = 0; i < lives; i++) { var lifeIcon = LK.getAsset('life', { anchorX: 0.5, anchorY: 0.5, x: i * 60, y: 0 }); livesContainer.addChild(lifeIcon); } } // Create color containers at the bottom function createContainers() { // Clear existing containers for (var i = 0; i < containers.length; i++) { if (containers[i] && containers[i].parent) { containers[i].parent.removeChild(containers[i]); } } containers = []; // Calculate spacing and create new containers var containerWidth = 150; var totalWidth = containerWidth * availableColors.length; var startX = (GAME_WIDTH - totalWidth) / 2 + containerWidth / 2; var spacing = containerWidth * 1.5; for (var i = 0; i < availableColors.length; i++) { var container = new CustomContainer(availableColors[i]); container.x = startX + i * spacing; container.y = CONTAINER_Y; game.addChild(container); containers.push(container); } } // Spawn a new gem function spawnGem() { if (!gameActive) { return; } var randomColorIndex = Math.floor(Math.random() * availableColors.length); var gemType = availableColors[randomColorIndex]; var gem = new Gem(gemType, gemSpeed); // Random X position within boundaries var padding = 120; // Gem width gem.x = padding + Math.random() * (GAME_WIDTH - padding * 2); gem.y = -100; // Start above screen // Small chance to create a special gem if (Math.random() < SPECIAL_GEM_CHANCE) { gem.makeSpecial(); } game.addChild(gem); gems.push(gem); // Schedule next gem spawn var randomDelay = Math.random() * 500; // Add some randomness LK.setTimeout(spawnGem, gemSpawnInterval + randomDelay); } // Check if a gem is on a container and handle matching function checkGemContainerCollision(gem) { if (gem.matched) { return; } for (var i = 0; i < containers.length; i++) { var container = containers[i]; if (gem.intersects(container)) { if (gem.type === container.type) { // Correct match gem.matched = true; // Score points var points = 10; if (gem.isSpecial) { points = 30; LK.getSound('special').play(); // Special gem effect: slow down all gems temporarily var originalSpeed = gemSpeed; gemSpeed = gemSpeed / 2; LK.setTimeout(function () { gemSpeed = originalSpeed; }, 3000); } else { LK.getSound('match').play(); } // Update score and display score += points; scoreTxt.setText('Score: ' + score); // Animate gem disappearing tween(gem, { alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 300, onFinish: function onFinish() { // Remove from game removeGem(gem); } }); // Flash container LK.effects.flashObject(container, 0xffffff, 500); return true; } else { // Wrong container LK.getSound('wrong').play(); lives--; updateLivesDisplay(); if (lives <= 0) { gameOver(); } // Flash container red LK.effects.flashObject(container, 0xff0000, 500); // Animate gem disappearing tween(gem, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { // Remove from game removeGem(gem); } }); return true; } } } return false; } // Remove a gem from the game function removeGem(gemToRemove) { for (var i = gems.length - 1; i >= 0; i--) { if (gems[i] === gemToRemove) { // Remove from array gems.splice(i, 1); // Remove from display if (gemToRemove.parent) { gemToRemove.parent.removeChild(gemToRemove); } break; } } } // Game over function function gameOver() { gameActive = false; // Check for high score if (score > storage.highScore) { storage.highScore = score; } // Show game over screen LK.showGameOver(); } // Level up function function levelUp() { level++; levelTxt.setText('Level: ' + level); LK.getSound('levelup').play(); // Add new color every 2 levels if (level === 2) { availableColors.push('yellow'); } else if (level === 3) { availableColors.push('purple'); } else if (level === 4) { availableColors.push('black'); } else if (level === 5) { availableColors.push('orange'); } else if (level === 6) { availableColors.push('pink'); } else if (level === 7) { availableColors.push('cyan'); } createContainers(); // Increase difficulty gemSpeed += 0.5; gemSpawnInterval = Math.max(500, gemSpawnInterval - 300); // Flash screen effect LK.effects.flashScreen(0xffffff, 500); // Show level completion popup LK.showPopup({ title: "Level Complete!", message: "Get ready for the next level!", onClose: function onClose() { if (level <= maxLevels) { initGame(); } else { LK.showYouWin(); } } }); } // Initialize the game function initGame() { score = 0; lives = MAX_LIVES; level = 1; maxLevels = 50; gameActive = true; gems = []; gemSpeed = 3; gemSpawnInterval = 2000; availableColors = ['red', 'blue', 'green']; scoreTxt.setText('Score: 0'); levelTxt.setText('Level: 1'); updateLivesDisplay(); createContainers(); // Start spawning gems LK.setTimeout(spawnGem, 1000); // Start music LK.playMusic('bgmusic'); } // Game event handlers game.down = function (x, y, obj) { // Handle checking which gem was clicked for (var i = 0; i < gems.length; i++) { var gem = gems[i]; var localPoint = gem.toLocal({ x: x, y: y }); if (localPoint.x >= -gem.width / 2 && localPoint.x <= gem.width / 2 && localPoint.y >= -gem.height / 2 && localPoint.y <= gem.height / 2) { currentDraggedGem = gem; break; } } }; game.move = function (x, y, obj) { // Update dragged gem position if (currentDraggedGem && !currentDraggedGem.matched) { currentDraggedGem.x = x; currentDraggedGem.y = y; } }; game.up = function (x, y, obj) { // Check if the gem was dropped on a container if (currentDraggedGem && !currentDraggedGem.matched) { checkGemContainerCollision(currentDraggedGem); } currentDraggedGem = null; }; // Main game loop game.update = function () { if (!gameActive) { return; } // Process all gems for (var i = gems.length - 1; i >= 0; i--) { var gem = gems[i]; // Skip gems being dragged if (gem === currentDraggedGem) { continue; } // Check if gem hit bottom if (gem.y > GAME_HEIGHT + 100) { if (!gem.matched) { lives--; updateLivesDisplay(); if (lives <= 0) { gameOver(); return; } } removeGem(gem); continue; } } // Check for level up (based on score) var scoreTrigger = level * 100; if (score >= scoreTrigger && score < scoreTrigger + 10) { levelUp(); } }; // Initialize game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var CustomContainer = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'red';
var baseContainer = self.attachAsset('container', {
anchorX: 0.5,
anchorY: 0.5
});
var colorIndicator = self.attachAsset('container_' + self.type, {
anchorX: 0.5,
anchorY: 0.5,
y: -15,
scaleX: 0.8,
scaleY: 0.5
});
return self;
});
var Gem = Container.expand(function (type, speed) {
var self = Container.call(this);
self.type = type || 'red';
self.speed = speed || 3;
self.matched = false;
self.isSpecial = false;
var assetId = 'gem_' + self.type;
var gemGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!self.matched) {
self.y += self.speed;
}
};
self.down = function (x, y, obj) {
// This gem is being dragged
if (!self.matched) {
currentDraggedGem = self;
}
};
self.makeSpecial = function () {
self.isSpecial = true;
tween(gemGraphics, {
alpha: 0.5
}, {
duration: 500,
easing: tween.easeInOut
});
tween.stop(gemGraphics, {
alpha: true
});
tween(gemGraphics, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
var specialGfx = self.attachAsset('special_gem', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x333333
});
/****
* Game Code
****/
// Game configuration
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var CONTAINER_Y = GAME_HEIGHT - 100;
var MAX_LIVES = 3;
var SPECIAL_GEM_CHANCE = 0.1;
// Game state variables
var score = 0;
var lives = MAX_LIVES;
var level = 1;
var maxLevels = 50;
var gameActive = true;
var gems = [];
var containers = [];
var currentDraggedGem = null;
var gemSpawnInterval = 2000; // milliseconds
var gemSpeed = 3;
var availableColors = ['red', 'blue', 'green']; // Start with 3 colors
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 100;
var levelTxt = new Text2('Level: 1', {
size: 70,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(levelTxt);
levelTxt.x = -250;
levelTxt.y = 100;
var livesContainer = new Container();
livesContainer.x = 200;
livesContainer.y = 120;
LK.gui.topLeft.addChild(livesContainer);
// Initialize lives display
function updateLivesDisplay() {
// Clear existing lives
while (livesContainer.children.length > 0) {
livesContainer.removeChildAt(0);
}
// Add life icons
for (var i = 0; i < lives; i++) {
var lifeIcon = LK.getAsset('life', {
anchorX: 0.5,
anchorY: 0.5,
x: i * 60,
y: 0
});
livesContainer.addChild(lifeIcon);
}
}
// Create color containers at the bottom
function createContainers() {
// Clear existing containers
for (var i = 0; i < containers.length; i++) {
if (containers[i] && containers[i].parent) {
containers[i].parent.removeChild(containers[i]);
}
}
containers = [];
// Calculate spacing and create new containers
var containerWidth = 150;
var totalWidth = containerWidth * availableColors.length;
var startX = (GAME_WIDTH - totalWidth) / 2 + containerWidth / 2;
var spacing = containerWidth * 1.5;
for (var i = 0; i < availableColors.length; i++) {
var container = new CustomContainer(availableColors[i]);
container.x = startX + i * spacing;
container.y = CONTAINER_Y;
game.addChild(container);
containers.push(container);
}
}
// Spawn a new gem
function spawnGem() {
if (!gameActive) {
return;
}
var randomColorIndex = Math.floor(Math.random() * availableColors.length);
var gemType = availableColors[randomColorIndex];
var gem = new Gem(gemType, gemSpeed);
// Random X position within boundaries
var padding = 120; // Gem width
gem.x = padding + Math.random() * (GAME_WIDTH - padding * 2);
gem.y = -100; // Start above screen
// Small chance to create a special gem
if (Math.random() < SPECIAL_GEM_CHANCE) {
gem.makeSpecial();
}
game.addChild(gem);
gems.push(gem);
// Schedule next gem spawn
var randomDelay = Math.random() * 500; // Add some randomness
LK.setTimeout(spawnGem, gemSpawnInterval + randomDelay);
}
// Check if a gem is on a container and handle matching
function checkGemContainerCollision(gem) {
if (gem.matched) {
return;
}
for (var i = 0; i < containers.length; i++) {
var container = containers[i];
if (gem.intersects(container)) {
if (gem.type === container.type) {
// Correct match
gem.matched = true;
// Score points
var points = 10;
if (gem.isSpecial) {
points = 30;
LK.getSound('special').play();
// Special gem effect: slow down all gems temporarily
var originalSpeed = gemSpeed;
gemSpeed = gemSpeed / 2;
LK.setTimeout(function () {
gemSpeed = originalSpeed;
}, 3000);
} else {
LK.getSound('match').play();
}
// Update score and display
score += points;
scoreTxt.setText('Score: ' + score);
// Animate gem disappearing
tween(gem, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2
}, {
duration: 300,
onFinish: function onFinish() {
// Remove from game
removeGem(gem);
}
});
// Flash container
LK.effects.flashObject(container, 0xffffff, 500);
return true;
} else {
// Wrong container
LK.getSound('wrong').play();
lives--;
updateLivesDisplay();
if (lives <= 0) {
gameOver();
}
// Flash container red
LK.effects.flashObject(container, 0xff0000, 500);
// Animate gem disappearing
tween(gem, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
// Remove from game
removeGem(gem);
}
});
return true;
}
}
}
return false;
}
// Remove a gem from the game
function removeGem(gemToRemove) {
for (var i = gems.length - 1; i >= 0; i--) {
if (gems[i] === gemToRemove) {
// Remove from array
gems.splice(i, 1);
// Remove from display
if (gemToRemove.parent) {
gemToRemove.parent.removeChild(gemToRemove);
}
break;
}
}
}
// Game over function
function gameOver() {
gameActive = false;
// Check for high score
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over screen
LK.showGameOver();
}
// Level up function
function levelUp() {
level++;
levelTxt.setText('Level: ' + level);
LK.getSound('levelup').play();
// Add new color every 2 levels
if (level === 2) {
availableColors.push('yellow');
} else if (level === 3) {
availableColors.push('purple');
} else if (level === 4) {
availableColors.push('black');
} else if (level === 5) {
availableColors.push('orange');
} else if (level === 6) {
availableColors.push('pink');
} else if (level === 7) {
availableColors.push('cyan');
}
createContainers();
// Increase difficulty
gemSpeed += 0.5;
gemSpawnInterval = Math.max(500, gemSpawnInterval - 300);
// Flash screen effect
LK.effects.flashScreen(0xffffff, 500);
// Show level completion popup
LK.showPopup({
title: "Level Complete!",
message: "Get ready for the next level!",
onClose: function onClose() {
if (level <= maxLevels) {
initGame();
} else {
LK.showYouWin();
}
}
});
}
// Initialize the game
function initGame() {
score = 0;
lives = MAX_LIVES;
level = 1;
maxLevels = 50;
gameActive = true;
gems = [];
gemSpeed = 3;
gemSpawnInterval = 2000;
availableColors = ['red', 'blue', 'green'];
scoreTxt.setText('Score: 0');
levelTxt.setText('Level: 1');
updateLivesDisplay();
createContainers();
// Start spawning gems
LK.setTimeout(spawnGem, 1000);
// Start music
LK.playMusic('bgmusic');
}
// Game event handlers
game.down = function (x, y, obj) {
// Handle checking which gem was clicked
for (var i = 0; i < gems.length; i++) {
var gem = gems[i];
var localPoint = gem.toLocal({
x: x,
y: y
});
if (localPoint.x >= -gem.width / 2 && localPoint.x <= gem.width / 2 && localPoint.y >= -gem.height / 2 && localPoint.y <= gem.height / 2) {
currentDraggedGem = gem;
break;
}
}
};
game.move = function (x, y, obj) {
// Update dragged gem position
if (currentDraggedGem && !currentDraggedGem.matched) {
currentDraggedGem.x = x;
currentDraggedGem.y = y;
}
};
game.up = function (x, y, obj) {
// Check if the gem was dropped on a container
if (currentDraggedGem && !currentDraggedGem.matched) {
checkGemContainerCollision(currentDraggedGem);
}
currentDraggedGem = null;
};
// Main game loop
game.update = function () {
if (!gameActive) {
return;
}
// Process all gems
for (var i = gems.length - 1; i >= 0; i--) {
var gem = gems[i];
// Skip gems being dragged
if (gem === currentDraggedGem) {
continue;
}
// Check if gem hit bottom
if (gem.y > GAME_HEIGHT + 100) {
if (!gem.matched) {
lives--;
updateLivesDisplay();
if (lives <= 0) {
gameOver();
return;
}
}
removeGem(gem);
continue;
}
}
// Check for level up (based on score)
var scoreTrigger = level * 100;
if (score >= scoreTrigger && score < scoreTrigger + 10) {
levelUp();
}
};
// Initialize game
initGame();