User prompt
Score yazısının üst tarafına min 4000 ekle
User prompt
Min 4000 yazan bir yazı ekle
User prompt
Bir hata var puan 1000 küsür olmasına ragmen kazandınız diyor
User prompt
Oyuncunun scoru süre bittiginde 4000 ve üzeri olmalı yoksa oyun biter
User prompt
Sayaç sıfırlandıgında oyuncunun puanı 4000 be üzeri olmalı aksi halde oyun biter
User prompt
3 dakikadan geri dogru sayan bir sayaç eklemek istiyorum
User prompt
Özel şeker için ses eklemek istiyorum
User prompt
Özel şekere dokundugum zaman etrafındaki 2x2 sıradaki şekerleri silip kaybolsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Özel şekere dokunmadıgım sürece kaybolmasın
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Candy = Container.expand(function (type, isSpecial) { var self = Container.call(this); self.candyType = type; self.isSpecial = isSpecial || false; self.gridX = -1; self.gridY = -1; self.isMatched = false; self.isMoving = false; self.isDragging = false; // Background removed - only candy graphics remain var candyGraphic; if (self.isSpecial) { candyGraphic = self.attachAsset('specialCandy', { anchorX: 0.5, anchorY: 0.5 }); } else { candyGraphic = self.attachAsset('candy' + type, { anchorX: 0.5, anchorY: 0.5 }); } self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = GRID_START_X + gridX * CELL_SIZE; self.y = GRID_START_Y + gridY * CELL_SIZE; }; self.animateToPosition = function (targetX, targetY, onComplete) { self.isMoving = true; tween(self, { x: targetX, y: targetY }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { self.isMoving = false; if (onComplete) onComplete(); } }); }; self.markForDestroy = function () { self.isMatched = true; tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { self.destroy(); } }); }; self.down = function (x, y, obj) { if (gameState !== 'playing' || self.isMoving) return; if (self.isSpecial) { // Special candy clicked - clear 2x2 area around it var centerX = self.gridX; var centerY = self.gridY; var candiesDestroyed = 0; // Clear 2x2 area around the special candy (including the special candy itself) for (var dx = -1; dx <= 1; dx++) { for (var dy = -1; dy <= 1; dy++) { var targetX = centerX + dx; var targetY = centerY + dy; if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) { var targetCandy = grid[targetX][targetY]; if (targetCandy && !targetCandy.isMatched && !targetCandy.isSpecial) { targetCandy.markForDestroy(); grid[targetX][targetY] = null; candiesDestroyed++; score += 15; // Bonus points for special candy destruction } } } } scoreText.setText('Score: ' + score); LK.getSound('match').play(); // Drop candies after delay LK.setTimeout(function () { dropCandies(); }, 350); return; // Exit early for special candies } selectedCandy = self; self.scaleX = 1.1; self.scaleY = 1.1; self.isDragging = true; self.dragStartX = x; self.dragStartY = y; self.startX = self.x; self.startY = self.y; }; self.move = function (x, y, obj) { if (self.isDragging && gameState === 'playing' && !self.isMoving) { var deltaX = x - self.dragStartX; var deltaY = y - self.dragStartY; // Determine which direction has the larger movement var absDeltaX = Math.abs(deltaX); var absDeltaY = Math.abs(deltaY); var targetX = self.startX; var targetY = self.startY; // Only move in the direction with the larger delta, and limit to one cell if (absDeltaX > absDeltaY) { // Horizontal movement if (deltaX > CELL_SIZE / 2 && self.gridX < GRID_SIZE - 1) { targetX = self.startX + CELL_SIZE; } else if (deltaX < -CELL_SIZE / 2 && self.gridX > 0) { targetX = self.startX - CELL_SIZE; } } else { // Vertical movement if (deltaY > CELL_SIZE / 2 && self.gridY < GRID_SIZE - 1) { targetY = self.startY + CELL_SIZE; } else if (deltaY < -CELL_SIZE / 2 && self.gridY > 0) { targetY = self.startY - CELL_SIZE; } } self.x = targetX; self.y = targetY; } }; self.up = function (x, y, obj) { if (gameState !== 'playing' || self.isMoving) return; if (self.isDragging) { self.isDragging = false; // Find target grid position based on current visual position var targetX = Math.round((self.x - GRID_START_X) / CELL_SIZE); var targetY = Math.round((self.y - GRID_START_Y) / CELL_SIZE); // Clamp to grid bounds targetX = Math.max(0, Math.min(GRID_SIZE - 1, targetX)); targetY = Math.max(0, Math.min(GRID_SIZE - 1, targetY)); // If position changed, try to swap if (targetX !== self.gridX || targetY !== self.gridY) { var targetCandy = grid[targetX][targetY]; if (targetCandy && targetCandy !== self) { // Store original positions var originalSelfX = self.gridX; var originalSelfY = self.gridY; var originalTargetX = targetCandy.gridX; var originalTargetY = targetCandy.gridY; // Temporarily swap candies in grid to check for matches grid[self.gridX][self.gridY] = targetCandy; grid[targetX][targetY] = self; var tempGridX = self.gridX; var tempGridY = self.gridY; self.gridX = targetX; self.gridY = targetY; targetCandy.gridX = tempGridX; targetCandy.gridY = tempGridY; // Check if this swap creates any matches var selfMatches = findMatchesAt(self.gridX, self.gridY, self.candyType); var targetMatches = findMatchesAt(targetCandy.gridX, targetCandy.gridY, targetCandy.candyType); if (selfMatches.length >= 3 || targetMatches.length >= 3) { // Valid move - animate both candies to their new positions var targetX1 = GRID_START_X + self.gridX * CELL_SIZE; var targetY1 = GRID_START_Y + self.gridY * CELL_SIZE; var targetX2 = GRID_START_X + targetCandy.gridX * CELL_SIZE; var targetY2 = GRID_START_Y + targetCandy.gridY * CELL_SIZE; self.animateToPosition(targetX1, targetY1, function () { checkForMatches(); }); targetCandy.animateToPosition(targetX2, targetY2); } else { // Invalid move - revert grid positions and return both candies to original positions self.gridX = originalSelfX; self.gridY = originalSelfY; targetCandy.gridX = originalTargetX; targetCandy.gridY = originalTargetY; grid[originalSelfX][originalSelfY] = self; grid[originalTargetX][originalTargetY] = targetCandy; // Return both candies to original positions tween(self, { x: GRID_START_X + self.gridX * CELL_SIZE, y: GRID_START_Y + self.gridY * CELL_SIZE }, { duration: 300, easing: tween.easeOut }); tween(targetCandy, { x: GRID_START_X + targetCandy.gridX * CELL_SIZE, y: GRID_START_Y + targetCandy.gridY * CELL_SIZE }, { duration: 300, easing: tween.easeOut }); } } else { // Return to original position tween(self, { x: GRID_START_X + self.gridX * CELL_SIZE, y: GRID_START_Y + self.gridY * CELL_SIZE }, { duration: 300, easing: tween.easeOut }); } } else { // Return to original position tween(self, { x: GRID_START_X + self.gridX * CELL_SIZE, y: GRID_START_Y + self.gridY * CELL_SIZE }, { duration: 300, easing: tween.easeOut }); } self.scaleX = 1; self.scaleY = 1; selectedCandy = null; } else if (selectedCandy === self) { self.scaleX = 1; self.scaleY = 1; selectedCandy = null; } else if (selectedCandy && isAdjacent(selectedCandy, self)) { attemptSwap(selectedCandy, self); selectedCandy.scaleX = 1; selectedCandy.scaleY = 1; selectedCandy = null; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game(); /**** * Game Code ****/ // Bright Red // Bright Green // Bright Blue // Bright Yellow // Bright Magenta // Bright Cyan var GRID_SIZE = 12; var CELL_SIZE = 140; var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2; var GRID_START_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2; var CANDY_TYPES = 6; var grid = []; var selectedCandy = null; var gameState = 'playing'; var score = 0; var moves = 30; var targetScore = 1000; // Add score display var scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 100; function initializeGrid() { grid = []; for (var x = 0; x < GRID_SIZE; x++) { grid[x] = []; for (var y = 0; y < GRID_SIZE; y++) { var candyType = Math.floor(Math.random() * CANDY_TYPES) + 1; var candy = new Candy(candyType); candy.setGridPosition(x, y); grid[x][y] = candy; game.addChild(candy); } } // Remove initial matches removeInitialMatches(); } function removeInitialMatches() { var hasMatches = true; var iterations = 0; while (hasMatches && iterations < 10) { hasMatches = false; for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (wouldCreateMatch(x, y, grid[x][y].candyType)) { var newType = Math.floor(Math.random() * CANDY_TYPES) + 1; grid[x][y].destroy(); var candy = new Candy(newType); candy.setGridPosition(x, y); grid[x][y] = candy; game.addChild(candy); hasMatches = true; } } } iterations++; } } function wouldCreateMatch(x, y, type) { // Check horizontal matches var horizontalCount = 1; var left = x - 1; while (left >= 0 && grid[left][y] && grid[left][y].candyType === type) { horizontalCount++; left--; } var right = x + 1; while (right < GRID_SIZE && grid[right][y] && grid[right][y].candyType === type) { horizontalCount++; right++; } // Check vertical matches var verticalCount = 1; var up = y - 1; while (up >= 0 && grid[x][up] && grid[x][up].candyType === type) { verticalCount++; up--; } var down = y + 1; while (down < GRID_SIZE && grid[x][down] && grid[x][down].candyType === type) { verticalCount++; down++; } return horizontalCount >= 3 || verticalCount >= 3; } function isAdjacent(candy1, candy2) { var dx = Math.abs(candy1.gridX - candy2.gridX); var dy = Math.abs(candy1.gridY - candy2.gridY); return dx === 1 && dy === 0 || dx === 0 && dy === 1; } function attemptSwap(candy1, candy2) { if (moves <= 0) return; // Temporarily swap positions var tempX = candy1.gridX; var tempY = candy1.gridY; candy1.gridX = candy2.gridX; candy1.gridY = candy2.gridY; candy2.gridX = tempX; candy2.gridY = tempY; grid[candy1.gridX][candy1.gridY] = candy1; grid[candy2.gridX][candy2.gridY] = candy2; // Check if this creates matches var matches1 = findMatches(candy1.gridX, candy1.gridY); var matches2 = findMatches(candy2.gridX, candy2.gridY); if (matches1.length > 0 || matches2.length > 0) { // Valid swap - animate moves--; // Moves text removed var targetX1 = GRID_START_X + candy1.gridX * CELL_SIZE; var targetY1 = GRID_START_Y + candy1.gridY * CELL_SIZE; var targetX2 = GRID_START_X + candy2.gridX * CELL_SIZE; var targetY2 = GRID_START_Y + candy2.gridY * CELL_SIZE; candy1.animateToPosition(targetX1, targetY1); candy2.animateToPosition(targetX2, targetY2, function () { LK.getSound('swap').play(); processMatches(); }); } else { // Invalid swap - revert candy1.gridX = tempX; candy1.gridY = tempY; candy2.gridX = candy2.gridX; candy2.gridY = candy2.gridY; grid[candy1.gridX][candy1.gridY] = candy1; grid[candy2.gridX][candy2.gridY] = candy2; } } function findMatches(x, y) { var matches = []; var candy = grid[x][y]; if (!candy) return matches; var type = candy.candyType; // Check horizontal matches var horizontal = [candy]; var left = x - 1; while (left >= 0 && grid[left][y] && grid[left][y].candyType === type) { horizontal.unshift(grid[left][y]); left--; } var right = x + 1; while (right < GRID_SIZE && grid[right][y] && grid[right][y].candyType === type) { horizontal.push(grid[right][y]); right++; } if (horizontal.length >= 3) { matches = matches.concat(horizontal); } // Check vertical matches var vertical = [candy]; var up = y - 1; while (up >= 0 && grid[x][up] && grid[x][up].candyType === type) { vertical.unshift(grid[x][up]); up--; } var down = y + 1; while (down < GRID_SIZE && grid[x][down] && grid[x][down].candyType === type) { vertical.push(grid[x][down]); down++; } if (vertical.length >= 3) { matches = matches.concat(vertical); } return matches; } function processMatches() { var allMatches = []; var specialCandyPositions = []; var processedCandies = []; // Find all matches on the grid for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] && !grid[x][y].isMatched) { // Check horizontal matches (3+ in a row) var horizontalMatches = []; var currentType = grid[x][y].candyType; var startX = x; // Find consecutive candies of same type horizontally while (startX < GRID_SIZE && grid[startX][y] && grid[startX][y].candyType === currentType) { horizontalMatches.push(grid[startX][y]); startX++; } // If we found 4 or more consecutive horizontal matches, mark for special candy if (horizontalMatches.length >= 4) { // Create special candy at the center of the match var centerX = Math.floor(x + (horizontalMatches.length - 1) / 2); specialCandyPositions.push({ x: centerX, y: y, type: currentType }); } // If we found 3 or more consecutive horizontal matches if (horizontalMatches.length >= 3) { for (var i = 0; i < horizontalMatches.length; i++) { if (allMatches.indexOf(horizontalMatches[i]) === -1) { allMatches.push(horizontalMatches[i]); } } } // Check vertical matches (3+ in a column) var verticalMatches = []; var startY = y; // Find consecutive candies of same type vertically while (startY < GRID_SIZE && grid[x][startY] && grid[x][startY].candyType === currentType) { verticalMatches.push(grid[x][startY]); startY++; } // If we found 4 or more consecutive vertical matches, mark for special candy if (verticalMatches.length >= 4) { // Create special candy at the center of the match var centerY = Math.floor(y + (verticalMatches.length - 1) / 2); specialCandyPositions.push({ x: x, y: centerY, type: currentType }); } // If we found 3 or more consecutive vertical matches if (verticalMatches.length >= 3) { for (var i = 0; i < verticalMatches.length; i++) { if (allMatches.indexOf(verticalMatches[i]) === -1) { allMatches.push(verticalMatches[i]); } } } } } } if (allMatches.length > 0) { // Mark matches for destruction and update score for (var i = 0; i < allMatches.length; i++) { var candy = allMatches[i]; if (!candy.isSpecial) { candy.markForDestroy(); grid[candy.gridX][candy.gridY] = null; score += 10; } } // Create only one special candy from the first valid position if (specialCandyPositions.length > 0) { var pos = specialCandyPositions[0]; // Only use the first position if (grid[pos.x][pos.y] === null) { var specialCandy = new Candy(pos.type, true); specialCandy.setGridPosition(pos.x, pos.y); grid[pos.x][pos.y] = specialCandy; game.addChild(specialCandy); // Add sparkle effect to special candy tween(specialCandy, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(specialCandy, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeIn }); } }); } } scoreText.setText('Score: ' + score); LK.getSound('match').play(); // Drop candies after delay LK.setTimeout(function () { dropCandies(); }, 350); } } function dropCandies() { var hasDropped = false; // Drop existing candies 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].gridX = x; grid[x][writeIndex].gridY = writeIndex; var targetX = GRID_START_X + x * CELL_SIZE; var targetY = GRID_START_Y + writeIndex * CELL_SIZE; grid[x][writeIndex].animateToPosition(targetX, targetY); hasDropped = true; } writeIndex--; } } // Fill empty spaces with new candies for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] === null) { var candyType = Math.floor(Math.random() * CANDY_TYPES) + 1; var candy = new Candy(candyType); candy.gridX = x; candy.gridY = y; candy.x = GRID_START_X + x * CELL_SIZE; candy.y = GRID_START_Y - (GRID_SIZE - y) * CELL_SIZE; var targetY = GRID_START_Y + y * CELL_SIZE; candy.animateToPosition(candy.x, targetY); grid[x][y] = candy; game.addChild(candy); hasDropped = true; } } } if (hasDropped) { LK.setTimeout(function () { processMatches(); }, 250); } else { checkGameState(); } } function checkForMatches() { var allMatches = []; var specialCandyPositions = []; // Check all positions for matches for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] && !grid[x][y].isMatched) { var candy = grid[x][y]; var matches = findMatchesAt(x, y, candy.candyType); // Check if this creates a 4-in-a-row for special candy if (matches.length >= 4) { // Check if it's horizontal or vertical match var isHorizontal = false; var isVertical = false; for (var i = 1; i < matches.length; i++) { if (matches[i].gridY === matches[0].gridY) isHorizontal = true; if (matches[i].gridX === matches[0].gridX) isVertical = true; } if (isHorizontal || isVertical) { specialCandyPositions.push({ x: x, y: y, type: candy.candyType }); } } // Add unique matches to allMatches for (var i = 0; i < matches.length; i++) { if (allMatches.indexOf(matches[i]) === -1) { allMatches.push(matches[i]); } } } } } if (allMatches.length > 0) { // Mark matches for destruction and update score for (var i = 0; i < allMatches.length; i++) { var candy = allMatches[i]; if (!candy.isSpecial) { candy.markForDestroy(); grid[candy.gridX][candy.gridY] = null; score += 10; } } // Create only one special candy from the first valid position if (specialCandyPositions.length > 0) { var pos = specialCandyPositions[0]; // Only use the first position if (grid[pos.x][pos.y] === null) { var specialCandy = new Candy(pos.type, true); specialCandy.setGridPosition(pos.x, pos.y); grid[pos.x][pos.y] = specialCandy; game.addChild(specialCandy); // Add sparkle effect to special candy tween(specialCandy, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(specialCandy, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeIn }); } }); } } scoreText.setText('Score: ' + score); LK.getSound('match').play(); // Drop candies after delay LK.setTimeout(function () { dropCandies(); }, 350); } } function findMatchesAt(x, y, candyType) { var matches = []; // Check horizontal matches (3+ in a row) var horizontalMatches = [grid[x][y]]; // Check left var left = x - 1; while (left >= 0 && grid[left][y] && grid[left][y].candyType === candyType && !grid[left][y].isMatched) { horizontalMatches.unshift(grid[left][y]); left--; } // Check right var right = x + 1; while (right < GRID_SIZE && grid[right][y] && grid[right][y].candyType === candyType && !grid[right][y].isMatched) { horizontalMatches.push(grid[right][y]); right++; } if (horizontalMatches.length >= 3) { matches = matches.concat(horizontalMatches); } // Check vertical matches (3+ in a column) var verticalMatches = [grid[x][y]]; // Check up var up = y - 1; while (up >= 0 && grid[x][up] && grid[x][up].candyType === candyType && !grid[x][up].isMatched) { verticalMatches.unshift(grid[x][up]); up--; } // Check down var down = y + 1; while (down < GRID_SIZE && grid[x][down] && grid[x][down].candyType === candyType && !grid[x][down].isMatched) { verticalMatches.push(grid[x][down]); down++; } if (verticalMatches.length >= 3) { // Remove duplicates if candy is part of both horizontal and vertical match for (var i = 0; i < verticalMatches.length; i++) { if (matches.indexOf(verticalMatches[i]) === -1) { matches.push(verticalMatches[i]); } } } return matches; } function checkGameState() { if (score >= targetScore) { gameState = 'won'; LK.showYouWin(); } else if (moves <= 0) { gameState = 'lost'; LK.showGameOver(); } } // Initialize the game initializeGrid(); game.update = function () { // Game loop updates handled by individual object updates };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Candy = Container.expand(function (type, isSpecial) {
var self = Container.call(this);
self.candyType = type;
self.isSpecial = isSpecial || false;
self.gridX = -1;
self.gridY = -1;
self.isMatched = false;
self.isMoving = false;
self.isDragging = false;
// Background removed - only candy graphics remain
var candyGraphic;
if (self.isSpecial) {
candyGraphic = self.attachAsset('specialCandy', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
candyGraphic = self.attachAsset('candy' + type, {
anchorX: 0.5,
anchorY: 0.5
});
}
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE;
self.y = GRID_START_Y + gridY * CELL_SIZE;
};
self.animateToPosition = function (targetX, targetY, onComplete) {
self.isMoving = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
if (onComplete) onComplete();
}
});
};
self.markForDestroy = function () {
self.isMatched = true;
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
};
self.down = function (x, y, obj) {
if (gameState !== 'playing' || self.isMoving) return;
if (self.isSpecial) {
// Special candy clicked - clear 2x2 area around it
var centerX = self.gridX;
var centerY = self.gridY;
var candiesDestroyed = 0;
// Clear 2x2 area around the special candy (including the special candy itself)
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
var targetX = centerX + dx;
var targetY = centerY + dy;
if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
var targetCandy = grid[targetX][targetY];
if (targetCandy && !targetCandy.isMatched && !targetCandy.isSpecial) {
targetCandy.markForDestroy();
grid[targetX][targetY] = null;
candiesDestroyed++;
score += 15; // Bonus points for special candy destruction
}
}
}
}
scoreText.setText('Score: ' + score);
LK.getSound('match').play();
// Drop candies after delay
LK.setTimeout(function () {
dropCandies();
}, 350);
return; // Exit early for special candies
}
selectedCandy = self;
self.scaleX = 1.1;
self.scaleY = 1.1;
self.isDragging = true;
self.dragStartX = x;
self.dragStartY = y;
self.startX = self.x;
self.startY = self.y;
};
self.move = function (x, y, obj) {
if (self.isDragging && gameState === 'playing' && !self.isMoving) {
var deltaX = x - self.dragStartX;
var deltaY = y - self.dragStartY;
// Determine which direction has the larger movement
var absDeltaX = Math.abs(deltaX);
var absDeltaY = Math.abs(deltaY);
var targetX = self.startX;
var targetY = self.startY;
// Only move in the direction with the larger delta, and limit to one cell
if (absDeltaX > absDeltaY) {
// Horizontal movement
if (deltaX > CELL_SIZE / 2 && self.gridX < GRID_SIZE - 1) {
targetX = self.startX + CELL_SIZE;
} else if (deltaX < -CELL_SIZE / 2 && self.gridX > 0) {
targetX = self.startX - CELL_SIZE;
}
} else {
// Vertical movement
if (deltaY > CELL_SIZE / 2 && self.gridY < GRID_SIZE - 1) {
targetY = self.startY + CELL_SIZE;
} else if (deltaY < -CELL_SIZE / 2 && self.gridY > 0) {
targetY = self.startY - CELL_SIZE;
}
}
self.x = targetX;
self.y = targetY;
}
};
self.up = function (x, y, obj) {
if (gameState !== 'playing' || self.isMoving) return;
if (self.isDragging) {
self.isDragging = false;
// Find target grid position based on current visual position
var targetX = Math.round((self.x - GRID_START_X) / CELL_SIZE);
var targetY = Math.round((self.y - GRID_START_Y) / CELL_SIZE);
// Clamp to grid bounds
targetX = Math.max(0, Math.min(GRID_SIZE - 1, targetX));
targetY = Math.max(0, Math.min(GRID_SIZE - 1, targetY));
// If position changed, try to swap
if (targetX !== self.gridX || targetY !== self.gridY) {
var targetCandy = grid[targetX][targetY];
if (targetCandy && targetCandy !== self) {
// Store original positions
var originalSelfX = self.gridX;
var originalSelfY = self.gridY;
var originalTargetX = targetCandy.gridX;
var originalTargetY = targetCandy.gridY;
// Temporarily swap candies in grid to check for matches
grid[self.gridX][self.gridY] = targetCandy;
grid[targetX][targetY] = self;
var tempGridX = self.gridX;
var tempGridY = self.gridY;
self.gridX = targetX;
self.gridY = targetY;
targetCandy.gridX = tempGridX;
targetCandy.gridY = tempGridY;
// Check if this swap creates any matches
var selfMatches = findMatchesAt(self.gridX, self.gridY, self.candyType);
var targetMatches = findMatchesAt(targetCandy.gridX, targetCandy.gridY, targetCandy.candyType);
if (selfMatches.length >= 3 || targetMatches.length >= 3) {
// Valid move - animate both candies to their new positions
var targetX1 = GRID_START_X + self.gridX * CELL_SIZE;
var targetY1 = GRID_START_Y + self.gridY * CELL_SIZE;
var targetX2 = GRID_START_X + targetCandy.gridX * CELL_SIZE;
var targetY2 = GRID_START_Y + targetCandy.gridY * CELL_SIZE;
self.animateToPosition(targetX1, targetY1, function () {
checkForMatches();
});
targetCandy.animateToPosition(targetX2, targetY2);
} else {
// Invalid move - revert grid positions and return both candies to original positions
self.gridX = originalSelfX;
self.gridY = originalSelfY;
targetCandy.gridX = originalTargetX;
targetCandy.gridY = originalTargetY;
grid[originalSelfX][originalSelfY] = self;
grid[originalTargetX][originalTargetY] = targetCandy;
// Return both candies to original positions
tween(self, {
x: GRID_START_X + self.gridX * CELL_SIZE,
y: GRID_START_Y + self.gridY * CELL_SIZE
}, {
duration: 300,
easing: tween.easeOut
});
tween(targetCandy, {
x: GRID_START_X + targetCandy.gridX * CELL_SIZE,
y: GRID_START_Y + targetCandy.gridY * CELL_SIZE
}, {
duration: 300,
easing: tween.easeOut
});
}
} else {
// Return to original position
tween(self, {
x: GRID_START_X + self.gridX * CELL_SIZE,
y: GRID_START_Y + self.gridY * CELL_SIZE
}, {
duration: 300,
easing: tween.easeOut
});
}
} else {
// Return to original position
tween(self, {
x: GRID_START_X + self.gridX * CELL_SIZE,
y: GRID_START_Y + self.gridY * CELL_SIZE
}, {
duration: 300,
easing: tween.easeOut
});
}
self.scaleX = 1;
self.scaleY = 1;
selectedCandy = null;
} else if (selectedCandy === self) {
self.scaleX = 1;
self.scaleY = 1;
selectedCandy = null;
} else if (selectedCandy && isAdjacent(selectedCandy, self)) {
attemptSwap(selectedCandy, self);
selectedCandy.scaleX = 1;
selectedCandy.scaleY = 1;
selectedCandy = null;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game();
/****
* Game Code
****/
// Bright Red
// Bright Green
// Bright Blue
// Bright Yellow
// Bright Magenta
// Bright Cyan
var GRID_SIZE = 12;
var CELL_SIZE = 140;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2;
var CANDY_TYPES = 6;
var grid = [];
var selectedCandy = null;
var gameState = 'playing';
var score = 0;
var moves = 30;
var targetScore = 1000;
// Add score display
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 100;
function initializeGrid() {
grid = [];
for (var x = 0; x < GRID_SIZE; x++) {
grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
var candyType = Math.floor(Math.random() * CANDY_TYPES) + 1;
var candy = new Candy(candyType);
candy.setGridPosition(x, y);
grid[x][y] = candy;
game.addChild(candy);
}
}
// Remove initial matches
removeInitialMatches();
}
function removeInitialMatches() {
var hasMatches = true;
var iterations = 0;
while (hasMatches && iterations < 10) {
hasMatches = false;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (wouldCreateMatch(x, y, grid[x][y].candyType)) {
var newType = Math.floor(Math.random() * CANDY_TYPES) + 1;
grid[x][y].destroy();
var candy = new Candy(newType);
candy.setGridPosition(x, y);
grid[x][y] = candy;
game.addChild(candy);
hasMatches = true;
}
}
}
iterations++;
}
}
function wouldCreateMatch(x, y, type) {
// Check horizontal matches
var horizontalCount = 1;
var left = x - 1;
while (left >= 0 && grid[left][y] && grid[left][y].candyType === type) {
horizontalCount++;
left--;
}
var right = x + 1;
while (right < GRID_SIZE && grid[right][y] && grid[right][y].candyType === type) {
horizontalCount++;
right++;
}
// Check vertical matches
var verticalCount = 1;
var up = y - 1;
while (up >= 0 && grid[x][up] && grid[x][up].candyType === type) {
verticalCount++;
up--;
}
var down = y + 1;
while (down < GRID_SIZE && grid[x][down] && grid[x][down].candyType === type) {
verticalCount++;
down++;
}
return horizontalCount >= 3 || verticalCount >= 3;
}
function isAdjacent(candy1, candy2) {
var dx = Math.abs(candy1.gridX - candy2.gridX);
var dy = Math.abs(candy1.gridY - candy2.gridY);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
function attemptSwap(candy1, candy2) {
if (moves <= 0) return;
// Temporarily swap positions
var tempX = candy1.gridX;
var tempY = candy1.gridY;
candy1.gridX = candy2.gridX;
candy1.gridY = candy2.gridY;
candy2.gridX = tempX;
candy2.gridY = tempY;
grid[candy1.gridX][candy1.gridY] = candy1;
grid[candy2.gridX][candy2.gridY] = candy2;
// Check if this creates matches
var matches1 = findMatches(candy1.gridX, candy1.gridY);
var matches2 = findMatches(candy2.gridX, candy2.gridY);
if (matches1.length > 0 || matches2.length > 0) {
// Valid swap - animate
moves--;
// Moves text removed
var targetX1 = GRID_START_X + candy1.gridX * CELL_SIZE;
var targetY1 = GRID_START_Y + candy1.gridY * CELL_SIZE;
var targetX2 = GRID_START_X + candy2.gridX * CELL_SIZE;
var targetY2 = GRID_START_Y + candy2.gridY * CELL_SIZE;
candy1.animateToPosition(targetX1, targetY1);
candy2.animateToPosition(targetX2, targetY2, function () {
LK.getSound('swap').play();
processMatches();
});
} else {
// Invalid swap - revert
candy1.gridX = tempX;
candy1.gridY = tempY;
candy2.gridX = candy2.gridX;
candy2.gridY = candy2.gridY;
grid[candy1.gridX][candy1.gridY] = candy1;
grid[candy2.gridX][candy2.gridY] = candy2;
}
}
function findMatches(x, y) {
var matches = [];
var candy = grid[x][y];
if (!candy) return matches;
var type = candy.candyType;
// Check horizontal matches
var horizontal = [candy];
var left = x - 1;
while (left >= 0 && grid[left][y] && grid[left][y].candyType === type) {
horizontal.unshift(grid[left][y]);
left--;
}
var right = x + 1;
while (right < GRID_SIZE && grid[right][y] && grid[right][y].candyType === type) {
horizontal.push(grid[right][y]);
right++;
}
if (horizontal.length >= 3) {
matches = matches.concat(horizontal);
}
// Check vertical matches
var vertical = [candy];
var up = y - 1;
while (up >= 0 && grid[x][up] && grid[x][up].candyType === type) {
vertical.unshift(grid[x][up]);
up--;
}
var down = y + 1;
while (down < GRID_SIZE && grid[x][down] && grid[x][down].candyType === type) {
vertical.push(grid[x][down]);
down++;
}
if (vertical.length >= 3) {
matches = matches.concat(vertical);
}
return matches;
}
function processMatches() {
var allMatches = [];
var specialCandyPositions = [];
var processedCandies = [];
// Find all matches on the grid
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && !grid[x][y].isMatched) {
// Check horizontal matches (3+ in a row)
var horizontalMatches = [];
var currentType = grid[x][y].candyType;
var startX = x;
// Find consecutive candies of same type horizontally
while (startX < GRID_SIZE && grid[startX][y] && grid[startX][y].candyType === currentType) {
horizontalMatches.push(grid[startX][y]);
startX++;
}
// If we found 4 or more consecutive horizontal matches, mark for special candy
if (horizontalMatches.length >= 4) {
// Create special candy at the center of the match
var centerX = Math.floor(x + (horizontalMatches.length - 1) / 2);
specialCandyPositions.push({
x: centerX,
y: y,
type: currentType
});
}
// If we found 3 or more consecutive horizontal matches
if (horizontalMatches.length >= 3) {
for (var i = 0; i < horizontalMatches.length; i++) {
if (allMatches.indexOf(horizontalMatches[i]) === -1) {
allMatches.push(horizontalMatches[i]);
}
}
}
// Check vertical matches (3+ in a column)
var verticalMatches = [];
var startY = y;
// Find consecutive candies of same type vertically
while (startY < GRID_SIZE && grid[x][startY] && grid[x][startY].candyType === currentType) {
verticalMatches.push(grid[x][startY]);
startY++;
}
// If we found 4 or more consecutive vertical matches, mark for special candy
if (verticalMatches.length >= 4) {
// Create special candy at the center of the match
var centerY = Math.floor(y + (verticalMatches.length - 1) / 2);
specialCandyPositions.push({
x: x,
y: centerY,
type: currentType
});
}
// If we found 3 or more consecutive vertical matches
if (verticalMatches.length >= 3) {
for (var i = 0; i < verticalMatches.length; i++) {
if (allMatches.indexOf(verticalMatches[i]) === -1) {
allMatches.push(verticalMatches[i]);
}
}
}
}
}
}
if (allMatches.length > 0) {
// Mark matches for destruction and update score
for (var i = 0; i < allMatches.length; i++) {
var candy = allMatches[i];
if (!candy.isSpecial) {
candy.markForDestroy();
grid[candy.gridX][candy.gridY] = null;
score += 10;
}
}
// Create only one special candy from the first valid position
if (specialCandyPositions.length > 0) {
var pos = specialCandyPositions[0]; // Only use the first position
if (grid[pos.x][pos.y] === null) {
var specialCandy = new Candy(pos.type, true);
specialCandy.setGridPosition(pos.x, pos.y);
grid[pos.x][pos.y] = specialCandy;
game.addChild(specialCandy);
// Add sparkle effect to special candy
tween(specialCandy, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(specialCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
scoreText.setText('Score: ' + score);
LK.getSound('match').play();
// Drop candies after delay
LK.setTimeout(function () {
dropCandies();
}, 350);
}
}
function dropCandies() {
var hasDropped = false;
// Drop existing candies
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].gridX = x;
grid[x][writeIndex].gridY = writeIndex;
var targetX = GRID_START_X + x * CELL_SIZE;
var targetY = GRID_START_Y + writeIndex * CELL_SIZE;
grid[x][writeIndex].animateToPosition(targetX, targetY);
hasDropped = true;
}
writeIndex--;
}
}
// Fill empty spaces with new candies
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] === null) {
var candyType = Math.floor(Math.random() * CANDY_TYPES) + 1;
var candy = new Candy(candyType);
candy.gridX = x;
candy.gridY = y;
candy.x = GRID_START_X + x * CELL_SIZE;
candy.y = GRID_START_Y - (GRID_SIZE - y) * CELL_SIZE;
var targetY = GRID_START_Y + y * CELL_SIZE;
candy.animateToPosition(candy.x, targetY);
grid[x][y] = candy;
game.addChild(candy);
hasDropped = true;
}
}
}
if (hasDropped) {
LK.setTimeout(function () {
processMatches();
}, 250);
} else {
checkGameState();
}
}
function checkForMatches() {
var allMatches = [];
var specialCandyPositions = [];
// Check all positions for matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && !grid[x][y].isMatched) {
var candy = grid[x][y];
var matches = findMatchesAt(x, y, candy.candyType);
// Check if this creates a 4-in-a-row for special candy
if (matches.length >= 4) {
// Check if it's horizontal or vertical match
var isHorizontal = false;
var isVertical = false;
for (var i = 1; i < matches.length; i++) {
if (matches[i].gridY === matches[0].gridY) isHorizontal = true;
if (matches[i].gridX === matches[0].gridX) isVertical = true;
}
if (isHorizontal || isVertical) {
specialCandyPositions.push({
x: x,
y: y,
type: candy.candyType
});
}
}
// Add unique matches to allMatches
for (var i = 0; i < matches.length; i++) {
if (allMatches.indexOf(matches[i]) === -1) {
allMatches.push(matches[i]);
}
}
}
}
}
if (allMatches.length > 0) {
// Mark matches for destruction and update score
for (var i = 0; i < allMatches.length; i++) {
var candy = allMatches[i];
if (!candy.isSpecial) {
candy.markForDestroy();
grid[candy.gridX][candy.gridY] = null;
score += 10;
}
}
// Create only one special candy from the first valid position
if (specialCandyPositions.length > 0) {
var pos = specialCandyPositions[0]; // Only use the first position
if (grid[pos.x][pos.y] === null) {
var specialCandy = new Candy(pos.type, true);
specialCandy.setGridPosition(pos.x, pos.y);
grid[pos.x][pos.y] = specialCandy;
game.addChild(specialCandy);
// Add sparkle effect to special candy
tween(specialCandy, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(specialCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
scoreText.setText('Score: ' + score);
LK.getSound('match').play();
// Drop candies after delay
LK.setTimeout(function () {
dropCandies();
}, 350);
}
}
function findMatchesAt(x, y, candyType) {
var matches = [];
// Check horizontal matches (3+ in a row)
var horizontalMatches = [grid[x][y]];
// Check left
var left = x - 1;
while (left >= 0 && grid[left][y] && grid[left][y].candyType === candyType && !grid[left][y].isMatched) {
horizontalMatches.unshift(grid[left][y]);
left--;
}
// Check right
var right = x + 1;
while (right < GRID_SIZE && grid[right][y] && grid[right][y].candyType === candyType && !grid[right][y].isMatched) {
horizontalMatches.push(grid[right][y]);
right++;
}
if (horizontalMatches.length >= 3) {
matches = matches.concat(horizontalMatches);
}
// Check vertical matches (3+ in a column)
var verticalMatches = [grid[x][y]];
// Check up
var up = y - 1;
while (up >= 0 && grid[x][up] && grid[x][up].candyType === candyType && !grid[x][up].isMatched) {
verticalMatches.unshift(grid[x][up]);
up--;
}
// Check down
var down = y + 1;
while (down < GRID_SIZE && grid[x][down] && grid[x][down].candyType === candyType && !grid[x][down].isMatched) {
verticalMatches.push(grid[x][down]);
down++;
}
if (verticalMatches.length >= 3) {
// Remove duplicates if candy is part of both horizontal and vertical match
for (var i = 0; i < verticalMatches.length; i++) {
if (matches.indexOf(verticalMatches[i]) === -1) {
matches.push(verticalMatches[i]);
}
}
}
return matches;
}
function checkGameState() {
if (score >= targetScore) {
gameState = 'won';
LK.showYouWin();
} else if (moves <= 0) {
gameState = 'lost';
LK.showGameOver();
}
}
// Initialize the game
initializeGrid();
game.update = function () {
// Game loop updates handled by individual object updates
};
Kırmızı 3d top. In-Game asset. 2d. High contrast. No shadows
Yeşil 3d top. In-Game asset. 2d. High contrast. No shadows
Mavi 3d yuvarlak top. In-Game asset. 2d. High contrast. No shadows
Sarı 2d top. In-Game asset. 2d. High contrast. No shadows
3d pembe daire. In-Game asset. 2d. High contrast. No shadows
Beyaz 3d daire. In-Game asset. 2d. High contrast. No shadows
Şeker. In-Game asset. 2d. High contrast. No shadows