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 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;
});
var Container = 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;
});
/****
* 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 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 Container(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 === 0 && availableColors.length < 5) {
if (level === 2) {
availableColors.push('yellow');
} else if (level === 4) {
availableColors.push('purple');
}
createContainers();
}
// Increase difficulty
gemSpeed += 0.5;
gemSpawnInterval = Math.max(500, gemSpawnInterval - 300);
// Flash screen effect
LK.effects.flashScreen(0xffffff, 500);
}
// Initialize the game
function initGame() {
score = 0;
lives = MAX_LIVES;
level = 1;
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(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,378 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0
+});
+
+/****
+* Classes
+****/
+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;
+});
+var Container = 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;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ 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 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 Container(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 === 0 && availableColors.length < 5) {
+ if (level === 2) {
+ availableColors.push('yellow');
+ } else if (level === 4) {
+ availableColors.push('purple');
+ }
+ createContainers();
+ }
+ // Increase difficulty
+ gemSpeed += 0.5;
+ gemSpawnInterval = Math.max(500, gemSpawnInterval - 300);
+ // Flash screen effect
+ LK.effects.flashScreen(0xffffff, 500);
+}
+// Initialize the game
+function initGame() {
+ score = 0;
+ lives = MAX_LIVES;
+ level = 1;
+ 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();
\ No newline at end of file