User prompt
For 1st episode we need to collect some gems with arrange it like easy because of first level
User prompt
After pass every level unlock next level ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (grid[x][y] && grid[x][y].isAnimating) {' Line Number: 1021
User prompt
Make main menu screen and show 1 to 10 level
User prompt
efekt sonrasi gemler ekranda kaliyor hata duzeltilsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
her eslestirmede kristal catlama efektleriyle taslar yok olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Her bonus gemlere ekstra efekt ekleyelim ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
4 lu eslestirmeler line clearer olustursun L veya T seklinde 4-5 sayili eslestirmeler bomba olustursun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
L veya T seklinde birlesimler ozel bir bomba olustursun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
eger 2 bonus birbiriyle eslestirilirse ozel bir bonus olusumu olsun ve daha guclu olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
L yada T eslestirmesi bomba yaratsin 2x2 eslestirmesi tekli hedef yokeden bir bonus olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
eger eslestirme sonucu hic bir match meydana gelmeyecekse tas tasinmasin ve moves hakkimiz azalmasin
User prompt
4lu ve 5li eslestirmelerin yanina L ve T seklinde eslestirmeler sonucunda da bomba efektli bir bonus gem olussun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
4lu ve 5li eslestirmeden olusan bonus gemler herhangi bir hareketlendirmede patlasin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 340
Code edit (1 edits merged)
Please save this source code
User prompt
Crystal Cascade - Match 3 Puzzle Adventure
Initial prompt
Match3 type of game rules are simple if you make same color at least with 3 block it will be match and gone more than 3 like 4 and 5 matchs create bonus gems with special abilities
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Gem = Container.expand(function (gemType, gridX, gridY) {
var self = Container.call(this);
self.gemType = gemType;
self.gridX = gridX;
self.gridY = gridY;
self.isSpecial = false;
self.specialType = 'normal'; // 'normal', 'striped_horizontal', 'striped_vertical', 'rainbow'
self.isAnimating = false;
self.isSelected = false;
var gemAsset = self.attachAsset(gemType, {
anchorX: 0.5,
anchorY: 0.5
});
self.setSpecial = function (type) {
self.isSpecial = true;
self.specialType = type;
if (type === 'striped_horizontal' || type === 'striped_vertical') {
self.removeChild(gemAsset);
gemAsset = self.attachAsset('striped_gem', {
anchorX: 0.5,
anchorY: 0.5
});
if (type === 'striped_horizontal') {
gemAsset.rotation = Math.PI / 2;
}
} else if (type === 'rainbow') {
self.removeChild(gemAsset);
gemAsset = self.attachAsset('rainbow_gem', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'bomb') {
self.removeChild(gemAsset);
gemAsset = self.attachAsset('bomb_gem', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'target') {
self.removeChild(gemAsset);
gemAsset = self.attachAsset('target_gem', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.highlight = function () {
self.isSelected = true;
gemAsset.alpha = 0.7;
};
self.unhighlight = function () {
self.isSelected = false;
gemAsset.alpha = 1.0;
};
self.down = function (x, y, obj) {
if (!self.isAnimating) {
handleGemSelect(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var GEM_SIZE = 200;
var BOARD_SIZE = GRID_SIZE * GEM_SIZE;
var BOARD_OFFSET_X = (2048 - BOARD_SIZE) / 2;
var BOARD_OFFSET_Y = (2732 - BOARD_SIZE) / 2 - 200;
var gemTypes = ['gem_red', 'gem_blue', 'gem_green', 'gem_yellow', 'gem_purple', 'gem_orange'];
var grid = [];
var selectedGem = null;
var isProcessing = false;
var movesLeft = 30;
var currentScore = 0;
var cascadeDepth = 0;
// Initialize UI
var scoreText = new Text2('Score: 0', {
size: 60,
fill: '#ffffff'
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var movesText = new Text2('Moves: 30', {
size: 60,
fill: '#ffffff'
});
movesText.anchor.set(0.5, 0);
movesText.y = 80;
LK.gui.top.addChild(movesText);
// Create board background
var boardBg = game.attachAsset('board_bg', {
anchorX: 0.5,
anchorY: 0.5,
x: BOARD_OFFSET_X + BOARD_SIZE / 2,
y: BOARD_OFFSET_Y + BOARD_SIZE / 2
});
// Initialize grid
function initializeGrid() {
grid = [];
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, ensuring no initial matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var validTypes = gemTypes.slice();
// Remove types that would create horizontal matches
if (x >= 2 && grid[x - 1][y] && grid[x - 2][y] && grid[x - 1][y].gemType === grid[x - 2][y].gemType) {
var typeToRemove = grid[x - 1][y].gemType;
var index = validTypes.indexOf(typeToRemove);
if (index > -1) validTypes.splice(index, 1);
}
// Remove types that would create vertical matches
if (y >= 2 && grid[x][y - 1] && grid[x][y - 2] && grid[x][y - 1].gemType === grid[x][y - 2].gemType) {
var typeToRemove = grid[x][y - 1].gemType;
var index = validTypes.indexOf(typeToRemove);
if (index > -1) validTypes.splice(index, 1);
}
var randomType = validTypes[Math.floor(Math.random() * validTypes.length)];
var gem = new Gem(randomType, x, y);
gem.x = BOARD_OFFSET_X + x * GEM_SIZE + GEM_SIZE / 2;
gem.y = BOARD_OFFSET_Y + y * GEM_SIZE + GEM_SIZE / 2;
grid[x][y] = gem;
game.addChild(gem);
}
}
}
function handleGemSelect(gem) {
if (isProcessing) return;
if (selectedGem === null) {
selectedGem = gem;
gem.highlight();
} else if (selectedGem === gem) {
selectedGem.unhighlight();
selectedGem = null;
} else {
// Check if gems are adjacent
var dx = Math.abs(selectedGem.gridX - gem.gridX);
var dy = Math.abs(selectedGem.gridY - gem.gridY);
if (dx === 1 && dy === 0 || dx === 0 && dy === 1) {
// Swap gems
swapGems(selectedGem, gem);
}
selectedGem.unhighlight();
selectedGem = null;
}
}
function swapGems(gem1, gem2) {
if (movesLeft <= 0) return;
isProcessing = true;
// Check if both gems are special - create super combo
if (gem1.isSpecial && gem2.isSpecial) {
movesLeft--;
movesText.setText('Moves: ' + movesLeft);
LK.setTimeout(function () {
activateSpecialCombo(gem1, gem2);
LK.setTimeout(function () {
applyGravity();
}, 500);
}, 100);
return;
}
// Check if either gem is special and activate it
var specialActivated = false;
if (gem1.isSpecial) {
specialActivated = true;
movesLeft--;
movesText.setText('Moves: ' + movesLeft);
LK.setTimeout(function () {
activateSpecialGem(gem1);
LK.setTimeout(function () {
applyGravity();
}, 500);
}, 100);
return;
}
if (gem2.isSpecial) {
specialActivated = true;
movesLeft--;
movesText.setText('Moves: ' + movesLeft);
LK.setTimeout(function () {
activateSpecialGem(gem2);
LK.setTimeout(function () {
applyGravity();
}, 500);
}, 100);
return;
}
// Store original positions
var tempX = gem1.gridX;
var tempY = gem1.gridY;
// Temporarily swap gems to check for matches
gem1.gridX = gem2.gridX;
gem1.gridY = gem2.gridY;
gem2.gridX = tempX;
gem2.gridY = tempY;
grid[gem1.gridX][gem1.gridY] = gem1;
grid[gem2.gridX][gem2.gridY] = gem2;
// Check if this swap creates any matches
var testMatches = findMatches();
// If no matches, revert the swap and don't continue
if (testMatches.length === 0) {
// Revert grid positions to original
gem1.gridX = tempX;
gem1.gridY = tempY;
gem2.gridX = gem2.gridX;
gem2.gridY = gem2.gridY;
grid[gem1.gridX][gem1.gridY] = gem1;
grid[gem2.gridX][gem2.gridY] = gem2;
isProcessing = false;
return;
}
// Update grid positions (already done above for testing)
// Animate swap
var targetX1 = BOARD_OFFSET_X + gem1.gridX * GEM_SIZE + GEM_SIZE / 2;
var targetY1 = BOARD_OFFSET_Y + gem1.gridY * GEM_SIZE + GEM_SIZE / 2;
var targetX2 = BOARD_OFFSET_X + gem2.gridX * GEM_SIZE + GEM_SIZE / 2;
var targetY2 = BOARD_OFFSET_Y + gem2.gridY * GEM_SIZE + GEM_SIZE / 2;
gem1.isAnimating = true;
gem2.isAnimating = true;
tween(gem1, {
x: targetX1,
y: targetY1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
gem1.isAnimating = false;
checkSwapComplete();
}
});
tween(gem2, {
x: targetX2,
y: targetY2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
gem2.isAnimating = false;
checkSwapComplete();
}
});
}
var swapCompleteCount = 0;
function checkSwapComplete() {
swapCompleteCount++;
if (swapCompleteCount === 2) {
swapCompleteCount = 0;
// Check for matches
var matches = findMatches();
if (matches.length > 0) {
movesLeft--;
movesText.setText('Moves: ' + movesLeft);
processMatches(matches);
} else {
// No matches, swap back
var gem1 = null,
gem2 = null;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y].x !== BOARD_OFFSET_X + x * GEM_SIZE + GEM_SIZE / 2 || grid[x][y].y !== BOARD_OFFSET_Y + y * GEM_SIZE + GEM_SIZE / 2) {
if (gem1 === null) gem1 = grid[x][y];else gem2 = grid[x][y];
}
}
}
if (gem1 && gem2) {
swapGems(gem1, gem2);
} else {
isProcessing = false;
}
}
}
}
function findMatches() {
var matches = [];
var visited = [];
// Initialize visited array
for (var x = 0; x < GRID_SIZE; x++) {
visited[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
visited[x][y] = false;
}
}
// Find horizontal matches
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE - 2; x++) {
if (grid[x][y] && grid[x + 1][y] && grid[x + 2][y] && grid[x][y].gemType === grid[x + 1][y].gemType && grid[x + 1][y].gemType === grid[x + 2][y].gemType) {
var matchGroup = [];
var currentX = x;
while (currentX < GRID_SIZE && grid[currentX][y] && grid[currentX][y].gemType === grid[x][y].gemType) {
if (!visited[currentX][y]) {
matchGroup.push(grid[currentX][y]);
visited[currentX][y] = true;
}
currentX++;
}
if (matchGroup.length >= 3) {
matches.push(matchGroup);
}
}
}
}
// Find vertical matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE - 2; y++) {
if (grid[x][y] && grid[x][y + 1] && grid[x][y + 2] && grid[x][y].gemType === grid[x][y + 1].gemType && grid[x][y + 1].gemType === grid[x][y + 2].gemType) {
var matchGroup = [];
var currentY = y;
while (currentY < GRID_SIZE && grid[x][currentY] && grid[x][currentY].gemType === grid[x][y].gemType) {
if (!visited[x][currentY]) {
matchGroup.push(grid[x][currentY]);
visited[x][currentY] = true;
}
currentY++;
}
if (matchGroup.length >= 3) {
matches.push(matchGroup);
}
}
}
}
// Find 2x2 square matches
for (var x = 0; x < GRID_SIZE - 1; x++) {
for (var y = 0; y < GRID_SIZE - 1; y++) {
if (grid[x][y] && grid[x + 1][y] && grid[x][y + 1] && grid[x + 1][y + 1]) {
var gemType = grid[x][y].gemType;
if (grid[x + 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x + 1][y + 1].gemType === gemType && !visited[x][y] && !visited[x + 1][y] && !visited[x][y + 1] && !visited[x + 1][y + 1]) {
var squareMatch = [grid[x][y], grid[x + 1][y], grid[x][y + 1], grid[x + 1][y + 1]];
matches.push(squareMatch);
for (var i = 0; i < squareMatch.length; i++) {
visited[squareMatch[i].gridX][squareMatch[i].gridY] = true;
}
}
}
}
}
// Find L and T shaped matches
for (var x = 1; x < GRID_SIZE - 1; x++) {
for (var y = 1; y < GRID_SIZE - 1; y++) {
if (grid[x][y]) {
var centerGem = grid[x][y];
var gemType = centerGem.gemType;
// Check L shapes (4 possible orientations)
// L shape: top-left
if (grid[x - 1][y] && grid[x][y - 1] && grid[x - 1][y - 1] && grid[x - 1][y].gemType === gemType && grid[x][y - 1].gemType === gemType && grid[x - 1][y - 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x][y - 1] && !visited[x - 1][y - 1]) {
var lMatch = [centerGem, grid[x - 1][y], grid[x][y - 1], grid[x - 1][y - 1]];
matches.push(lMatch);
for (var i = 0; i < lMatch.length; i++) {
visited[lMatch[i].gridX][lMatch[i].gridY] = true;
}
}
// L shape: top-right
if (grid[x + 1][y] && grid[x][y - 1] && grid[x + 1][y - 1] && grid[x + 1][y].gemType === gemType && grid[x][y - 1].gemType === gemType && grid[x + 1][y - 1].gemType === gemType && !visited[x][y] && !visited[x + 1][y] && !visited[x][y - 1] && !visited[x + 1][y - 1]) {
var lMatch = [centerGem, grid[x + 1][y], grid[x][y - 1], grid[x + 1][y - 1]];
matches.push(lMatch);
for (var i = 0; i < lMatch.length; i++) {
visited[lMatch[i].gridX][lMatch[i].gridY] = true;
}
}
// L shape: bottom-left
if (grid[x - 1][y] && grid[x][y + 1] && grid[x - 1][y + 1] && grid[x - 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x - 1][y + 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x][y + 1] && !visited[x - 1][y + 1]) {
var lMatch = [centerGem, grid[x - 1][y], grid[x][y + 1], grid[x - 1][y + 1]];
matches.push(lMatch);
for (var i = 0; i < lMatch.length; i++) {
visited[lMatch[i].gridX][lMatch[i].gridY] = true;
}
}
// L shape: bottom-right
if (grid[x + 1][y] && grid[x][y + 1] && grid[x + 1][y + 1] && grid[x + 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x + 1][y + 1].gemType === gemType && !visited[x][y] && !visited[x + 1][y] && !visited[x][y + 1] && !visited[x + 1][y + 1]) {
var lMatch = [centerGem, grid[x + 1][y], grid[x][y + 1], grid[x + 1][y + 1]];
matches.push(lMatch);
for (var i = 0; i < lMatch.length; i++) {
visited[lMatch[i].gridX][lMatch[i].gridY] = true;
}
}
// Check T shapes (4 possible orientations)
// T shape: horizontal top
if (grid[x - 1][y] && grid[x + 1][y] && grid[x][y - 1] && grid[x - 1][y].gemType === gemType && grid[x + 1][y].gemType === gemType && grid[x][y - 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x + 1][y] && !visited[x][y - 1]) {
var tMatch = [centerGem, grid[x - 1][y], grid[x + 1][y], grid[x][y - 1]];
matches.push(tMatch);
for (var i = 0; i < tMatch.length; i++) {
visited[tMatch[i].gridX][tMatch[i].gridY] = true;
}
}
// T shape: horizontal bottom
if (grid[x - 1][y] && grid[x + 1][y] && grid[x][y + 1] && grid[x - 1][y].gemType === gemType && grid[x + 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x + 1][y] && !visited[x][y + 1]) {
var tMatch = [centerGem, grid[x - 1][y], grid[x + 1][y], grid[x][y + 1]];
matches.push(tMatch);
for (var i = 0; i < tMatch.length; i++) {
visited[tMatch[i].gridX][tMatch[i].gridY] = true;
}
}
// T shape: vertical left
if (grid[x][y - 1] && grid[x][y + 1] && grid[x - 1][y] && grid[x][y - 1].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x - 1][y].gemType === gemType && !visited[x][y] && !visited[x][y - 1] && !visited[x][y + 1] && !visited[x - 1][y]) {
var tMatch = [centerGem, grid[x][y - 1], grid[x][y + 1], grid[x - 1][y]];
matches.push(tMatch);
for (var i = 0; i < tMatch.length; i++) {
visited[tMatch[i].gridX][tMatch[i].gridY] = true;
}
}
// T shape: vertical right
if (grid[x][y - 1] && grid[x][y + 1] && grid[x + 1][y] && grid[x][y - 1].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x + 1][y].gemType === gemType && !visited[x][y] && !visited[x][y - 1] && !visited[x][y + 1] && !visited[x + 1][y]) {
var tMatch = [centerGem, grid[x][y - 1], grid[x][y + 1], grid[x + 1][y]];
matches.push(tMatch);
for (var i = 0; i < tMatch.length; i++) {
visited[tMatch[i].gridX][tMatch[i].gridY] = true;
}
}
}
}
}
return matches;
}
function processMatches(matches) {
cascadeDepth++;
var totalScore = 0;
var specialGems = [];
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
var matchScore = match.length * 10 * cascadeDepth;
totalScore += matchScore;
// Create special gems for larger matches
if (match.length === 4) {
// Check if it's a 2x2 square
var isSquare = false;
if (match.length === 4) {
// Sort gems by position to check square pattern
var sortedMatch = match.slice().sort(function (a, b) {
if (a.gridX !== b.gridX) return a.gridX - b.gridX;
return a.gridY - b.gridY;
});
// Check if it forms a 2x2 square
if (sortedMatch[0].gridX === sortedMatch[1].gridX - 1 && sortedMatch[0].gridY === sortedMatch[2].gridY - 1 && sortedMatch[1].gridX === sortedMatch[3].gridX && sortedMatch[2].gridY === sortedMatch[3].gridY && sortedMatch[0].gridX === sortedMatch[2].gridX && sortedMatch[1].gridY === sortedMatch[0].gridY) {
isSquare = true;
}
}
if (isSquare) {
// Create target gem for 2x2 square
var specialGem = match[0];
specialGem.setSpecial('target');
specialGems.push(specialGem);
} else {
// Check if it's an L or T shape (4 gems but not in a line or square)
var isLine = true;
if (match.length === 4) {
// Check if all gems are in the same row
var sameRow = true;
for (var k = 1; k < match.length; k++) {
if (match[k].gridY !== match[0].gridY) {
sameRow = false;
break;
}
}
// Check if all gems are in the same column
var sameCol = true;
for (var k = 1; k < match.length; k++) {
if (match[k].gridX !== match[0].gridX) {
sameCol = false;
break;
}
}
isLine = sameRow || sameCol;
}
if (!isLine) {
// Create bomb gem for L and T shapes
var specialGem = match[0];
specialGem.setSpecial('bomb');
specialGems.push(specialGem);
} else {
// Create striped gem for 4 in a line
var specialGem = match[0];
var isHorizontal = match[0].gridY === match[1].gridY;
specialGem.setSpecial(isHorizontal ? 'striped_horizontal' : 'striped_vertical');
specialGems.push(specialGem);
}
}
} else if (match.length >= 5) {
// Create rainbow gem
var specialGem = match[0];
specialGem.setSpecial('rainbow');
specialGems.push(specialGem);
}
// Remove matched gems (except special gems)
for (var j = 0; j < match.length; j++) {
var gem = match[j];
if (specialGems.indexOf(gem) === -1) {
grid[gem.gridX][gem.gridY] = null;
gem.destroy();
}
}
}
currentScore += totalScore;
scoreText.setText('Score: ' + currentScore);
LK.getSound('match').play();
// Apply gravity and cascade
LK.setTimeout(function () {
applyGravity();
}, 200);
}
function applyGravity() {
var gemsToAnimate = [];
// Move gems down
for (var x = 0; x < GRID_SIZE; x++) {
var writeIndex = GRID_SIZE - 1;
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (grid[x][y] !== null) {
if (y !== writeIndex) {
grid[x][writeIndex] = grid[x][y];
grid[x][y] = null;
grid[x][writeIndex].gridY = writeIndex;
var targetY = BOARD_OFFSET_Y + writeIndex * GEM_SIZE + GEM_SIZE / 2;
gemsToAnimate.push({
gem: grid[x][writeIndex],
targetY: targetY
});
}
writeIndex--;
}
}
// Fill empty spaces with new gems
for (var y = 0; y <= writeIndex; y++) {
var randomType = gemTypes[Math.floor(Math.random() * gemTypes.length)];
var newGem = new Gem(randomType, x, y);
newGem.x = BOARD_OFFSET_X + x * GEM_SIZE + GEM_SIZE / 2;
newGem.y = BOARD_OFFSET_Y + y * GEM_SIZE + GEM_SIZE / 2 - (writeIndex - y + 1) * GEM_SIZE;
grid[x][y] = newGem;
game.addChild(newGem);
var targetY = BOARD_OFFSET_Y + y * GEM_SIZE + GEM_SIZE / 2;
gemsToAnimate.push({
gem: newGem,
targetY: targetY
});
}
}
// Animate falling gems
var animationCount = 0;
for (var i = 0; i < gemsToAnimate.length; i++) {
var animData = gemsToAnimate[i];
animData.gem.isAnimating = true;
tween(animData.gem, {
y: animData.targetY
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
animationCount++;
if (animationCount === gemsToAnimate.length) {
checkForCascade();
}
}
});
}
if (gemsToAnimate.length === 0) {
checkForCascade();
}
}
function activateSpecialGem(gem) {
if (!gem.isSpecial) return false;
var gemsToRemove = [];
if (gem.specialType === 'striped_horizontal') {
// Remove entire row
for (var x = 0; x < GRID_SIZE; x++) {
if (grid[x][gem.gridY] && grid[x][gem.gridY] !== gem) {
gemsToRemove.push(grid[x][gem.gridY]);
}
}
} else if (gem.specialType === 'striped_vertical') {
// Remove entire column
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[gem.gridX][y] && grid[gem.gridX][y] !== gem) {
gemsToRemove.push(grid[gem.gridX][y]);
}
}
} else if (gem.specialType === 'rainbow') {
// Remove all gems of the same type as the first regular gem found
var targetType = null;
for (var x = 0; x < GRID_SIZE && !targetType; x++) {
for (var y = 0; y < GRID_SIZE && !targetType; y++) {
if (grid[x][y] && !grid[x][y].isSpecial && grid[x][y] !== gem) {
targetType = grid[x][y].gemType;
}
}
}
if (targetType) {
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && grid[x][y].gemType === targetType && grid[x][y] !== gem) {
gemsToRemove.push(grid[x][y]);
}
}
}
}
} else if (gem.specialType === 'bomb') {
// Remove 3x3 area around the bomb
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
var targetX = gem.gridX + dx;
var targetY = gem.gridY + dy;
if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
if (grid[targetX][targetY] && grid[targetX][targetY] !== gem) {
gemsToRemove.push(grid[targetX][targetY]);
}
}
}
}
} else if (gem.specialType === 'target') {
// Remove single target gem (the gem itself)
// Target gem destroys only itself when activated
}
// Remove the special gem itself
gemsToRemove.push(gem);
// Add explosion effect
tween(gem, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
// Remove all targeted gems
for (var i = 0; i < gemsToRemove.length; i++) {
var gemToRemove = gemsToRemove[i];
grid[gemToRemove.gridX][gemToRemove.gridY] = null;
// Add removal effect
tween(gemToRemove, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
if (gemToRemove.parent) {
gemToRemove.destroy();
}
}
});
}
// Add score for special activation
var bonusScore = gemsToRemove.length * 20;
currentScore += bonusScore;
scoreText.setText('Score: ' + currentScore);
return true;
}
function checkForCascade() {
var matches = findMatches();
if (matches.length > 0) {
LK.getSound('cascade').play();
processMatches(matches);
} else {
cascadeDepth = 0;
isProcessing = false;
// Check for game over
if (movesLeft <= 0) {
LK.showGameOver();
}
}
}
// Initialize the game
initializeGrid();
game.update = function () {
// Update gem animations
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && grid[x][y].isAnimating) {
grid[x][y].isAnimating = false;
}
}
}
};
function activateSpecialCombo(gem1, gem2) {
var gemsToRemove = [];
var comboScore = 0;
// Add dramatic visual effect for combo
tween(gem1, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
tween(gem2, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
// Determine combo effect based on gem types
var type1 = gem1.specialType;
var type2 = gem2.specialType;
if ((type1 === 'striped_horizontal' || type1 === 'striped_vertical') && (type2 === 'striped_horizontal' || type2 === 'striped_vertical')) {
// Striped + Striped = Clear entire row AND column
for (var x = 0; x < GRID_SIZE; x++) {
if (grid[x][gem1.gridY] && grid[x][gem1.gridY] !== gem1 && grid[x][gem1.gridY] !== gem2) {
gemsToRemove.push(grid[x][gem1.gridY]);
}
}
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[gem1.gridX][y] && grid[gem1.gridX][y] !== gem1 && grid[gem1.gridX][y] !== gem2) {
gemsToRemove.push(grid[gem1.gridX][y]);
}
}
comboScore = 500;
} else if (type1 === 'bomb' && type2 === 'bomb') {
// Bomb + Bomb = 5x5 explosion
for (var dx = -2; dx <= 2; dx++) {
for (var dy = -2; dy <= 2; dy++) {
var targetX = gem1.gridX + dx;
var targetY = gem1.gridY + dy;
if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
if (grid[targetX][targetY] && grid[targetX][targetY] !== gem1 && grid[targetX][targetY] !== gem2) {
gemsToRemove.push(grid[targetX][targetY]);
}
}
}
}
comboScore = 400;
} else if ((type1 === 'striped_horizontal' || type1 === 'striped_vertical') && type2 === 'bomb') {
// Striped + Bomb = 3 rows or 3 columns
if (type1 === 'striped_horizontal') {
for (var dy = -1; dy <= 1; dy++) {
for (var x = 0; x < GRID_SIZE; x++) {
var targetY = gem1.gridY + dy;
if (targetY >= 0 && targetY < GRID_SIZE) {
if (grid[x][targetY] && grid[x][targetY] !== gem1 && grid[x][targetY] !== gem2) {
gemsToRemove.push(grid[x][targetY]);
}
}
}
}
} else {
for (var dx = -1; dx <= 1; dx++) {
for (var y = 0; y < GRID_SIZE; y++) {
var targetX = gem1.gridX + dx;
if (targetX >= 0 && targetX < GRID_SIZE) {
if (grid[targetX][y] && grid[targetX][y] !== gem1 && grid[targetX][y] !== gem2) {
gemsToRemove.push(grid[targetX][y]);
}
}
}
}
}
comboScore = 350;
} else if (type1 === 'bomb' && (type2 === 'striped_horizontal' || type2 === 'striped_vertical')) {
// Bomb + Striped = 3 rows or 3 columns
if (type2 === 'striped_horizontal') {
for (var dy = -1; dy <= 1; dy++) {
for (var x = 0; x < GRID_SIZE; x++) {
var targetY = gem2.gridY + dy;
if (targetY >= 0 && targetY < GRID_SIZE) {
if (grid[x][targetY] && grid[x][targetY] !== gem1 && grid[x][targetY] !== gem2) {
gemsToRemove.push(grid[x][targetY]);
}
}
}
}
} else {
for (var dx = -1; dx <= 1; dx++) {
for (var y = 0; y < GRID_SIZE; y++) {
var targetX = gem2.gridX + dx;
if (targetX >= 0 && targetX < GRID_SIZE) {
if (grid[targetX][y] && grid[targetX][y] !== gem1 && grid[targetX][y] !== gem2) {
gemsToRemove.push(grid[targetX][y]);
}
}
}
}
}
comboScore = 350;
} else if (type1 === 'rainbow' || type2 === 'rainbow') {
// Rainbow + Any special = Transform all gems of one type to that special type
var otherGem = type1 === 'rainbow' ? gem2 : gem1;
var targetType = gemTypes[Math.floor(Math.random() * gemTypes.length)];
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && grid[x][y].gemType === targetType && grid[x][y] !== gem1 && grid[x][y] !== gem2) {
// Transform to special type
grid[x][y].setSpecial(otherGem.specialType);
}
}
}
comboScore = 600;
} else if (type1 === 'target' || type2 === 'target') {
// Target + Any special = Clear all gems of 2 random colors
var color1 = gemTypes[Math.floor(Math.random() * gemTypes.length)];
var color2 = gemTypes[Math.floor(Math.random() * gemTypes.length)];
while (color2 === color1) {
color2 = gemTypes[Math.floor(Math.random() * gemTypes.length)];
}
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && (grid[x][y].gemType === color1 || grid[x][y].gemType === color2) && grid[x][y] !== gem1 && grid[x][y] !== gem2) {
gemsToRemove.push(grid[x][y]);
}
}
}
comboScore = 450;
}
// Remove the special gems themselves
gemsToRemove.push(gem1);
gemsToRemove.push(gem2);
// Remove all targeted gems with enhanced effects
for (var i = 0; i < gemsToRemove.length; i++) {
var gemToRemove = gemsToRemove[i];
if (grid[gemToRemove.gridX] && grid[gemToRemove.gridX][gemToRemove.gridY]) {
grid[gemToRemove.gridX][gemToRemove.gridY] = null;
}
// Enhanced removal effect for combo
tween(gemToRemove, {
scaleX: 0,
scaleY: 0,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
if (gemToRemove.parent) {
gemToRemove.destroy();
}
}
});
}
// Add bonus score for special combo
currentScore += comboScore;
scoreText.setText('Score: ' + currentScore);
// Flash screen to indicate powerful combo
LK.effects.flashScreen(0xffd700, 800);
} ===================================================================
--- original.js
+++ change.js
@@ -166,8 +166,20 @@
}
function swapGems(gem1, gem2) {
if (movesLeft <= 0) return;
isProcessing = true;
+ // Check if both gems are special - create super combo
+ if (gem1.isSpecial && gem2.isSpecial) {
+ movesLeft--;
+ movesText.setText('Moves: ' + movesLeft);
+ LK.setTimeout(function () {
+ activateSpecialCombo(gem1, gem2);
+ LK.setTimeout(function () {
+ applyGravity();
+ }, 500);
+ }, 100);
+ return;
+ }
// Check if either gem is special and activate it
var specialActivated = false;
if (gem1.isSpecial) {
specialActivated = true;
@@ -674,5 +686,167 @@
grid[x][y].isAnimating = false;
}
}
}
-};
\ No newline at end of file
+};
+function activateSpecialCombo(gem1, gem2) {
+ var gemsToRemove = [];
+ var comboScore = 0;
+ // Add dramatic visual effect for combo
+ tween(gem1, {
+ scaleX: 3,
+ scaleY: 3,
+ alpha: 0
+ }, {
+ duration: 500,
+ easing: tween.easeOut
+ });
+ tween(gem2, {
+ scaleX: 3,
+ scaleY: 3,
+ alpha: 0
+ }, {
+ duration: 500,
+ easing: tween.easeOut
+ });
+ // Determine combo effect based on gem types
+ var type1 = gem1.specialType;
+ var type2 = gem2.specialType;
+ if ((type1 === 'striped_horizontal' || type1 === 'striped_vertical') && (type2 === 'striped_horizontal' || type2 === 'striped_vertical')) {
+ // Striped + Striped = Clear entire row AND column
+ for (var x = 0; x < GRID_SIZE; x++) {
+ if (grid[x][gem1.gridY] && grid[x][gem1.gridY] !== gem1 && grid[x][gem1.gridY] !== gem2) {
+ gemsToRemove.push(grid[x][gem1.gridY]);
+ }
+ }
+ for (var y = 0; y < GRID_SIZE; y++) {
+ if (grid[gem1.gridX][y] && grid[gem1.gridX][y] !== gem1 && grid[gem1.gridX][y] !== gem2) {
+ gemsToRemove.push(grid[gem1.gridX][y]);
+ }
+ }
+ comboScore = 500;
+ } else if (type1 === 'bomb' && type2 === 'bomb') {
+ // Bomb + Bomb = 5x5 explosion
+ for (var dx = -2; dx <= 2; dx++) {
+ for (var dy = -2; dy <= 2; dy++) {
+ var targetX = gem1.gridX + dx;
+ var targetY = gem1.gridY + dy;
+ if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
+ if (grid[targetX][targetY] && grid[targetX][targetY] !== gem1 && grid[targetX][targetY] !== gem2) {
+ gemsToRemove.push(grid[targetX][targetY]);
+ }
+ }
+ }
+ }
+ comboScore = 400;
+ } else if ((type1 === 'striped_horizontal' || type1 === 'striped_vertical') && type2 === 'bomb') {
+ // Striped + Bomb = 3 rows or 3 columns
+ if (type1 === 'striped_horizontal') {
+ for (var dy = -1; dy <= 1; dy++) {
+ for (var x = 0; x < GRID_SIZE; x++) {
+ var targetY = gem1.gridY + dy;
+ if (targetY >= 0 && targetY < GRID_SIZE) {
+ if (grid[x][targetY] && grid[x][targetY] !== gem1 && grid[x][targetY] !== gem2) {
+ gemsToRemove.push(grid[x][targetY]);
+ }
+ }
+ }
+ }
+ } else {
+ for (var dx = -1; dx <= 1; dx++) {
+ for (var y = 0; y < GRID_SIZE; y++) {
+ var targetX = gem1.gridX + dx;
+ if (targetX >= 0 && targetX < GRID_SIZE) {
+ if (grid[targetX][y] && grid[targetX][y] !== gem1 && grid[targetX][y] !== gem2) {
+ gemsToRemove.push(grid[targetX][y]);
+ }
+ }
+ }
+ }
+ }
+ comboScore = 350;
+ } else if (type1 === 'bomb' && (type2 === 'striped_horizontal' || type2 === 'striped_vertical')) {
+ // Bomb + Striped = 3 rows or 3 columns
+ if (type2 === 'striped_horizontal') {
+ for (var dy = -1; dy <= 1; dy++) {
+ for (var x = 0; x < GRID_SIZE; x++) {
+ var targetY = gem2.gridY + dy;
+ if (targetY >= 0 && targetY < GRID_SIZE) {
+ if (grid[x][targetY] && grid[x][targetY] !== gem1 && grid[x][targetY] !== gem2) {
+ gemsToRemove.push(grid[x][targetY]);
+ }
+ }
+ }
+ }
+ } else {
+ for (var dx = -1; dx <= 1; dx++) {
+ for (var y = 0; y < GRID_SIZE; y++) {
+ var targetX = gem2.gridX + dx;
+ if (targetX >= 0 && targetX < GRID_SIZE) {
+ if (grid[targetX][y] && grid[targetX][y] !== gem1 && grid[targetX][y] !== gem2) {
+ gemsToRemove.push(grid[targetX][y]);
+ }
+ }
+ }
+ }
+ }
+ comboScore = 350;
+ } else if (type1 === 'rainbow' || type2 === 'rainbow') {
+ // Rainbow + Any special = Transform all gems of one type to that special type
+ var otherGem = type1 === 'rainbow' ? gem2 : gem1;
+ var targetType = gemTypes[Math.floor(Math.random() * gemTypes.length)];
+ for (var x = 0; x < GRID_SIZE; x++) {
+ for (var y = 0; y < GRID_SIZE; y++) {
+ if (grid[x][y] && grid[x][y].gemType === targetType && grid[x][y] !== gem1 && grid[x][y] !== gem2) {
+ // Transform to special type
+ grid[x][y].setSpecial(otherGem.specialType);
+ }
+ }
+ }
+ comboScore = 600;
+ } else if (type1 === 'target' || type2 === 'target') {
+ // Target + Any special = Clear all gems of 2 random colors
+ var color1 = gemTypes[Math.floor(Math.random() * gemTypes.length)];
+ var color2 = gemTypes[Math.floor(Math.random() * gemTypes.length)];
+ while (color2 === color1) {
+ color2 = gemTypes[Math.floor(Math.random() * gemTypes.length)];
+ }
+ for (var x = 0; x < GRID_SIZE; x++) {
+ for (var y = 0; y < GRID_SIZE; y++) {
+ if (grid[x][y] && (grid[x][y].gemType === color1 || grid[x][y].gemType === color2) && grid[x][y] !== gem1 && grid[x][y] !== gem2) {
+ gemsToRemove.push(grid[x][y]);
+ }
+ }
+ }
+ comboScore = 450;
+ }
+ // Remove the special gems themselves
+ gemsToRemove.push(gem1);
+ gemsToRemove.push(gem2);
+ // Remove all targeted gems with enhanced effects
+ for (var i = 0; i < gemsToRemove.length; i++) {
+ var gemToRemove = gemsToRemove[i];
+ if (grid[gemToRemove.gridX] && grid[gemToRemove.gridX][gemToRemove.gridY]) {
+ grid[gemToRemove.gridX][gemToRemove.gridY] = null;
+ }
+ // Enhanced removal effect for combo
+ tween(gemToRemove, {
+ scaleX: 0,
+ scaleY: 0,
+ alpha: 0,
+ rotation: Math.PI * 2
+ }, {
+ duration: 300,
+ easing: tween.easeIn,
+ onFinish: function onFinish() {
+ if (gemToRemove.parent) {
+ gemToRemove.destroy();
+ }
+ }
+ });
+ }
+ // Add bonus score for special combo
+ currentScore += comboScore;
+ scoreText.setText('Score: ' + currentScore);
+ // Flash screen to indicate powerful combo
+ LK.effects.flashScreen(0xffd700, 800);
+}
\ No newline at end of file
Kristal gorunumlu rainbow bonus gem'i olmasi icin turuncu, mavi, turkuaz, yesil , pembe iceren ozel bir kristal png arka plan olmasin. In-Game asset. 2d. High contrast. No shadows
Kristal olarak bi bomba bonusu icin bir gem olustur
Bu renkte bir line clearer icin kristal bonus gem olustur
make wood for blocked gem. In-Game asset. 2d. High contrast. No shadows