/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Candy class: represents a single candy on the board var Candy = Container.expand(function () { var self = Container.call(this); // Properties self.type = 0; // 0-5 for normal candies, 6+ for special self.row = 0; self.col = 0; self.selected = false; self.special = null; // null, 'row', 'col', 'bomb' // Attach asset var candyColors = [0xff4d4d, // Red (pentagon) 0x4db8ff, // Blue 0xffe14d, // Yellow 0x7cff4d, // Green 0xff4df7, // Pink 0xff914d // Orange ]; // For special candies, use a white border function getCandyAsset(type, special) { var color = candyColors[type % candyColors.length]; var asset = LK.getAsset('candy_' + type, { width: candySize, height: candySize, color: color, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5 }); if (special) { // Add a border by overlaying a slightly larger ellipse var border = LK.getAsset('candy_border', { width: candySize + 16, height: candySize + 16, color: 0xffffff, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5 }); var group = new Container(); group.addChild(border); group.addChild(asset); return group; } return asset; } self.setType = function (type, special) { self.type = type; self.special = special || null; // Remove old graphics while (self.children.length) self.removeChild(self.children[0]); var asset = getCandyAsset(type, special); self.addChild(asset); }; // Highlight for selection self.setSelected = function (selected) { self.selected = selected; if (self.children.length) { if (selected) { tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 120, easing: tween.easeOut }); } else { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.easeOut }); } } }; // Animate removal self.animateRemove = function (_onFinish) { tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 180, easing: tween.easeIn, onFinish: function onFinish() { if (_onFinish) _onFinish(); } }); }; // Animate drop self.animateDrop = function (targetY, onFinish) { tween(self, { y: targetY }, { duration: 180, easing: tween.bounceOut, onFinish: onFinish }); }; // Animate spawn self.animateSpawn = function () { self.scaleX = self.scaleY = 0; tween(self, { scaleX: 1, scaleY: 1 }, { duration: 180, easing: tween.easeOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222244 }); /**** * Game Code ****/ // Board settings var boardRows = 9; var boardCols = 7; var candyTypes = 6; var candySize = 180; var boardOffsetX = Math.floor((2048 - boardCols * candySize) / 2); var boardOffsetY = 320; var moveLimit = 25; var targetScore = 3000; // Game state var board = []; var candies = []; var selectedCandy = null; var swapping = false; var animating = false; var movesLeft = moveLimit; var score = 0; // UI var scoreTxt = new Text2('Score: 0', { size: 90, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var movesTxt = new Text2('Moves: ' + movesLeft, { size: 70, fill: "#fff" }); movesTxt.anchor.set(0.5, 0); LK.gui.top.addChild(movesTxt); movesTxt.y = 110; // Helper: get board position from x/y function getBoardPos(x, y) { var col = Math.floor((x - boardOffsetX) / candySize); var row = Math.floor((y - boardOffsetY) / candySize); if (col < 0 || col >= boardCols || row < 0 || row >= boardRows) return null; return { row: row, col: col }; } // Helper: get candy at row,col function getCandy(row, col) { if (row < 0 || row >= boardRows || col < 0 || col >= boardCols) return null; return board[row][col]; } // Helper: swap candies in board and update their row/col function swapCandies(c1, c2) { 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; } // Helper: check if two candies are adjacent function areAdjacent(c1, c2) { return Math.abs(c1.row - c2.row) + Math.abs(c1.col - c2.col) === 1; } // Helper: find all matches on the board function findMatches() { var matches = []; // Horizontal for (var r = 0; r < boardRows; r++) { var streak = 1; for (var c = 1; c < boardCols; c++) { if (board[r][c].type === board[r][c - 1].type) { streak++; } else { if (streak >= 3) { matches.push({ row: r, col: c - 1, len: streak, dir: 'h' }); } streak = 1; } } if (streak >= 3) { matches.push({ row: r, col: boardCols - 1, len: streak, dir: 'h' }); } } // Vertical for (var c = 0; c < boardCols; c++) { var streak = 1; for (var r = 1; r < boardRows; r++) { if (board[r][c].type === board[r - 1][c].type) { streak++; } else { if (streak >= 3) { matches.push({ row: r - 1, col: c, len: streak, dir: 'v' }); } streak = 1; } } if (streak >= 3) { matches.push({ row: boardRows - 1, col: c, len: streak, dir: 'v' }); } } return matches; } // Helper: mark candies to be removed, and create special candies if needed function markMatches(matches) { var removeMap = []; for (var r = 0; r < boardRows; r++) { removeMap[r] = []; for (var c = 0; c < boardCols; c++) { removeMap[r][c] = false; } } // For special candy creation var specials = []; for (var i = 0; i < matches.length; i++) { var m = matches[i]; if (m.dir === 'h') { for (var k = 0; k < m.len; k++) { removeMap[m.row][m.col - k] = true; } // Create special for 4/5 if (m.len === 4) { specials.push({ row: m.row, col: m.col - 1, special: 'row' }); } else if (m.len >= 5) { specials.push({ row: m.row, col: m.col - 2, special: 'bomb' }); } } else if (m.dir === 'v') { for (var k = 0; k < m.len; k++) { removeMap[m.row - k][m.col] = true; } if (m.len === 4) { specials.push({ row: m.row - 1, col: m.col, special: 'col' }); } else if (m.len >= 5) { specials.push({ row: m.row - 2, col: m.col, special: 'bomb' }); } } } return { removeMap: removeMap, specials: specials }; } // Helper: remove candies, animate, and return positions to refill function removeAndScore(removeMap, specials) { var toRemove = []; for (var r = 0; r < boardRows; r++) { for (var c = 0; c < boardCols; c++) { if (removeMap[r][c]) { toRemove.push(board[r][c]); } } } // Score: 60 per candy, + bonus for special var gained = toRemove.length * 60; score += gained; LK.setScore(score); scoreTxt.setText('Score: ' + score); // Place specials for (var i = 0; i < specials.length; i++) { var s = specials[i]; var candy = board[s.row][s.col]; if (candy) { candy.setType(candy.type, s.special); } } // Animate and remove var removed = 0; for (var i = 0; i < toRemove.length; i++) { var c = toRemove[i]; c.animateRemove(function () { removed++; if (removed === toRemove.length) { refillBoard(); } }); // Remove from board after animation board[c.row][c.col] = null; } // If nothing to remove, refill immediately if (toRemove.length === 0) { refillBoard(); } } // Helper: refill board after removals function refillBoard() { // Drop candies down for (var c = 0; c < boardCols; c++) { var empty = 0; for (var r = boardRows - 1; r >= 0; r--) { if (!board[r][c]) { empty++; } else if (empty > 0) { var candy = board[r][c]; board[r + empty][c] = candy; candy.row = r + empty; candy.col = c; board[r][c] = null; var targetY = boardOffsetY + (r + empty) * candySize + candySize / 2; candy.animateDrop(targetY); } } // Add new candies at top for (var e = 0; e < empty; e++) { var type = Math.floor(Math.random() * candyTypes); var newCandy = new Candy(); newCandy.setType(type); newCandy.row = e; newCandy.col = c; var x = boardOffsetX + c * candySize + candySize / 2; var y = boardOffsetY + e * candySize + candySize / 2 - empty * candySize; newCandy.x = x; newCandy.y = y; newCandy.scaleX = newCandy.scaleY = 1; newCandy.alpha = 1; game.addChild(newCandy); candies.push(newCandy); board[e][c] = newCandy; // Animate drop to correct position var targetY = boardOffsetY + e * candySize + candySize / 2; newCandy.animateDrop(targetY, function () {}); newCandy.animateSpawn(); } } // After all drops, check for new matches LK.setTimeout(function () { resolveBoard(); }, 220); } // Helper: resolve board (find matches, remove, refill) function resolveBoard() { var matches = findMatches(); if (matches.length > 0) { var _markMatches = markMatches(matches), removeMap = _markMatches.removeMap, specials = _markMatches.specials; removeAndScore(removeMap, specials); } else { animating = false; // Check for win/lose if (score >= targetScore) { LK.showYouWin(); } else if (movesLeft <= 0) { LK.showGameOver(); } } } // Helper: deselect all candies function deselectAll() { for (var i = 0; i < candies.length; i++) { candies[i].setSelected(false); } selectedCandy = null; } // Helper: get candy at x,y function getCandyAt(x, y) { var pos = getBoardPos(x, y); if (!pos) return null; return board[pos.row][pos.col]; } // Initialize board function initBoard() { // Clear old for (var i = 0; i < candies.length; i++) { candies[i].destroy(); } candies = []; board = []; for (var r = 0; r < boardRows; r++) { board[r] = []; for (var c = 0; c < boardCols; c++) { var type = Math.floor(Math.random() * candyTypes); var candy = new Candy(); candy.setType(type); candy.row = r; candy.col = c; var x = boardOffsetX + c * candySize + candySize / 2; var y = boardOffsetY + r * candySize + candySize / 2; candy.x = x; candy.y = y; candy.scaleX = candy.scaleY = 1; candy.alpha = 1; game.addChild(candy); candies.push(candy); board[r][c] = candy; } } // Remove any initial matches LK.setTimeout(function () { resolveBoard(); }, 100); } // Handle touch/mouse down game.down = function (x, y, obj) { if (animating) return; var candy = getCandyAt(x, y); if (!candy) { deselectAll(); return; } if (!selectedCandy) { selectedCandy = candy; candy.setSelected(true); } else if (selectedCandy === candy) { deselectAll(); } else if (areAdjacent(selectedCandy, candy)) { swapping = true; animating = true; // Swap visually var c1 = selectedCandy, c2 = candy; var c1x = c1.x, c1y = c1.y, c2x = c2.x, c2y = c2.y; tween(c1, { x: c2x, y: c2y }, { duration: 180, easing: tween.easeInOut }); tween(c2, { x: c1x, y: c1y }, { duration: 180, easing: tween.easeInOut, onFinish: function onFinish() { // Swap in board swapCandies(c1, c2); // Check for matches var matches = findMatches(); if (matches.length > 0) { movesLeft--; movesTxt.setText('Moves: ' + movesLeft); deselectAll(); var _markMatches2 = markMatches(matches), removeMap = _markMatches2.removeMap, specials = _markMatches2.specials; removeAndScore(removeMap, specials); } else { // No match, swap back tween(c1, { x: c1x, y: c1y }, { duration: 180, easing: tween.easeInOut }); tween(c2, { x: c2x, y: c2y }, { duration: 180, easing: tween.easeInOut, onFinish: function onFinish() { swapCandies(c1, c2); deselectAll(); animating = false; } }); } swapping = false; } }); } else { deselectAll(); selectedCandy = candy; candy.setSelected(true); } }; // Prevent drag game.move = function (x, y, obj) { // No drag for match-3 }; // Prevent up game.up = function (x, y, obj) {}; // Game update game.update = function () { // No per-frame logic needed }; // Start game function startGame() { score = 0; movesLeft = moveLimit; LK.setScore(score); scoreTxt.setText('Score: ' + score); movesTxt.setText('Moves: ' + movesLeft); animating = false; swapping = false; selectedCandy = null; initBoard(); } startGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Candy class: represents a single candy on the board
var Candy = Container.expand(function () {
var self = Container.call(this);
// Properties
self.type = 0; // 0-5 for normal candies, 6+ for special
self.row = 0;
self.col = 0;
self.selected = false;
self.special = null; // null, 'row', 'col', 'bomb'
// Attach asset
var candyColors = [0xff4d4d,
// Red (pentagon)
0x4db8ff,
// Blue
0xffe14d,
// Yellow
0x7cff4d,
// Green
0xff4df7,
// Pink
0xff914d // Orange
];
// For special candies, use a white border
function getCandyAsset(type, special) {
var color = candyColors[type % candyColors.length];
var asset = LK.getAsset('candy_' + type, {
width: candySize,
height: candySize,
color: color,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
if (special) {
// Add a border by overlaying a slightly larger ellipse
var border = LK.getAsset('candy_border', {
width: candySize + 16,
height: candySize + 16,
color: 0xffffff,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
var group = new Container();
group.addChild(border);
group.addChild(asset);
return group;
}
return asset;
}
self.setType = function (type, special) {
self.type = type;
self.special = special || null;
// Remove old graphics
while (self.children.length) self.removeChild(self.children[0]);
var asset = getCandyAsset(type, special);
self.addChild(asset);
};
// Highlight for selection
self.setSelected = function (selected) {
self.selected = selected;
if (self.children.length) {
if (selected) {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 120,
easing: tween.easeOut
});
} else {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
}
}
};
// Animate removal
self.animateRemove = function (_onFinish) {
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 180,
easing: tween.easeIn,
onFinish: function onFinish() {
if (_onFinish) _onFinish();
}
});
};
// Animate drop
self.animateDrop = function (targetY, onFinish) {
tween(self, {
y: targetY
}, {
duration: 180,
easing: tween.bounceOut,
onFinish: onFinish
});
};
// Animate spawn
self.animateSpawn = function () {
self.scaleX = self.scaleY = 0;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 180,
easing: tween.easeOut
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222244
});
/****
* Game Code
****/
// Board settings
var boardRows = 9;
var boardCols = 7;
var candyTypes = 6;
var candySize = 180;
var boardOffsetX = Math.floor((2048 - boardCols * candySize) / 2);
var boardOffsetY = 320;
var moveLimit = 25;
var targetScore = 3000;
// Game state
var board = [];
var candies = [];
var selectedCandy = null;
var swapping = false;
var animating = false;
var movesLeft = moveLimit;
var score = 0;
// UI
var scoreTxt = new Text2('Score: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var movesTxt = new Text2('Moves: ' + movesLeft, {
size: 70,
fill: "#fff"
});
movesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(movesTxt);
movesTxt.y = 110;
// Helper: get board position from x/y
function getBoardPos(x, y) {
var col = Math.floor((x - boardOffsetX) / candySize);
var row = Math.floor((y - boardOffsetY) / candySize);
if (col < 0 || col >= boardCols || row < 0 || row >= boardRows) return null;
return {
row: row,
col: col
};
}
// Helper: get candy at row,col
function getCandy(row, col) {
if (row < 0 || row >= boardRows || col < 0 || col >= boardCols) return null;
return board[row][col];
}
// Helper: swap candies in board and update their row/col
function swapCandies(c1, c2) {
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;
}
// Helper: check if two candies are adjacent
function areAdjacent(c1, c2) {
return Math.abs(c1.row - c2.row) + Math.abs(c1.col - c2.col) === 1;
}
// Helper: find all matches on the board
function findMatches() {
var matches = [];
// Horizontal
for (var r = 0; r < boardRows; r++) {
var streak = 1;
for (var c = 1; c < boardCols; c++) {
if (board[r][c].type === board[r][c - 1].type) {
streak++;
} else {
if (streak >= 3) {
matches.push({
row: r,
col: c - 1,
len: streak,
dir: 'h'
});
}
streak = 1;
}
}
if (streak >= 3) {
matches.push({
row: r,
col: boardCols - 1,
len: streak,
dir: 'h'
});
}
}
// Vertical
for (var c = 0; c < boardCols; c++) {
var streak = 1;
for (var r = 1; r < boardRows; r++) {
if (board[r][c].type === board[r - 1][c].type) {
streak++;
} else {
if (streak >= 3) {
matches.push({
row: r - 1,
col: c,
len: streak,
dir: 'v'
});
}
streak = 1;
}
}
if (streak >= 3) {
matches.push({
row: boardRows - 1,
col: c,
len: streak,
dir: 'v'
});
}
}
return matches;
}
// Helper: mark candies to be removed, and create special candies if needed
function markMatches(matches) {
var removeMap = [];
for (var r = 0; r < boardRows; r++) {
removeMap[r] = [];
for (var c = 0; c < boardCols; c++) {
removeMap[r][c] = false;
}
}
// For special candy creation
var specials = [];
for (var i = 0; i < matches.length; i++) {
var m = matches[i];
if (m.dir === 'h') {
for (var k = 0; k < m.len; k++) {
removeMap[m.row][m.col - k] = true;
}
// Create special for 4/5
if (m.len === 4) {
specials.push({
row: m.row,
col: m.col - 1,
special: 'row'
});
} else if (m.len >= 5) {
specials.push({
row: m.row,
col: m.col - 2,
special: 'bomb'
});
}
} else if (m.dir === 'v') {
for (var k = 0; k < m.len; k++) {
removeMap[m.row - k][m.col] = true;
}
if (m.len === 4) {
specials.push({
row: m.row - 1,
col: m.col,
special: 'col'
});
} else if (m.len >= 5) {
specials.push({
row: m.row - 2,
col: m.col,
special: 'bomb'
});
}
}
}
return {
removeMap: removeMap,
specials: specials
};
}
// Helper: remove candies, animate, and return positions to refill
function removeAndScore(removeMap, specials) {
var toRemove = [];
for (var r = 0; r < boardRows; r++) {
for (var c = 0; c < boardCols; c++) {
if (removeMap[r][c]) {
toRemove.push(board[r][c]);
}
}
}
// Score: 60 per candy, + bonus for special
var gained = toRemove.length * 60;
score += gained;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
// Place specials
for (var i = 0; i < specials.length; i++) {
var s = specials[i];
var candy = board[s.row][s.col];
if (candy) {
candy.setType(candy.type, s.special);
}
}
// Animate and remove
var removed = 0;
for (var i = 0; i < toRemove.length; i++) {
var c = toRemove[i];
c.animateRemove(function () {
removed++;
if (removed === toRemove.length) {
refillBoard();
}
});
// Remove from board after animation
board[c.row][c.col] = null;
}
// If nothing to remove, refill immediately
if (toRemove.length === 0) {
refillBoard();
}
}
// Helper: refill board after removals
function refillBoard() {
// Drop candies down
for (var c = 0; c < boardCols; c++) {
var empty = 0;
for (var r = boardRows - 1; r >= 0; r--) {
if (!board[r][c]) {
empty++;
} else if (empty > 0) {
var candy = board[r][c];
board[r + empty][c] = candy;
candy.row = r + empty;
candy.col = c;
board[r][c] = null;
var targetY = boardOffsetY + (r + empty) * candySize + candySize / 2;
candy.animateDrop(targetY);
}
}
// Add new candies at top
for (var e = 0; e < empty; e++) {
var type = Math.floor(Math.random() * candyTypes);
var newCandy = new Candy();
newCandy.setType(type);
newCandy.row = e;
newCandy.col = c;
var x = boardOffsetX + c * candySize + candySize / 2;
var y = boardOffsetY + e * candySize + candySize / 2 - empty * candySize;
newCandy.x = x;
newCandy.y = y;
newCandy.scaleX = newCandy.scaleY = 1;
newCandy.alpha = 1;
game.addChild(newCandy);
candies.push(newCandy);
board[e][c] = newCandy;
// Animate drop to correct position
var targetY = boardOffsetY + e * candySize + candySize / 2;
newCandy.animateDrop(targetY, function () {});
newCandy.animateSpawn();
}
}
// After all drops, check for new matches
LK.setTimeout(function () {
resolveBoard();
}, 220);
}
// Helper: resolve board (find matches, remove, refill)
function resolveBoard() {
var matches = findMatches();
if (matches.length > 0) {
var _markMatches = markMatches(matches),
removeMap = _markMatches.removeMap,
specials = _markMatches.specials;
removeAndScore(removeMap, specials);
} else {
animating = false;
// Check for win/lose
if (score >= targetScore) {
LK.showYouWin();
} else if (movesLeft <= 0) {
LK.showGameOver();
}
}
}
// Helper: deselect all candies
function deselectAll() {
for (var i = 0; i < candies.length; i++) {
candies[i].setSelected(false);
}
selectedCandy = null;
}
// Helper: get candy at x,y
function getCandyAt(x, y) {
var pos = getBoardPos(x, y);
if (!pos) return null;
return board[pos.row][pos.col];
}
// Initialize board
function initBoard() {
// Clear old
for (var i = 0; i < candies.length; i++) {
candies[i].destroy();
}
candies = [];
board = [];
for (var r = 0; r < boardRows; r++) {
board[r] = [];
for (var c = 0; c < boardCols; c++) {
var type = Math.floor(Math.random() * candyTypes);
var candy = new Candy();
candy.setType(type);
candy.row = r;
candy.col = c;
var x = boardOffsetX + c * candySize + candySize / 2;
var y = boardOffsetY + r * candySize + candySize / 2;
candy.x = x;
candy.y = y;
candy.scaleX = candy.scaleY = 1;
candy.alpha = 1;
game.addChild(candy);
candies.push(candy);
board[r][c] = candy;
}
}
// Remove any initial matches
LK.setTimeout(function () {
resolveBoard();
}, 100);
}
// Handle touch/mouse down
game.down = function (x, y, obj) {
if (animating) return;
var candy = getCandyAt(x, y);
if (!candy) {
deselectAll();
return;
}
if (!selectedCandy) {
selectedCandy = candy;
candy.setSelected(true);
} else if (selectedCandy === candy) {
deselectAll();
} else if (areAdjacent(selectedCandy, candy)) {
swapping = true;
animating = true;
// Swap visually
var c1 = selectedCandy,
c2 = candy;
var c1x = c1.x,
c1y = c1.y,
c2x = c2.x,
c2y = c2.y;
tween(c1, {
x: c2x,
y: c2y
}, {
duration: 180,
easing: tween.easeInOut
});
tween(c2, {
x: c1x,
y: c1y
}, {
duration: 180,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Swap in board
swapCandies(c1, c2);
// Check for matches
var matches = findMatches();
if (matches.length > 0) {
movesLeft--;
movesTxt.setText('Moves: ' + movesLeft);
deselectAll();
var _markMatches2 = markMatches(matches),
removeMap = _markMatches2.removeMap,
specials = _markMatches2.specials;
removeAndScore(removeMap, specials);
} else {
// No match, swap back
tween(c1, {
x: c1x,
y: c1y
}, {
duration: 180,
easing: tween.easeInOut
});
tween(c2, {
x: c2x,
y: c2y
}, {
duration: 180,
easing: tween.easeInOut,
onFinish: function onFinish() {
swapCandies(c1, c2);
deselectAll();
animating = false;
}
});
}
swapping = false;
}
});
} else {
deselectAll();
selectedCandy = candy;
candy.setSelected(true);
}
};
// Prevent drag
game.move = function (x, y, obj) {
// No drag for match-3
};
// Prevent up
game.up = function (x, y, obj) {};
// Game update
game.update = function () {
// No per-frame logic needed
};
// Start game
function startGame() {
score = 0;
movesLeft = moveLimit;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
movesTxt.setText('Moves: ' + movesLeft);
animating = false;
swapping = false;
selectedCandy = null;
initBoard();
}
startGame();
candy . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
candy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
black bomb candy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
yellow candy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
red candy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat