User prompt
add new gems
User prompt
i noticed less gems bud fix it
User prompt
make the game more kid friendly even more add a target and dont change the background color
User prompt
actually change the background brown again
User prompt
make the background color different
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'scaleX')' in or related to this line: 'tween(selectedGem, {' Line Number: 445 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'scaleX')' in or related to this line: 'tween(selectedGem, {' Line Number: 445 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
im not sure that color fits good ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the game more kid friendly
User prompt
make the grid with more gems but slightly smaller
User prompt
make the grid perfectly fit the screen
User prompt
U MADE IT WORSE NOW I CANT SWIPE FIX IT ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
FOR SOME REASON WHENEVER I SWIPE AND DONT MAKE A MATCH THE GEM DOESNT GO BACK TO WHERE IT WAS FIX IT ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Gem Crush Saga
Initial prompt
U BETTER NOT MESS UP LAST TIMRE IT DID DO GOOD THIS TIME NOW MAKE A GAME LIKE CANDY CRUSH BUT GEMS AND SWIPE CONTROLS PLUS TOUCH MAKE ME START ON THE HOME SCREEN THERES A PLAY BUTTON A LEADERBOARD AND A SIGN UP LOGIN AND WHEN YOURE LOGGED IN THERES A BUTTON ON THE HOME SCREEN THAT SAYS LOGOUT
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Gem = Container.expand(function (type) {
var self = Container.call(this);
self.gemType = type;
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var gemAssets = ['gem_red', 'gem_blue', 'gem_green', 'gem_yellow', 'gem_purple', 'gem_orange'];
var gemGraphics = self.attachAsset(gemAssets[type], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: CELL_SIZE / 256,
scaleY: CELL_SIZE / 256
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = boardStartX + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = boardStartY + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
if (duration === undefined) duration = 300;
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var BOARD_SIZE = 8;
var CELL_SIZE = Math.floor(Math.min(2048, 2732 - 400) / BOARD_SIZE); // Leave 400px for UI elements
var BOARD_TOTAL_SIZE = BOARD_SIZE * CELL_SIZE;
var boardStartX = (2048 - BOARD_TOTAL_SIZE) / 2;
var boardStartY = (2732 - BOARD_TOTAL_SIZE) / 2 + 100; // Offset for top UI
var board = [];
var gems = [];
var selectedGem = null;
var isProcessingMatches = false;
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
var score = 0;
// Create board background
var boardBackground = game.addChild(LK.getAsset('boardBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: boardStartY + BOARD_TOTAL_SIZE / 2,
scaleX: BOARD_TOTAL_SIZE / 960,
scaleY: BOARD_TOTAL_SIZE / 960
}));
// Initialize score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 100;
function initializeBoard() {
// Create 2D array for board
for (var y = 0; y < BOARD_SIZE; y++) {
board[y] = [];
gems[y] = [];
for (var x = 0; x < BOARD_SIZE; x++) {
var gemType = Math.floor(Math.random() * 6);
var gem = new Gem(gemType);
gem.setGridPosition(x, y);
board[y][x] = gemType;
gems[y][x] = gem;
game.addChild(gem);
}
}
// Remove initial matches
removeInitialMatches();
}
function removeInitialMatches() {
var foundMatches = true;
var iterations = 0;
while (foundMatches && iterations < 10) {
foundMatches = false;
iterations++;
for (var y = 0; y < BOARD_SIZE; y++) {
for (var x = 0; x < BOARD_SIZE; x++) {
if (hasMatchAt(x, y)) {
var newType = Math.floor(Math.random() * 6);
board[y][x] = newType;
gems[y][x].gemType = newType;
// Update gem graphics by recreating
gems[y][x].destroy();
var newGem = new Gem(newType);
newGem.setGridPosition(x, y);
gems[y][x] = newGem;
game.addChild(newGem);
foundMatches = true;
}
}
}
}
}
function hasMatchAt(x, y) {
var gemType = board[y][x];
// Check horizontal match
var horizontalCount = 1;
// Check left
for (var i = x - 1; i >= 0 && board[y][i] === gemType; i--) {
horizontalCount++;
}
// Check right
for (var i = x + 1; i < BOARD_SIZE && board[y][i] === gemType; i++) {
horizontalCount++;
}
// Check vertical match
var verticalCount = 1;
// Check up
for (var i = y - 1; i >= 0 && board[i][x] === gemType; i--) {
verticalCount++;
}
// Check down
for (var i = y + 1; i < BOARD_SIZE && board[i][x] === gemType; i++) {
verticalCount++;
}
return horizontalCount >= 3 || verticalCount >= 3;
}
function getGemAt(gameX, gameY) {
var gridX = Math.floor((gameX - boardStartX) / CELL_SIZE);
var gridY = Math.floor((gameY - boardStartY) / CELL_SIZE);
if (gridX >= 0 && gridX < BOARD_SIZE && gridY >= 0 && gridY < BOARD_SIZE) {
return gems[gridY][gridX];
}
return null;
}
function isAdjacent(gem1, gem2) {
var dx = Math.abs(gem1.gridX - gem2.gridX);
var dy = Math.abs(gem1.gridY - gem2.gridY);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
function swapGems(gem1, gem2) {
if (!gem1 || !gem2 || gem1.isAnimating || gem2.isAnimating) return;
// Store original positions and types
var originalGem1X = gem1.gridX;
var originalGem1Y = gem1.gridY;
var originalGem2X = gem2.gridX;
var originalGem2Y = gem2.gridY;
var originalGem1Type = gem1.gemType;
var originalGem2Type = gem2.gemType;
// Calculate original visual positions
var originalGem1PosX = boardStartX + originalGem1X * CELL_SIZE + CELL_SIZE / 2;
var originalGem1PosY = boardStartY + originalGem1Y * CELL_SIZE + CELL_SIZE / 2;
var originalGem2PosX = boardStartX + originalGem2X * CELL_SIZE + CELL_SIZE / 2;
var originalGem2PosY = boardStartY + originalGem2Y * CELL_SIZE + CELL_SIZE / 2;
// Temporarily update board and gem properties to test for matches
board[originalGem1Y][originalGem1X] = originalGem2Type;
board[originalGem2Y][originalGem2X] = originalGem1Type;
gem1.gemType = originalGem2Type;
gem2.gemType = originalGem1Type;
// Check if this swap creates any matches
var hasMatch = hasMatchAt(originalGem1X, originalGem1Y) || hasMatchAt(originalGem2X, originalGem2Y);
if (hasMatch) {
// Valid swap - complete the swap
gem1.setGridPosition(originalGem2X, originalGem2Y);
gem2.setGridPosition(originalGem1X, originalGem1Y);
// Update gems array
gems[originalGem1Y][originalGem1X] = gem2;
gems[originalGem2Y][originalGem2X] = gem1;
// Animate to swapped positions
gem1.animateToPosition(originalGem2PosX, originalGem2PosY, 200);
gem2.animateToPosition(originalGem1PosX, originalGem1PosY, 200, function () {
LK.getSound('swap').play();
checkForMatches();
});
} else {
// Invalid swap - revert changes
board[originalGem1Y][originalGem1X] = originalGem1Type;
board[originalGem2Y][originalGem2X] = originalGem2Type;
gem1.gemType = originalGem1Type;
gem2.gemType = originalGem2Type;
// Animate gems briefly toward each other then back
var swapDistance = 30;
var gem1SwipePosX = originalGem1PosX + (originalGem2PosX - originalGem1PosX) * 0.3;
var gem1SwipePosY = originalGem1PosY + (originalGem2PosY - originalGem1PosY) * 0.3;
var gem2SwipePosX = originalGem2PosX + (originalGem1PosX - originalGem2PosX) * 0.3;
var gem2SwipePosY = originalGem2PosY + (originalGem1PosY - originalGem2PosY) * 0.3;
// First animate toward each other
gem1.animateToPosition(gem1SwipePosX, gem1SwipePosY, 150, function () {
// Then animate back to original positions
gem1.animateToPosition(originalGem1PosX, originalGem1PosY, 150);
});
gem2.animateToPosition(gem2SwipePosX, gem2SwipePosY, 150, function () {
// Then animate back to original positions
gem2.animateToPosition(originalGem2PosX, originalGem2PosY, 150);
});
}
}
function checkForMatches() {
if (isProcessingMatches) return;
var matchesFound = [];
// Find all matches
for (var y = 0; y < BOARD_SIZE; y++) {
for (var x = 0; x < BOARD_SIZE; x++) {
var matches = getMatchesAt(x, y);
if (matches.length >= 3) {
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
var alreadyFound = false;
for (var j = 0; j < matchesFound.length; j++) {
if (matchesFound[j].x === match.x && matchesFound[j].y === match.y) {
alreadyFound = true;
break;
}
}
if (!alreadyFound) {
matchesFound.push(match);
}
}
}
}
}
if (matchesFound.length > 0) {
isProcessingMatches = true;
removeMatches(matchesFound);
}
}
function getMatchesAt(x, y) {
var gemType = board[y][x];
var matches = [{
x: x,
y: y
}];
// Check horizontal
var horizontalMatches = [{
x: x,
y: y
}];
// Check left
for (var i = x - 1; i >= 0 && board[y][i] === gemType; i--) {
horizontalMatches.push({
x: i,
y: y
});
}
// Check right
for (var i = x + 1; i < BOARD_SIZE && board[y][i] === gemType; i++) {
horizontalMatches.push({
x: i,
y: y
});
}
// Check vertical
var verticalMatches = [{
x: x,
y: y
}];
// Check up
for (var i = y - 1; i >= 0 && board[i][x] === gemType; i--) {
verticalMatches.push({
x: x,
y: i
});
}
// Check down
for (var i = y + 1; i < BOARD_SIZE && board[i][x] === gemType; i++) {
verticalMatches.push({
x: x,
y: i
});
}
if (horizontalMatches.length >= 3) {
matches = horizontalMatches;
}
if (verticalMatches.length >= 3) {
if (matches.length === 1) {
matches = verticalMatches;
} else {
// Combine both matches
for (var i = 0; i < verticalMatches.length; i++) {
var vMatch = verticalMatches[i];
var alreadyExists = false;
for (var j = 0; j < matches.length; j++) {
if (matches[j].x === vMatch.x && matches[j].y === vMatch.y) {
alreadyExists = true;
break;
}
}
if (!alreadyExists) {
matches.push(vMatch);
}
}
}
}
return matches.length >= 3 ? matches : [];
}
function removeMatches(matches) {
// Add score
score += matches.length * 10;
scoreTxt.setText('Score: ' + score);
// Flash and remove matched gems
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
var gem = gems[match.y][match.x];
if (gem) {
LK.effects.flashObject(gem, 0xffffff, 300);
tween(gem, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 300,
easing: tween.easeIn
});
}
board[match.y][match.x] = -1; // Mark as empty
}
LK.getSound('match').play();
// Wait for animation then drop gems
LK.setTimeout(function () {
dropGems();
}, 350);
}
function dropGems() {
var moved = false;
// Drop existing gems
for (var x = 0; x < BOARD_SIZE; x++) {
var writePos = BOARD_SIZE - 1;
for (var y = BOARD_SIZE - 1; y >= 0; y--) {
if (board[y][x] !== -1) {
if (y !== writePos) {
// Move gem down
board[writePos][x] = board[y][x];
gems[writePos][x] = gems[y][x];
gems[writePos][x].setGridPosition(x, writePos);
gems[writePos][x].animateToPosition(boardStartX + x * CELL_SIZE + CELL_SIZE / 2, boardStartY + writePos * CELL_SIZE + CELL_SIZE / 2, 200);
board[y][x] = -1;
gems[y][x] = null;
moved = true;
}
writePos--;
}
}
}
// Fill empty spaces with new gems
for (var x = 0; x < BOARD_SIZE; x++) {
for (var y = 0; y < BOARD_SIZE; y++) {
if (board[y][x] === -1) {
var newType = Math.floor(Math.random() * 6);
var newGem = new Gem(newType);
newGem.setGridPosition(x, y);
newGem.y = boardStartY - (BOARD_SIZE - y) * CELL_SIZE + CELL_SIZE / 2; // Start above board
newGem.animateToPosition(boardStartX + x * CELL_SIZE + CELL_SIZE / 2, boardStartY + y * CELL_SIZE + CELL_SIZE / 2, 400);
board[y][x] = newType;
gems[y][x] = newGem;
game.addChild(newGem);
moved = true;
}
}
}
if (moved) {
LK.setTimeout(function () {
isProcessingMatches = false;
checkForMatches(); // Check for cascade matches
}, 450);
} else {
isProcessingMatches = false;
}
}
game.down = function (x, y, obj) {
if (isProcessingMatches) return;
selectedGem = getGemAt(x, y);
if (selectedGem) {
isDragging = true;
dragStartX = x;
dragStartY = y;
LK.effects.flashObject(selectedGem, 0xffffff, 200);
}
};
game.move = function (x, y, obj) {
if (!isDragging || !selectedGem || isProcessingMatches) return;
var deltaX = x - dragStartX;
var deltaY = y - dragStartY;
var threshold = CELL_SIZE / 2;
if (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold) {
var targetGem = null;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
if (deltaX > 0 && selectedGem.gridX < BOARD_SIZE - 1) {
targetGem = gems[selectedGem.gridY][selectedGem.gridX + 1];
} else if (deltaX < 0 && selectedGem.gridX > 0) {
targetGem = gems[selectedGem.gridY][selectedGem.gridX - 1];
}
} else {
// Vertical swipe
if (deltaY > 0 && selectedGem.gridY < BOARD_SIZE - 1) {
targetGem = gems[selectedGem.gridY + 1][selectedGem.gridX];
} else if (deltaY < 0 && selectedGem.gridY > 0) {
targetGem = gems[selectedGem.gridY - 1][selectedGem.gridX];
}
}
if (targetGem) {
swapGems(selectedGem, targetGem);
}
isDragging = false;
selectedGem = null;
}
};
game.up = function (x, y, obj) {
isDragging = false;
selectedGem = null;
};
// Initialize the game board
initializeBoard(); ===================================================================
--- original.js
+++ change.js
@@ -14,15 +14,17 @@
self.isAnimating = false;
var gemAssets = ['gem_red', 'gem_blue', 'gem_green', 'gem_yellow', 'gem_purple', 'gem_orange'];
var gemGraphics = self.attachAsset(gemAssets[type], {
anchorX: 0.5,
- anchorY: 0.5
+ anchorY: 0.5,
+ scaleX: CELL_SIZE / 256,
+ scaleY: CELL_SIZE / 256
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
- self.x = boardStartX + gridX * 120 + 60;
- self.y = boardStartY + gridY * 120 + 60;
+ self.x = boardStartX + gridX * CELL_SIZE + CELL_SIZE / 2;
+ self.y = boardStartY + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
if (duration === undefined) duration = 300;
self.isAnimating = true;
@@ -51,11 +53,12 @@
/****
* Game Code
****/
var BOARD_SIZE = 8;
-var CELL_SIZE = 120;
-var boardStartX = (2048 - BOARD_SIZE * CELL_SIZE) / 2;
-var boardStartY = (2732 - BOARD_SIZE * CELL_SIZE) / 2;
+var CELL_SIZE = Math.floor(Math.min(2048, 2732 - 400) / BOARD_SIZE); // Leave 400px for UI elements
+var BOARD_TOTAL_SIZE = BOARD_SIZE * CELL_SIZE;
+var boardStartX = (2048 - BOARD_TOTAL_SIZE) / 2;
+var boardStartY = (2732 - BOARD_TOTAL_SIZE) / 2 + 100; // Offset for top UI
var board = [];
var gems = [];
var selectedGem = null;
var isProcessingMatches = false;
@@ -67,9 +70,11 @@
var boardBackground = game.addChild(LK.getAsset('boardBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
- y: 2732 / 2
+ y: boardStartY + BOARD_TOTAL_SIZE / 2,
+ scaleX: BOARD_TOTAL_SIZE / 960,
+ scaleY: BOARD_TOTAL_SIZE / 960
}));
// Initialize score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
@@ -165,12 +170,12 @@
var originalGem2Y = gem2.gridY;
var originalGem1Type = gem1.gemType;
var originalGem2Type = gem2.gemType;
// Calculate original visual positions
- var originalGem1PosX = boardStartX + originalGem1X * 120 + 60;
- var originalGem1PosY = boardStartY + originalGem1Y * 120 + 60;
- var originalGem2PosX = boardStartX + originalGem2X * 120 + 60;
- var originalGem2PosY = boardStartY + originalGem2Y * 120 + 60;
+ var originalGem1PosX = boardStartX + originalGem1X * CELL_SIZE + CELL_SIZE / 2;
+ var originalGem1PosY = boardStartY + originalGem1Y * CELL_SIZE + CELL_SIZE / 2;
+ var originalGem2PosX = boardStartX + originalGem2X * CELL_SIZE + CELL_SIZE / 2;
+ var originalGem2PosY = boardStartY + originalGem2Y * CELL_SIZE + CELL_SIZE / 2;
// Temporarily update board and gem properties to test for matches
board[originalGem1Y][originalGem1X] = originalGem2Type;
board[originalGem2Y][originalGem2X] = originalGem1Type;
gem1.gemType = originalGem2Type;
@@ -349,9 +354,9 @@
// Move gem down
board[writePos][x] = board[y][x];
gems[writePos][x] = gems[y][x];
gems[writePos][x].setGridPosition(x, writePos);
- gems[writePos][x].animateToPosition(boardStartX + x * 120 + 60, boardStartY + writePos * 120 + 60, 200);
+ gems[writePos][x].animateToPosition(boardStartX + x * CELL_SIZE + CELL_SIZE / 2, boardStartY + writePos * CELL_SIZE + CELL_SIZE / 2, 200);
board[y][x] = -1;
gems[y][x] = null;
moved = true;
}
@@ -365,10 +370,10 @@
if (board[y][x] === -1) {
var newType = Math.floor(Math.random() * 6);
var newGem = new Gem(newType);
newGem.setGridPosition(x, y);
- newGem.y = boardStartY - (BOARD_SIZE - y) * 120 + 60; // Start above board
- newGem.animateToPosition(boardStartX + x * 120 + 60, boardStartY + y * 120 + 60, 400);
+ newGem.y = boardStartY - (BOARD_SIZE - y) * CELL_SIZE + CELL_SIZE / 2; // Start above board
+ newGem.animateToPosition(boardStartX + x * CELL_SIZE + CELL_SIZE / 2, boardStartY + y * CELL_SIZE + CELL_SIZE / 2, 400);
board[y][x] = newType;
gems[y][x] = newGem;
game.addChild(newGem);
moved = true;
@@ -397,9 +402,9 @@
game.move = function (x, y, obj) {
if (!isDragging || !selectedGem || isProcessingMatches) return;
var deltaX = x - dragStartX;
var deltaY = y - dragStartY;
- var threshold = 60;
+ var threshold = CELL_SIZE / 2;
if (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold) {
var targetGem = null;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
make a orange gem realistic. In-Game asset. 2d. High contrast. No shadows
a purple gem not a diamond realistic. In-Game asset. 2d. High contrast. No shadows
a red gem realistic. In-Game asset. 2d. High contrast. No shadows
a yellow gem found from the caves of colorado make it realistic. In-Game asset. 2d. High contrast. No shadows
a cyan realistic gem. In-Game asset. 2d. High contrast. No shadows
a pink gem realistic. In-Game asset. 2d. High contrast. No shadows
a very modern pause button. In-Game asset. 2d. High contrast. No shadows
a fun play button that says play on it super modern and kid friendly. In-Game asset. 2d. High contrast. No shadows
a create account button for signing up in a game supa kid friendly and modern. In-Game asset. 2d. High contrast. No shadows