User prompt
Şekerler birlediginde ses ciksin
User prompt
Şekerler birlestiginde toplam puan gözüksün
User prompt
Toplam puan ekle
User prompt
Toplam puan ekle
User prompt
Şekerler birleştiğinde ses olsun
User prompt
Şeker ler patlayınca ses olsun
User prompt
Skor ekle
User prompt
Özel şekerler ekle
User prompt
Skor tahtası ekle
User prompt
Puan sistemi ekle
User prompt
Please fix the bug: 'ReferenceError: candy is not defined' in or related to this line: 'board[candy.row][candy.col] = null;' Line Number: 302
Code edit (1 edits merged)
Please save this source code
User prompt
Candy Match Mania
Initial prompt
Bana candy crush benzeri oyun yap
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
level: 1,
bestScore: 0
});
/****
* Classes
****/
// Candy class
var Candy = Container.expand(function () {
var self = Container.call(this);
// Properties
self.type = null; // 0-5 for normal, 6 for striped
self.row = 0;
self.col = 0;
self.isSpecial = false;
// Attach asset
self.setType = function (type, isSpecial) {
self.type = type;
self.isSpecial = !!isSpecial;
self.removeChildren();
var assetId;
if (isSpecial) {
assetId = 'candyStriped';
} else {
assetId = ['candyRed', 'candyGreen', 'candyBlue', 'candyYellow', 'candyPurple', 'candyOrange'][type];
}
var candyGfx = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// For striped, tint to match base color
if (isSpecial) {
var tints = [0xff4b5c, 0x4be04b, 0x4b7bff, 0xffe14b, 0xb44bff, 0xffa14b];
candyGfx.tint = tints[type];
}
};
// Animate pop
self.pop = function (_onFinish) {
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 0
}, {
duration: 220,
easing: tween.easeIn,
onFinish: function onFinish() {
if (_onFinish) _onFinish();
}
});
};
// Animate drop
self.dropTo = function (newY, onFinish) {
tween(self, {
y: newY
}, {
duration: 220,
easing: tween.bounceOut,
onFinish: onFinish
});
};
// Animate swap
self.swapTo = function (newX, newY, onFinish) {
tween(self, {
x: newX,
y: newY
}, {
duration: 180,
easing: tween.cubicInOut,
onFinish: onFinish
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181828
});
/****
* Game Code
****/
// Music
// Sound effects
// Board background
// Special candy (striped)
// Candy shapes/colors (6 types)
// Board config
var BOARD_SIZE = 8;
var CELL_SIZE = 200;
var BOARD_OFFSET_X = (2048 - BOARD_SIZE * CELL_SIZE) / 2;
var BOARD_OFFSET_Y = 320;
var CANDY_TYPES = 6;
var MOVES_PER_LEVEL = 20;
var TARGET_SCORE_BASE = 1200;
// State
var board = []; // 2D array [row][col] of Candy
var selectedCandy = null;
var swappingCandy = null;
var isAnimating = false;
var movesLeft = MOVES_PER_LEVEL;
var score = 0;
var targetScore = TARGET_SCORE_BASE + (storage.level - 1) * 400;
var level = storage.level || 1;
// GUI
var scoreTxt = new Text2('Score: 0', {
size: 90,
fill: '#fff'
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 30;
scoreTxt.x = 2048 / 2;
var movesTxt = new Text2('Moves: ' + MOVES_PER_LEVEL, {
size: 70,
fill: '#fff'
});
movesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(movesTxt);
movesTxt.y = 140;
movesTxt.x = 2048 / 2;
var targetTxt = new Text2('Target: ' + targetScore, {
size: 60,
fill: '#fff'
});
targetTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(targetTxt);
targetTxt.y = 220;
targetTxt.x = 2048 / 2;
// Board background
var boardBg = LK.getAsset('boardBg', {
anchorX: 0,
anchorY: 0
});
boardBg.x = BOARD_OFFSET_X - 10;
boardBg.y = BOARD_OFFSET_Y - 10;
game.addChild(boardBg);
// Helper: get candy at board position
function getCandy(row, col) {
if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) return null;
return board[row][col];
}
// Helper: get board position from x,y
function getBoardPos(x, y) {
var col = Math.floor((x - BOARD_OFFSET_X) / CELL_SIZE);
var row = Math.floor((y - BOARD_OFFSET_Y) / CELL_SIZE);
if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) return null;
return {
row: row,
col: col
};
}
// Helper: get pixel position from board pos
function getPixelPos(row, col) {
return {
x: BOARD_OFFSET_X + col * CELL_SIZE + CELL_SIZE / 2,
y: BOARD_OFFSET_Y + row * CELL_SIZE + CELL_SIZE / 2
};
}
// Helper: random candy type
function randomCandyType() {
return Math.floor(Math.random() * CANDY_TYPES);
}
// Helper: check if two candies are adjacent
function areAdjacent(c1, c2) {
if (!c1 || !c2) return false;
var dr = Math.abs(c1.row - c2.row);
var dc = Math.abs(c1.col - c2.col);
return dr + dc === 1;
}
// Helper: find all matches on board
function findMatches() {
var matches = [];
// Horizontal
for (var r = 0; r < BOARD_SIZE; r++) {
var runType = null,
runStart = 0,
runLen = 0;
for (var c = 0; c <= BOARD_SIZE; c++) {
var candy = c < BOARD_SIZE ? board[r][c] : null;
var t = candy && !candy.isSpecial ? candy.type : -1;
if (t === runType) {
runLen++;
} else {
if (runLen >= 3 && runType !== null) {
var arr = [];
for (var i = runStart; i < runStart + runLen; i++) arr.push(board[r][i]);
matches.push(arr);
}
runType = t;
runStart = c;
runLen = 1;
}
}
}
// Vertical
for (var c = 0; c < BOARD_SIZE; c++) {
var runType = null,
runStart = 0,
runLen = 0;
for (var r = 0; r <= BOARD_SIZE; r++) {
var candy = r < BOARD_SIZE ? board[r][c] : null;
var t = candy && !candy.isSpecial ? candy.type : -1;
if (t === runType) {
runLen++;
} else {
if (runLen >= 3 && runType !== null) {
var arr = [];
for (var i = runStart; i < runStart + runLen; i++) arr.push(board[i][c]);
matches.push(arr);
}
runType = t;
runStart = r;
runLen = 1;
}
}
}
return matches;
}
// Helper: find special matches (4+)
function findSpecials(matches) {
var specials = [];
for (var i = 0; i < matches.length; i++) {
if (matches[i].length === 4) specials.push({
candies: matches[i],
type: 'striped'
});
// For MVP, only striped for 4-match
}
return specials;
}
// Helper: remove candies in matches, return positions to fill
function removeMatches(matches, specials) {
var toRemove = [];
for (var i = 0; i < matches.length; i++) {
for (var j = 0; j < matches[i].length; j++) {
if (toRemove.indexOf(matches[i][j]) === -1) toRemove.push(matches[i][j]);
}
}
// Mark special candies
for (var i = 0; i < specials.length; i++) {
var arr = specials[i].candies;
var idx = Math.floor(arr.length / 2);
var c = arr[idx];
c.setType(c.type, true);
// Remove all except special
for (var j = 0; j < arr.length; j++) {
if (arr[j] !== c && toRemove.indexOf(arr[j]) === -1) toRemove.push(arr[j]);
}
}
// Animate and remove
var removed = 0;
for (var i = 0; i < toRemove.length; i++) {
(function (candy) {
candy.pop(function () {
game.removeChild(candy);
});
})(toRemove[i]);
// Remove from board
board[candy.row][candy.col] = null;
removed++;
}
return removed;
}
// Helper: drop candies and fill new
function dropAndFill(onFinish) {
// For each column, drop candies down
var maxDrop = 0;
for (var c = 0; c < BOARD_SIZE; c++) {
var empty = 0;
for (var r = BOARD_SIZE - 1; r >= 0; r--) {
var candy = board[r][c];
if (!candy) {
empty++;
} else if (empty > 0) {
board[r + empty][c] = candy;
board[r][c] = null;
var pos = getPixelPos(r + empty, c);
candy.row = r + empty;
candy.col = c;
candy.dropTo(pos.y);
if (empty > maxDrop) maxDrop = empty;
}
}
// Fill new candies at top
for (var e = 0; e < empty; e++) {
var type = randomCandyType();
var newCandy = new Candy();
newCandy.setType(type, false);
newCandy.row = e;
newCandy.col = c;
var pos = getPixelPos(e, c);
newCandy.x = pos.x;
newCandy.y = pos.y - empty * CELL_SIZE;
game.addChild(newCandy);
board[e][c] = newCandy;
newCandy.dropTo(pos.y);
}
}
// Wait for drop animation
LK.setTimeout(onFinish, 240);
}
// Helper: check if board has any matches
function hasAnyMatches() {
var m = findMatches();
return m.length > 0;
}
// Helper: shuffle board if no moves
function shuffleBoard() {
// Simple shuffle: randomize all candies
var candies = [];
for (var r = 0; r < BOARD_SIZE; r++) for (var c = 0; c < BOARD_SIZE; c++) candies.push(board[r][c]);
for (var i = candies.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
// Swap
var trow = candies[i].row,
tcol = candies[i].col;
candies[i].row = candies[j].row;
candies[i].col = candies[j].col;
candies[j].row = trow;
candies[j].col = tcol;
board[candies[i].row][candies[i].col] = candies[i];
board[candies[j].row][candies[j].col] = candies[j];
// Animate
var posI = getPixelPos(candies[i].row, candies[i].col);
var posJ = getPixelPos(candies[j].row, candies[j].col);
candies[i].swapTo(posI.x, posI.y);
candies[j].swapTo(posJ.x, posJ.y);
}
}
// Helper: check if any valid moves exist (MVP: skip, always allow shuffle after 3 failed attempts)
// Initialize board
function initBoard() {
// Remove old candies
for (var r = 0; r < BOARD_SIZE; r++) for (var c = 0; c < BOARD_SIZE; c++) {
if (board[r] && board[r][c]) {
game.removeChild(board[r][c]);
}
}
board = [];
for (var r = 0; r < BOARD_SIZE; r++) {
board[r] = [];
for (var c = 0; c < BOARD_SIZE; c++) {
var type = randomCandyType();
var candy = new Candy();
candy.setType(type, false);
candy.row = r;
candy.col = c;
var pos = getPixelPos(r, c);
candy.x = pos.x;
candy.y = pos.y;
game.addChild(candy);
board[r][c] = candy;
}
}
// Remove initial matches
while (hasAnyMatches()) {
var matches = findMatches();
for (var i = 0; i < matches.length; i++) {
for (var j = 0; j < matches[i].length; j++) {
var c = matches[i][j];
var t;
do {
t = randomCandyType();
} while (t === c.type);
c.setType(t, false);
}
}
}
}
// Start new level
function startLevel() {
movesLeft = MOVES_PER_LEVEL;
score = 0;
level = storage.level || 1;
targetScore = TARGET_SCORE_BASE + (level - 1) * 400;
scoreTxt.setText('Score: 0');
movesTxt.setText('Moves: ' + movesLeft);
targetTxt.setText('Target: ' + targetScore);
selectedCandy = null;
swappingCandy = null;
isAnimating = false;
initBoard();
}
// Handle swap logic
function trySwap(c1, c2) {
if (!c1 || !c2 || isAnimating) return;
if (!areAdjacent(c1, c2)) return;
isAnimating = true;
// Swap in board
var r1 = c1.row,
c1c = c1.col,
r2 = c2.row,
c2c = c2.col;
board[r1][c1c] = c2;
board[r2][c2c] = c1;
c1.row = r2;
c1.col = c2c;
c2.row = r1;
c2.col = c1c;
// Animate
var pos1 = getPixelPos(c1.row, c1.col);
var pos2 = getPixelPos(c2.row, c2.col);
var done = 0;
c1.swapTo(pos1.x, pos1.y, function () {
done++;
if (done === 2) afterSwap();
});
c2.swapTo(pos2.x, pos2.y, function () {
done++;
if (done === 2) afterSwap();
});
LK.getSound('swap').play();
function afterSwap() {
var matches = findMatches();
if (matches.length === 0) {
// No match, swap back
board[r1][c1c] = c1;
board[r2][c2c] = c2;
c1.row = r1;
c1.col = c1c;
c2.row = r2;
c2.col = c2c;
var pos1b = getPixelPos(c1.row, c1.col);
var pos2b = getPixelPos(c2.row, c2.col);
c1.swapTo(pos1b.x, pos1b.y);
c2.swapTo(pos2b.x, pos2b.y, function () {
isAnimating = false;
LK.getSound('noMatch').play();
});
} else {
// Valid match
movesLeft--;
movesTxt.setText('Moves: ' + movesLeft);
resolveMatches(matches);
}
selectedCandy = null;
swappingCandy = null;
}
}
// Resolve matches recursively
function resolveMatches(matches) {
if (!matches || matches.length === 0) {
isAnimating = false;
// Check for win/lose
if (score >= targetScore) {
// Win
storage.level = level + 1;
if (score > storage.bestScore) storage.bestScore = score;
LK.showYouWin();
} else if (movesLeft <= 0) {
// Lose
storage.level = 1;
LK.showGameOver();
}
return;
}
LK.getSound('match').play();
// Special candies
var specials = findSpecials(matches);
// Remove matches
var removed = removeMatches(matches, specials);
// Score
score += removed * 60;
if (score > storage.bestScore) storage.bestScore = score;
scoreTxt.setText('Score: ' + score);
// Drop and fill
dropAndFill(function () {
// Check for new matches
var newMatches = findMatches();
if (newMatches.length > 0) {
// Chain
LK.getSound('special').play();
resolveMatches(newMatches);
} else {
isAnimating = false;
}
});
}
// Touch/drag logic
var dragStart = null;
var dragStartCandy = null;
game.down = function (x, y, obj) {
if (isAnimating) return;
var pos = getBoardPos(x, y);
if (!pos) return;
var candy = getCandy(pos.row, pos.col);
if (!candy) return;
dragStart = {
x: x,
y: y
};
dragStartCandy = candy;
selectedCandy = candy;
// Highlight (scale up)
tween(candy, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100
});
};
game.move = function (x, y, obj) {
if (!dragStart || !dragStartCandy || isAnimating) return;
var dx = x - dragStart.x;
var dy = y - dragStart.y;
if (Math.abs(dx) < 40 && Math.abs(dy) < 40) return;
// Determine direction
var dir = null;
if (Math.abs(dx) > Math.abs(dy)) {
dir = dx > 0 ? 'right' : 'left';
} else {
dir = dy > 0 ? 'down' : 'up';
}
var pos = {
row: dragStartCandy.row,
col: dragStartCandy.col
};
if (dir === 'right') pos.col++;
if (dir === 'left') pos.col--;
if (dir === 'down') pos.row++;
if (dir === 'up') pos.row--;
var target = getCandy(pos.row, pos.col);
if (target) {
trySwap(dragStartCandy, target);
}
// Reset highlight
tween(dragStartCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
dragStart = null;
dragStartCandy = null;
};
game.up = function (x, y, obj) {
if (selectedCandy) {
tween(selectedCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
selectedCandy = null;
}
dragStart = null;
dragStartCandy = null;
};
// Main update (not used for logic, but could be used for hint/shuffle)
game.update = function () {
// No-op for now
};
// Start game
startLevel();
// Play music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.7,
duration: 1200
}
}); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,570 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ level: 1,
+ bestScore: 0
+});
+
+/****
+* Classes
+****/
+// Candy class
+var Candy = Container.expand(function () {
+ var self = Container.call(this);
+ // Properties
+ self.type = null; // 0-5 for normal, 6 for striped
+ self.row = 0;
+ self.col = 0;
+ self.isSpecial = false;
+ // Attach asset
+ self.setType = function (type, isSpecial) {
+ self.type = type;
+ self.isSpecial = !!isSpecial;
+ self.removeChildren();
+ var assetId;
+ if (isSpecial) {
+ assetId = 'candyStriped';
+ } else {
+ assetId = ['candyRed', 'candyGreen', 'candyBlue', 'candyYellow', 'candyPurple', 'candyOrange'][type];
+ }
+ var candyGfx = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For striped, tint to match base color
+ if (isSpecial) {
+ var tints = [0xff4b5c, 0x4be04b, 0x4b7bff, 0xffe14b, 0xb44bff, 0xffa14b];
+ candyGfx.tint = tints[type];
+ }
+ };
+ // Animate pop
+ self.pop = function (_onFinish) {
+ tween(self, {
+ scaleX: 1.3,
+ scaleY: 1.3,
+ alpha: 0
+ }, {
+ duration: 220,
+ easing: tween.easeIn,
+ onFinish: function onFinish() {
+ if (_onFinish) _onFinish();
+ }
+ });
+ };
+ // Animate drop
+ self.dropTo = function (newY, onFinish) {
+ tween(self, {
+ y: newY
+ }, {
+ duration: 220,
+ easing: tween.bounceOut,
+ onFinish: onFinish
+ });
+ };
+ // Animate swap
+ self.swapTo = function (newX, newY, onFinish) {
+ tween(self, {
+ x: newX,
+ y: newY
+ }, {
+ duration: 180,
+ easing: tween.cubicInOut,
+ onFinish: onFinish
+ });
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x181828
+});
+
+/****
+* Game Code
+****/
+// Music
+// Sound effects
+// Board background
+// Special candy (striped)
+// Candy shapes/colors (6 types)
+// Board config
+var BOARD_SIZE = 8;
+var CELL_SIZE = 200;
+var BOARD_OFFSET_X = (2048 - BOARD_SIZE * CELL_SIZE) / 2;
+var BOARD_OFFSET_Y = 320;
+var CANDY_TYPES = 6;
+var MOVES_PER_LEVEL = 20;
+var TARGET_SCORE_BASE = 1200;
+// State
+var board = []; // 2D array [row][col] of Candy
+var selectedCandy = null;
+var swappingCandy = null;
+var isAnimating = false;
+var movesLeft = MOVES_PER_LEVEL;
+var score = 0;
+var targetScore = TARGET_SCORE_BASE + (storage.level - 1) * 400;
+var level = storage.level || 1;
+// GUI
+var scoreTxt = new Text2('Score: 0', {
+ size: 90,
+ fill: '#fff'
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+scoreTxt.y = 30;
+scoreTxt.x = 2048 / 2;
+var movesTxt = new Text2('Moves: ' + MOVES_PER_LEVEL, {
+ size: 70,
+ fill: '#fff'
+});
+movesTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(movesTxt);
+movesTxt.y = 140;
+movesTxt.x = 2048 / 2;
+var targetTxt = new Text2('Target: ' + targetScore, {
+ size: 60,
+ fill: '#fff'
+});
+targetTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(targetTxt);
+targetTxt.y = 220;
+targetTxt.x = 2048 / 2;
+// Board background
+var boardBg = LK.getAsset('boardBg', {
+ anchorX: 0,
+ anchorY: 0
+});
+boardBg.x = BOARD_OFFSET_X - 10;
+boardBg.y = BOARD_OFFSET_Y - 10;
+game.addChild(boardBg);
+// Helper: get candy at board position
+function getCandy(row, col) {
+ if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) return null;
+ return board[row][col];
+}
+// Helper: get board position from x,y
+function getBoardPos(x, y) {
+ var col = Math.floor((x - BOARD_OFFSET_X) / CELL_SIZE);
+ var row = Math.floor((y - BOARD_OFFSET_Y) / CELL_SIZE);
+ if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) return null;
+ return {
+ row: row,
+ col: col
+ };
+}
+// Helper: get pixel position from board pos
+function getPixelPos(row, col) {
+ return {
+ x: BOARD_OFFSET_X + col * CELL_SIZE + CELL_SIZE / 2,
+ y: BOARD_OFFSET_Y + row * CELL_SIZE + CELL_SIZE / 2
+ };
+}
+// Helper: random candy type
+function randomCandyType() {
+ return Math.floor(Math.random() * CANDY_TYPES);
+}
+// Helper: check if two candies are adjacent
+function areAdjacent(c1, c2) {
+ if (!c1 || !c2) return false;
+ var dr = Math.abs(c1.row - c2.row);
+ var dc = Math.abs(c1.col - c2.col);
+ return dr + dc === 1;
+}
+// Helper: find all matches on board
+function findMatches() {
+ var matches = [];
+ // Horizontal
+ for (var r = 0; r < BOARD_SIZE; r++) {
+ var runType = null,
+ runStart = 0,
+ runLen = 0;
+ for (var c = 0; c <= BOARD_SIZE; c++) {
+ var candy = c < BOARD_SIZE ? board[r][c] : null;
+ var t = candy && !candy.isSpecial ? candy.type : -1;
+ if (t === runType) {
+ runLen++;
+ } else {
+ if (runLen >= 3 && runType !== null) {
+ var arr = [];
+ for (var i = runStart; i < runStart + runLen; i++) arr.push(board[r][i]);
+ matches.push(arr);
+ }
+ runType = t;
+ runStart = c;
+ runLen = 1;
+ }
+ }
+ }
+ // Vertical
+ for (var c = 0; c < BOARD_SIZE; c++) {
+ var runType = null,
+ runStart = 0,
+ runLen = 0;
+ for (var r = 0; r <= BOARD_SIZE; r++) {
+ var candy = r < BOARD_SIZE ? board[r][c] : null;
+ var t = candy && !candy.isSpecial ? candy.type : -1;
+ if (t === runType) {
+ runLen++;
+ } else {
+ if (runLen >= 3 && runType !== null) {
+ var arr = [];
+ for (var i = runStart; i < runStart + runLen; i++) arr.push(board[i][c]);
+ matches.push(arr);
+ }
+ runType = t;
+ runStart = r;
+ runLen = 1;
+ }
+ }
+ }
+ return matches;
+}
+// Helper: find special matches (4+)
+function findSpecials(matches) {
+ var specials = [];
+ for (var i = 0; i < matches.length; i++) {
+ if (matches[i].length === 4) specials.push({
+ candies: matches[i],
+ type: 'striped'
+ });
+ // For MVP, only striped for 4-match
+ }
+ return specials;
+}
+// Helper: remove candies in matches, return positions to fill
+function removeMatches(matches, specials) {
+ var toRemove = [];
+ for (var i = 0; i < matches.length; i++) {
+ for (var j = 0; j < matches[i].length; j++) {
+ if (toRemove.indexOf(matches[i][j]) === -1) toRemove.push(matches[i][j]);
+ }
+ }
+ // Mark special candies
+ for (var i = 0; i < specials.length; i++) {
+ var arr = specials[i].candies;
+ var idx = Math.floor(arr.length / 2);
+ var c = arr[idx];
+ c.setType(c.type, true);
+ // Remove all except special
+ for (var j = 0; j < arr.length; j++) {
+ if (arr[j] !== c && toRemove.indexOf(arr[j]) === -1) toRemove.push(arr[j]);
+ }
+ }
+ // Animate and remove
+ var removed = 0;
+ for (var i = 0; i < toRemove.length; i++) {
+ (function (candy) {
+ candy.pop(function () {
+ game.removeChild(candy);
+ });
+ })(toRemove[i]);
+ // Remove from board
+ board[candy.row][candy.col] = null;
+ removed++;
+ }
+ return removed;
+}
+// Helper: drop candies and fill new
+function dropAndFill(onFinish) {
+ // For each column, drop candies down
+ var maxDrop = 0;
+ for (var c = 0; c < BOARD_SIZE; c++) {
+ var empty = 0;
+ for (var r = BOARD_SIZE - 1; r >= 0; r--) {
+ var candy = board[r][c];
+ if (!candy) {
+ empty++;
+ } else if (empty > 0) {
+ board[r + empty][c] = candy;
+ board[r][c] = null;
+ var pos = getPixelPos(r + empty, c);
+ candy.row = r + empty;
+ candy.col = c;
+ candy.dropTo(pos.y);
+ if (empty > maxDrop) maxDrop = empty;
+ }
+ }
+ // Fill new candies at top
+ for (var e = 0; e < empty; e++) {
+ var type = randomCandyType();
+ var newCandy = new Candy();
+ newCandy.setType(type, false);
+ newCandy.row = e;
+ newCandy.col = c;
+ var pos = getPixelPos(e, c);
+ newCandy.x = pos.x;
+ newCandy.y = pos.y - empty * CELL_SIZE;
+ game.addChild(newCandy);
+ board[e][c] = newCandy;
+ newCandy.dropTo(pos.y);
+ }
+ }
+ // Wait for drop animation
+ LK.setTimeout(onFinish, 240);
+}
+// Helper: check if board has any matches
+function hasAnyMatches() {
+ var m = findMatches();
+ return m.length > 0;
+}
+// Helper: shuffle board if no moves
+function shuffleBoard() {
+ // Simple shuffle: randomize all candies
+ var candies = [];
+ for (var r = 0; r < BOARD_SIZE; r++) for (var c = 0; c < BOARD_SIZE; c++) candies.push(board[r][c]);
+ for (var i = candies.length - 1; i > 0; i--) {
+ var j = Math.floor(Math.random() * (i + 1));
+ // Swap
+ var trow = candies[i].row,
+ tcol = candies[i].col;
+ candies[i].row = candies[j].row;
+ candies[i].col = candies[j].col;
+ candies[j].row = trow;
+ candies[j].col = tcol;
+ board[candies[i].row][candies[i].col] = candies[i];
+ board[candies[j].row][candies[j].col] = candies[j];
+ // Animate
+ var posI = getPixelPos(candies[i].row, candies[i].col);
+ var posJ = getPixelPos(candies[j].row, candies[j].col);
+ candies[i].swapTo(posI.x, posI.y);
+ candies[j].swapTo(posJ.x, posJ.y);
+ }
+}
+// Helper: check if any valid moves exist (MVP: skip, always allow shuffle after 3 failed attempts)
+// Initialize board
+function initBoard() {
+ // Remove old candies
+ for (var r = 0; r < BOARD_SIZE; r++) for (var c = 0; c < BOARD_SIZE; c++) {
+ if (board[r] && board[r][c]) {
+ game.removeChild(board[r][c]);
+ }
+ }
+ board = [];
+ for (var r = 0; r < BOARD_SIZE; r++) {
+ board[r] = [];
+ for (var c = 0; c < BOARD_SIZE; c++) {
+ var type = randomCandyType();
+ var candy = new Candy();
+ candy.setType(type, false);
+ candy.row = r;
+ candy.col = c;
+ var pos = getPixelPos(r, c);
+ candy.x = pos.x;
+ candy.y = pos.y;
+ game.addChild(candy);
+ board[r][c] = candy;
+ }
+ }
+ // Remove initial matches
+ while (hasAnyMatches()) {
+ var matches = findMatches();
+ for (var i = 0; i < matches.length; i++) {
+ for (var j = 0; j < matches[i].length; j++) {
+ var c = matches[i][j];
+ var t;
+ do {
+ t = randomCandyType();
+ } while (t === c.type);
+ c.setType(t, false);
+ }
+ }
+ }
+}
+// Start new level
+function startLevel() {
+ movesLeft = MOVES_PER_LEVEL;
+ score = 0;
+ level = storage.level || 1;
+ targetScore = TARGET_SCORE_BASE + (level - 1) * 400;
+ scoreTxt.setText('Score: 0');
+ movesTxt.setText('Moves: ' + movesLeft);
+ targetTxt.setText('Target: ' + targetScore);
+ selectedCandy = null;
+ swappingCandy = null;
+ isAnimating = false;
+ initBoard();
+}
+// Handle swap logic
+function trySwap(c1, c2) {
+ if (!c1 || !c2 || isAnimating) return;
+ if (!areAdjacent(c1, c2)) return;
+ isAnimating = true;
+ // Swap in board
+ var r1 = c1.row,
+ c1c = c1.col,
+ r2 = c2.row,
+ c2c = c2.col;
+ board[r1][c1c] = c2;
+ board[r2][c2c] = c1;
+ c1.row = r2;
+ c1.col = c2c;
+ c2.row = r1;
+ c2.col = c1c;
+ // Animate
+ var pos1 = getPixelPos(c1.row, c1.col);
+ var pos2 = getPixelPos(c2.row, c2.col);
+ var done = 0;
+ c1.swapTo(pos1.x, pos1.y, function () {
+ done++;
+ if (done === 2) afterSwap();
+ });
+ c2.swapTo(pos2.x, pos2.y, function () {
+ done++;
+ if (done === 2) afterSwap();
+ });
+ LK.getSound('swap').play();
+ function afterSwap() {
+ var matches = findMatches();
+ if (matches.length === 0) {
+ // No match, swap back
+ board[r1][c1c] = c1;
+ board[r2][c2c] = c2;
+ c1.row = r1;
+ c1.col = c1c;
+ c2.row = r2;
+ c2.col = c2c;
+ var pos1b = getPixelPos(c1.row, c1.col);
+ var pos2b = getPixelPos(c2.row, c2.col);
+ c1.swapTo(pos1b.x, pos1b.y);
+ c2.swapTo(pos2b.x, pos2b.y, function () {
+ isAnimating = false;
+ LK.getSound('noMatch').play();
+ });
+ } else {
+ // Valid match
+ movesLeft--;
+ movesTxt.setText('Moves: ' + movesLeft);
+ resolveMatches(matches);
+ }
+ selectedCandy = null;
+ swappingCandy = null;
+ }
+}
+// Resolve matches recursively
+function resolveMatches(matches) {
+ if (!matches || matches.length === 0) {
+ isAnimating = false;
+ // Check for win/lose
+ if (score >= targetScore) {
+ // Win
+ storage.level = level + 1;
+ if (score > storage.bestScore) storage.bestScore = score;
+ LK.showYouWin();
+ } else if (movesLeft <= 0) {
+ // Lose
+ storage.level = 1;
+ LK.showGameOver();
+ }
+ return;
+ }
+ LK.getSound('match').play();
+ // Special candies
+ var specials = findSpecials(matches);
+ // Remove matches
+ var removed = removeMatches(matches, specials);
+ // Score
+ score += removed * 60;
+ if (score > storage.bestScore) storage.bestScore = score;
+ scoreTxt.setText('Score: ' + score);
+ // Drop and fill
+ dropAndFill(function () {
+ // Check for new matches
+ var newMatches = findMatches();
+ if (newMatches.length > 0) {
+ // Chain
+ LK.getSound('special').play();
+ resolveMatches(newMatches);
+ } else {
+ isAnimating = false;
+ }
+ });
+}
+// Touch/drag logic
+var dragStart = null;
+var dragStartCandy = null;
+game.down = function (x, y, obj) {
+ if (isAnimating) return;
+ var pos = getBoardPos(x, y);
+ if (!pos) return;
+ var candy = getCandy(pos.row, pos.col);
+ if (!candy) return;
+ dragStart = {
+ x: x,
+ y: y
+ };
+ dragStartCandy = candy;
+ selectedCandy = candy;
+ // Highlight (scale up)
+ tween(candy, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 100
+ });
+};
+game.move = function (x, y, obj) {
+ if (!dragStart || !dragStartCandy || isAnimating) return;
+ var dx = x - dragStart.x;
+ var dy = y - dragStart.y;
+ if (Math.abs(dx) < 40 && Math.abs(dy) < 40) return;
+ // Determine direction
+ var dir = null;
+ if (Math.abs(dx) > Math.abs(dy)) {
+ dir = dx > 0 ? 'right' : 'left';
+ } else {
+ dir = dy > 0 ? 'down' : 'up';
+ }
+ var pos = {
+ row: dragStartCandy.row,
+ col: dragStartCandy.col
+ };
+ if (dir === 'right') pos.col++;
+ if (dir === 'left') pos.col--;
+ if (dir === 'down') pos.row++;
+ if (dir === 'up') pos.row--;
+ var target = getCandy(pos.row, pos.col);
+ if (target) {
+ trySwap(dragStartCandy, target);
+ }
+ // Reset highlight
+ tween(dragStartCandy, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 100
+ });
+ dragStart = null;
+ dragStartCandy = null;
+};
+game.up = function (x, y, obj) {
+ if (selectedCandy) {
+ tween(selectedCandy, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 100
+ });
+ selectedCandy = null;
+ }
+ dragStart = null;
+ dragStartCandy = null;
+};
+// Main update (not used for logic, but could be used for hint/shuffle)
+game.update = function () {
+ // No-op for now
+};
+// Start game
+startLevel();
+// Play music
+LK.playMusic('bgmusic', {
+ fade: {
+ start: 0,
+ end: 0.7,
+ duration: 1200
+ }
});
\ No newline at end of file
Mavi şeker. In-Game asset. 2d. High contrast. No shadows
Yeşil seker. In-Game asset. 2d. High contrast. No shadows
Turuncu şeker. In-Game asset. 2d. High contrast. No shadows
Mor şeker. In-Game asset. 2d. High contrast. No shadows
Sarı şeker. In-Game asset. 2d. High contrast. No shadows
Kırmızı şeker. In-Game asset. 2d. High contrast. No shadows