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;
// Total score
var totalScore = storage.totalScore || 0;
var totalScoreTxt = new Text2('Total: ' + totalScore, {
size: 60,
fill: '#fff'
});
totalScoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(totalScoreTxt);
totalScoreTxt.y = 100;
totalScoreTxt.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;
// Leaderboard button
var leaderboardBtn = new Text2('🏆', {
size: 90,
fill: '#fff'
});
leaderboardBtn.anchor.set(1, 0);
LK.gui.top.addChild(leaderboardBtn);
// Place at top right, leaving margin for safe area
leaderboardBtn.x = 2048 - 40;
leaderboardBtn.y = 30;
// Show leaderboard on press
leaderboardBtn.down = function (x, y, obj) {
LK.showLeaderboard();
};
// 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];
// Only create special if not already special
if (!c.isSpecial) {
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;
if (toRemove.length > 0) {
LK.getSound('match').play();
}
for (var i = 0; i < toRemove.length; i++) {
(function (candy) {
// Play match sound for each candy popped
LK.getSound('match').play();
candy.pop(function () {
game.removeChild(candy);
});
// Remove from board
board[candy.row][candy.col] = null;
removed++;
})(toRemove[i]);
}
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;
newCandy.isSpecial = false;
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;
candy.isSpecial = false;
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;
// Uncomment the next two lines to reset total score on game over
// totalScore = 0;
// storage.totalScore = 0;
LK.showGameOver();
}
return;
}
LK.getSound('match').play();
// Special candies
var specials = findSpecials(matches);
// Activate special candies (striped) if matched
for (var i = 0; i < matches.length; i++) {
for (var j = 0; j < matches[i].length; j++) {
var candy = matches[i][j];
if (candy && candy.isSpecial) {
// Striped: clear row or column
var isRow = false;
// Check if this match is horizontal or vertical
for (var k = 0; k < matches[i].length - 1; k++) {
if (matches[i][k].row === matches[i][k + 1].row) isRow = true;
}
if (isRow) {
// Clear entire row
for (var c = 0; c < BOARD_SIZE; c++) {
var target = board[candy.row][c];
if (target && !target.isSpecial) {
target.pop(function () {});
game.removeChild(target);
board[candy.row][c] = null;
}
}
} else {
// Clear entire column
for (var r = 0; r < BOARD_SIZE; r++) {
var target = board[r][candy.col];
if (target && !target.isSpecial) {
target.pop(function () {});
game.removeChild(target);
board[r][candy.col] = null;
}
}
}
LK.getSound('special').play();
}
}
}
// Remove matches
var removed = removeMatches(matches, specials);
// Score
score += removed * 60;
if (score > storage.bestScore) storage.bestScore = score;
scoreTxt.setText('Score: ' + score);
// Update total score and persist
totalScore += removed * 60;
storage.totalScore = totalScore;
totalScoreTxt.setText('Total: ' + totalScore);
// Show total score text when candies are matched (merged)
totalScoreTxt.visible = true;
// 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
@@ -547,8 +547,10 @@
// Update total score and persist
totalScore += removed * 60;
storage.totalScore = totalScore;
totalScoreTxt.setText('Total: ' + totalScore);
+ // Show total score text when candies are matched (merged)
+ totalScoreTxt.visible = true;
// Drop and fill
dropAndFill(function () {
// Check for new matches
var newMatches = findMatches();
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