User prompt
Oyuna basit bir başlangıç ekranı ekle bu ekranda "Start" butonu ve "Options" butonu olsun Options Butonuna tıkladığımız zaman açılan bölümde ses seviyesi bulunsun bunu değiştirebilelim ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Oyuna puan sistemi ekle alt kisımda puanımiz yazsın her bir patlayan gem için 10 puan eklensin
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading '8')' in or related to this line: 'if (grid[x][y]) {' Line Number: 503
User prompt
Some bombs and gems can fit into each other. Fix this issue.
User prompt
Bazı gemler patladıgı zaman alt kısımlarda 1x1 alana sahip bölgeler boş kaliyor bunu düzelt bir nesne patladığı zaman hemen o kalan boşlukları üstten gelen bomba gem ve benzeri nesneler doldursun
User prompt
Oyuna bomba mekaniği ekle patladığı zaman 3x3 alana sahip bir bölgeyi patlatsın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Bir topun altındaki blok gidince o topun aşagı düşmesini sağla
Code edit (1 edits merged)
Please save this source code
User prompt
Gem Cascade
Initial prompt
Design me a game similar to Candy Crush, and in addition to the game, make sure that the coefficient of the points we earn increases after reaching a certain score.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Gem = Container.expand(function () {
var self = Container.call(this);
self.gemType = 0;
self.gridX = 0;
self.gridY = 0;
self.graphics = null;
self.isSelected = false;
self.isMatched = false;
self.isFalling = false;
self.init = function (type, gx, gy) {
self.gemType = type;
self.gridX = gx;
self.gridY = gy;
var gemTypes = ['gemRed', 'gemBlue', 'gemGreen', 'gemYellow', 'gemPurple', 'gemOrange'];
self.graphics = self.attachAsset(gemTypes[type], {
anchorX: 0.5,
anchorY: 0.5
});
self.updatePosition();
};
self.updatePosition = function () {
var startX = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var startY = 400;
self.x = startX + self.gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = startY + self.gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.graphics.alpha = 0.7;
tween(self.graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200
});
} else {
self.graphics.alpha = 1.0;
tween(self.graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
};
self.fallTo = function (newY, callback) {
self.isFalling = true;
self.gridY = newY;
var newPosY = 400 + newY * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
y: newPosY
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.isFalling = false;
if (callback) callback();
}
});
};
self.destroy = function () {
self.isMatched = true;
tween(self.graphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
self.down = function (x, y, obj) {
if (!self.isFalling && !isProcessing) {
selectGem(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 200;
var GEM_TYPES = 6;
var grid = [];
var selectedGem = null;
var score = 0;
var multiplier = 1;
var isProcessing = false;
var cascadeCount = 0;
// Initialize score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var multiplierTxt = new Text2('Multiplier: x1', {
size: 60,
fill: 0xFFFF00
});
multiplierTxt.anchor.set(0.5, 0);
multiplierTxt.y = 100;
LK.gui.top.addChild(multiplierTxt);
// Initialize grid
function initializeGrid() {
var startX = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var startY = 400;
// Create background cells
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var cell = LK.getAsset('gridCell', {
anchorX: 0,
anchorY: 0,
alpha: 0.3
});
cell.x = startX + x * CELL_SIZE;
cell.y = startY + y * CELL_SIZE;
game.addChild(cell);
}
}
// Initialize grid array
for (var x = 0; x < GRID_SIZE; x++) {
grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
grid[x][y] = null;
}
}
// Fill grid with gems
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
createGem(x, y);
}
}
// Remove initial matches
removeInitialMatches();
}
function createGem(x, y) {
var gem = new Gem();
var gemType = Math.floor(Math.random() * GEM_TYPES);
gem.init(gemType, x, y);
grid[x][y] = gem;
game.addChild(gem);
return gem;
}
function removeInitialMatches() {
var hasMatches = true;
var attempts = 0;
while (hasMatches && attempts < 50) {
hasMatches = false;
attempts++;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && hasMatchAt(x, y)) {
// Regenerate this gem
var oldGem = grid[x][y];
if (oldGem.parent) {
oldGem.parent.removeChild(oldGem);
}
createGem(x, y);
hasMatches = true;
}
}
}
}
}
function selectGem(gem) {
if (selectedGem === gem) {
// Deselect
selectedGem.setSelected(false);
selectedGem = null;
return;
}
if (selectedGem === null) {
// First selection
selectedGem = gem;
gem.setSelected(true);
} else {
// Second selection - check if adjacent
if (areAdjacent(selectedGem, gem)) {
swapGems(selectedGem, gem);
}
selectedGem.setSelected(false);
selectedGem = null;
}
}
function areAdjacent(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 (isProcessing) return;
isProcessing = true;
// Store positions
var tempX = gem1.gridX;
var tempY = gem1.gridY;
// Update grid positions
gem1.gridX = gem2.gridX;
gem1.gridY = gem2.gridY;
gem2.gridX = tempX;
gem2.gridY = tempY;
// Update grid array
grid[gem1.gridX][gem1.gridY] = gem1;
grid[gem2.gridX][gem2.gridY] = gem2;
// Animate swap
var gem1NewX = gem1.x;
var gem1NewY = gem1.y;
gem1.updatePosition();
var gem2NewX = gem2.x;
var gem2NewY = gem2.y;
gem2.updatePosition();
gem1.x = gem2NewX;
gem1.y = gem2NewY;
gem2.x = gem1NewX;
gem2.y = gem1NewY;
tween(gem1, {
x: gem1NewX,
y: gem1NewY
}, {
duration: 300
});
tween(gem2, {
x: gem2NewX,
y: gem2NewY
}, {
duration: 300,
onFinish: function onFinish() {
checkForMatches();
}
});
}
function hasMatchAt(x, y) {
if (!grid[x] || !grid[x][y]) return false;
var gemType = grid[x][y].gemType;
// Check horizontal
var hCount = 1;
// Check left
for (var i = x - 1; i >= 0 && grid[i][y] && grid[i][y].gemType === gemType; i--) {
hCount++;
}
// Check right
for (var i = x + 1; i < GRID_SIZE && grid[i][y] && grid[i][y].gemType === gemType; i++) {
hCount++;
}
if (hCount >= 3) return true;
// Check vertical
var vCount = 1;
// Check up
for (var i = y - 1; i >= 0 && grid[x][i] && grid[x][i].gemType === gemType; i--) {
vCount++;
}
// Check down
for (var i = y + 1; i < GRID_SIZE && grid[x][i] && grid[x][i].gemType === gemType; i++) {
vCount++;
}
return vCount >= 3;
}
function checkForMatches() {
var matches = [];
// Find all matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && hasMatchAt(x, y)) {
matches.push({
x: x,
y: y
});
}
}
}
if (matches.length > 0) {
cascadeCount++;
LK.getSound('match').play();
// Calculate score
var points = matches.length * 10 * multiplier * cascadeCount;
score += points;
updateScore();
// Mark matched gems for destruction
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (grid[match.x][match.y]) {
grid[match.x][match.y].destroy();
grid[match.x][match.y] = null;
}
}
// Wait for destruction animation then cascade
LK.setTimeout(function () {
cascadeGems();
}, 400);
} else {
cascadeCount = 0;
isProcessing = false;
}
}
function cascadeGems() {
var needsCascade = false;
var fallPromises = 0;
// Process each column from left to right
for (var x = 0; x < GRID_SIZE; x++) {
var gemsToMove = [];
var targetPositions = [];
// Find all gems that need to fall in this column
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (grid[x][y] !== null) {
// Find the lowest available position for this gem
var targetY = y;
while (targetY + 1 < GRID_SIZE && grid[x][targetY + 1] === null) {
targetY++;
}
// If gem needs to move down
if (targetY !== y) {
gemsToMove.push({
gem: grid[x][y],
fromY: y,
toY: targetY
});
needsCascade = true;
}
}
}
// Move gems to their new positions
for (var i = 0; i < gemsToMove.length; i++) {
var moveData = gemsToMove[i];
var gem = moveData.gem;
var fromY = moveData.fromY;
var toY = moveData.toY;
// Update grid array
grid[x][fromY] = null;
grid[x][toY] = gem;
// Animate the fall
fallPromises++;
gem.fallTo(toY, function () {
fallPromises--;
if (fallPromises === 0) {
fillEmptySpaces();
}
});
}
}
if (!needsCascade) {
fillEmptySpaces();
} else {
LK.getSound('cascade').play();
}
}
function fillEmptySpaces() {
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] === null) {
createGem(x, y);
// Animate gem falling from top
grid[x][y].y = -200;
tween(grid[x][y], {
y: 400 + y * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 500,
easing: tween.bounceOut
});
}
}
}
// Check for new matches after a delay
LK.setTimeout(function () {
checkForMatches();
}, 600);
}
function updateScore() {
scoreTxt.setText('Score: ' + score);
// Update multiplier based on score
var newMultiplier = 1;
if (score >= 2500) newMultiplier = 5;else if (score >= 1000) newMultiplier = 4;else if (score >= 500) newMultiplier = 3;else if (score >= 100) newMultiplier = 2;
if (newMultiplier !== multiplier) {
multiplier = newMultiplier;
multiplierTxt.setText('Multiplier: x' + multiplier);
LK.effects.flashScreen(0x00ff00, 500);
}
// Win condition
if (score >= 5000) {
LK.showYouWin();
}
}
// Initialize the game
initializeGrid();
updateScore();
game.update = function () {
// Game loop - handle any continuous updates here
}; ===================================================================
--- original.js
+++ change.js
@@ -316,29 +316,49 @@
}
function cascadeGems() {
var needsCascade = false;
var fallPromises = 0;
+ // Process each column from left to right
for (var x = 0; x < GRID_SIZE; x++) {
- // Count empty spaces from bottom
- var writeIndex = GRID_SIZE - 1;
+ var gemsToMove = [];
+ var targetPositions = [];
+ // Find all gems that need to fall in this column
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (grid[x][y] !== null) {
- if (y !== writeIndex) {
- // Move gem down
- grid[x][writeIndex] = grid[x][y];
- grid[x][y] = null;
- fallPromises++;
- grid[x][writeIndex].fallTo(writeIndex, function () {
- fallPromises--;
- if (fallPromises === 0) {
- fillEmptySpaces();
- }
+ // Find the lowest available position for this gem
+ var targetY = y;
+ while (targetY + 1 < GRID_SIZE && grid[x][targetY + 1] === null) {
+ targetY++;
+ }
+ // If gem needs to move down
+ if (targetY !== y) {
+ gemsToMove.push({
+ gem: grid[x][y],
+ fromY: y,
+ toY: targetY
});
needsCascade = true;
}
- writeIndex--;
}
}
+ // Move gems to their new positions
+ for (var i = 0; i < gemsToMove.length; i++) {
+ var moveData = gemsToMove[i];
+ var gem = moveData.gem;
+ var fromY = moveData.fromY;
+ var toY = moveData.toY;
+ // Update grid array
+ grid[x][fromY] = null;
+ grid[x][toY] = gem;
+ // Animate the fall
+ fallPromises++;
+ gem.fallTo(toY, function () {
+ fallPromises--;
+ if (fallPromises === 0) {
+ fillEmptySpaces();
+ }
+ });
+ }
}
if (!needsCascade) {
fillEmptySpaces();
} else {
red smiley ball. In-Game asset. 2d. High contrast. No shadows
Blue smiley ball. In-Game asset. 2d. High contrast. No shadows
Green smiley face. In-Game asset. 2d. High contrast. No shadows
Orange smiley ball. In-Game asset. 2d. High contrast. No shadows
Purple smiley ball. In-Game asset. 2d. High contrast. No shadows
Yellow smiley ball. In-Game asset. 2d. High contrast. No shadows
Bomba. In-Game asset. 2d. High contrast. No shadows
Star. In-Game asset. 2d. High contrast. No shadows
Spaceship. In-Game asset. 2d. High contrast. No shadows
A UFO with aliens inside. In-Game asset. 2d. High contrast. No shadows
Red smiley face. In-Game asset. 2d. High contrast. No shadows
Green smiley ball. In-Game asset. 2d. High contrast. No shadows
Male Cyber Character. In-Game asset. 2d. High contrast. No shadows
Vertical rocket. In-Game asset. 2d. High contrast. No shadows