/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Gem = Container.expand(function (gemType) {
var self = Container.call(this);
self.gemType = gemType;
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var gemGraphics = self.attachAsset(gemType, {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = 304 + gridX * 160;
self.y = 526 + gridY * 160;
};
self.animateToPosition = function (targetX, targetY, callback) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (callback) callback();
}
});
};
self.down = function (x, y, obj) {
// Selection is now handled in game.down to prevent conflicts
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1,
scaleY: 1
}));
var gemTypes = ['diamond', 'emerald', 'ruby', 'sapphire', 'topaz'];
var grid = [];
var selectedGem = null;
var gameAnimating = false;
var currentLevel = storage.currentLevel || 1;
var maxLevel = storage.maxLevel || 1;
var movesRemaining = 30;
var chainMultiplier = 1;
var targetScore = currentLevel * 100; // Score needed to advance
// Initialize grid array
for (var x = 0; x < 10; x++) {
grid[x] = [];
for (var y = 0; y < 10; y++) {
grid[x][y] = null;
}
}
// Create grid background
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
var gridCell = game.addChild(LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
x: 304 + x * 160,
y: 526 + y * 160
}));
}
}
// UI Elements
var scoreText = new Text2('Puan: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var movesText = new Text2('Hamle: 30', {
size: 65,
fill: 0xFFFF00
});
movesText.anchor.set(0.5, 0);
movesText.y = 80;
LK.gui.top.addChild(movesText);
var levelText = new Text2('Seviye: 1', {
size: 65,
fill: 0x00FF00
});
levelText.anchor.set(0.5, 0);
levelText.y = 140;
LK.gui.top.addChild(levelText);
var targetText = new Text2('Hedef: 100', {
size: 55,
fill: 0xFFFFFF
});
targetText.anchor.set(0.5, 0);
targetText.y = 200;
LK.gui.top.addChild(targetText);
function getRandomGemType() {
// Higher levels have more gem types (more difficulty)
var availableTypes = Math.min(3 + Math.floor(currentLevel / 3), gemTypes.length);
return gemTypes[Math.floor(Math.random() * availableTypes)];
}
function createGem(x, y) {
var gemType = getRandomGemType();
var gem = new Gem(gemType);
gem.setGridPosition(x, y);
grid[x][y] = gem;
game.addChild(gem);
return gem;
}
function initializeGrid() {
// Set moves based on level difficulty
movesRemaining = Math.max(20, 40 - Math.floor(currentLevel / 2));
targetScore = currentLevel * 100 + (currentLevel - 1) * 50;
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
createGem(x, y);
}
}
// Remove initial matches
clearMatches(false);
}
function checkLevelComplete() {
if (LK.getScore() >= targetScore) {
// Level completed!
currentLevel++;
maxLevel = Math.max(maxLevel, currentLevel);
// Save progress
storage.currentLevel = currentLevel;
storage.maxLevel = maxLevel;
// Reset for next level
LK.setScore(0);
movesRemaining = Math.max(20, 40 - Math.floor(currentLevel / 2));
targetScore = currentLevel * 100 + (currentLevel - 1) * 50;
chainMultiplier = 1;
// Clear and regenerate grid for new level
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
if (grid[x][y]) {
grid[x][y].destroy();
grid[x][y] = null;
}
}
}
initializeGrid();
updateUI();
// Show level up message
LK.effects.flashScreen(0x00FF00, 1000);
}
}
function isValidPosition(x, y) {
return x >= 0 && x < 10 && y >= 0 && y < 10;
}
function swapGems(gem1, gem2) {
if (!gem1 || !gem2 || gem1.isAnimating || gem2.isAnimating) return false;
var tempX = gem1.gridX;
var tempY = gem1.gridY;
// Update grid positions
gem1.gridX = gem2.gridX;
gem1.gridY = gem2.gridY;
gem2.gridX = tempX;
gem2.gridY = tempY;
// Update grid array
grid[gem1.gridX][gem1.gridY] = gem1;
grid[gem2.gridX][gem2.gridY] = gem2;
// Animate to new positions
gameAnimating = true;
var animationsComplete = 0;
function checkMatches() {
if (animationsComplete === 2) {
LK.getSound('swap').play();
// Check for matches
var matches = findMatches();
if (matches.length > 0) {
movesRemaining--;
updateUI();
gameAnimating = false;
clearMatches(true);
} else {
// Deduct move for non-matching swap but keep gems in new positions
movesRemaining--;
updateUI();
gameAnimating = false;
}
}
}
gem1.animateToPosition(304 + gem1.gridX * 160, 526 + gem1.gridY * 160, function () {
animationsComplete++;
checkMatches();
});
gem2.animateToPosition(304 + gem2.gridX * 160, 526 + gem2.gridY * 160, function () {
animationsComplete++;
checkMatches();
});
return true;
}
function findMatches() {
var matches = [];
var checked = [];
// Initialize checked array
for (var x = 0; x < 10; x++) {
checked[x] = [];
for (var y = 0; y < 10; y++) {
checked[x][y] = false;
}
}
// Check horizontal matches
for (var y = 0; y < 10; y++) {
for (var x = 0; x < 8; x++) {
if (grid[x][y] && grid[x + 1][y] && grid[x + 2][y] && grid[x][y].gemType === grid[x + 1][y].gemType && grid[x][y].gemType === grid[x + 2][y].gemType) {
var matchLength = 3;
while (x + matchLength < 10 && grid[x + matchLength][y] && grid[x + matchLength][y].gemType === grid[x][y].gemType) {
matchLength++;
}
for (var i = 0; i < matchLength; i++) {
if (!checked[x + i][y]) {
matches.push({
x: x + i,
y: y
});
checked[x + i][y] = true;
}
}
x += matchLength - 1;
}
}
}
// Check vertical matches
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 8; y++) {
if (grid[x][y] && grid[x][y + 1] && grid[x][y + 2] && grid[x][y].gemType === grid[x][y + 1].gemType && grid[x][y].gemType === grid[x][y + 2].gemType) {
var matchLength = 3;
while (y + matchLength < 10 && grid[x][y + matchLength] && grid[x][y + matchLength].gemType === grid[x][y].gemType) {
matchLength++;
}
for (var i = 0; i < matchLength; i++) {
if (!checked[x][y + i]) {
matches.push({
x: x,
y: y + i
});
checked[x][y + i] = true;
}
}
y += matchLength - 1;
}
}
}
return matches;
}
function clearMatches(addScore) {
var matches = findMatches();
if (matches.length === 0) {
chainMultiplier = 1;
return false;
}
if (addScore) {
var points = matches.length * 10 * chainMultiplier;
LK.setScore(LK.getScore() + points);
chainMultiplier++;
LK.getSound('match').play();
}
// Remove matched gems
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (grid[match.x][match.y]) {
grid[match.x][match.y].destroy();
grid[match.x][match.y] = null;
}
}
// Drop gems down
gameAnimating = true;
var animationsRemaining = 0;
for (var x = 0; x < 10; x++) {
var writeIndex = 9;
for (var y = 9; y >= 0; y--) {
if (grid[x][y] !== null) {
if (writeIndex !== y) {
grid[x][writeIndex] = grid[x][y];
grid[x][y] = null;
grid[x][writeIndex].gridY = writeIndex;
animationsRemaining++;
grid[x][writeIndex].animateToPosition(304 + x * 160, 526 + writeIndex * 160, function () {
animationsRemaining--;
if (animationsRemaining === 0) {
fillEmptySpaces();
}
});
}
writeIndex--;
}
}
}
if (animationsRemaining === 0) {
fillEmptySpaces();
}
return true;
}
function fillEmptySpaces() {
var animationsRemaining = 0;
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
if (grid[x][y] === null) {
var gem = new Gem(getRandomGemType());
gem.gridX = x;
gem.gridY = y;
gem.x = 304 + x * 160;
gem.y = 526 + y * 160 - 1600;
grid[x][y] = gem;
game.addChild(gem);
animationsRemaining++;
gem.animateToPosition(304 + x * 160, 526 + y * 160, function () {
animationsRemaining--;
if (animationsRemaining === 0) {
gameAnimating = false;
// Check for new matches after falling
LK.setTimeout(function () {
clearMatches(true);
}, 100);
}
});
}
}
}
if (animationsRemaining === 0) {
gameAnimating = false;
LK.setTimeout(function () {
clearMatches(true);
}, 100);
}
}
function updateUI() {
scoreText.setText('Puan: ' + LK.getScore());
movesText.setText('Hamle: ' + movesRemaining);
levelText.setText('Seviye: ' + currentLevel);
targetText.setText('Hedef: ' + targetScore);
// Check level completion
checkLevelComplete();
// Check lose condition
if (movesRemaining <= 0 && LK.getScore() < targetScore) {
LK.showGameOver();
}
}
function areAdjacent(gem1, gem2) {
var dx = Math.abs(gem1.gridX - gem2.gridX);
var dy = Math.abs(gem1.gridY - gem2.gridY);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
game.down = function (x, y, obj) {
if (gameAnimating || movesRemaining <= 0) return;
// Find which gem was touched
var touchedGem = null;
for (var gx = 0; gx < 10; gx++) {
for (var gy = 0; gy < 10; gy++) {
if (grid[gx][gy]) {
var gemX = 304 + gx * 160;
var gemY = 526 + gy * 160;
var distance = Math.sqrt((x - gemX) * (x - gemX) + (y - gemY) * (y - gemY));
if (distance < 80) {
touchedGem = grid[gx][gy];
break;
}
}
}
if (touchedGem) break;
}
if (touchedGem) {
// If touching the same gem that's already selected, do nothing
if (selectedGem === touchedGem) {
return;
}
// Reset all gem scales first
for (var gx = 0; gx < 10; gx++) {
for (var gy = 0; gy < 10; gy++) {
if (grid[gx][gy]) {
grid[gx][gy].scaleX = 1;
grid[gx][gy].scaleY = 1;
}
}
}
// Select and scale the touched gem
selectedGem = touchedGem;
selectedGem.scaleX = 1.1;
selectedGem.scaleY = 1.1;
} else {
// Reset all gem scales if touching empty space
for (var gx = 0; gx < 10; gx++) {
for (var gy = 0; gy < 10; gy++) {
if (grid[gx][gy]) {
grid[gx][gy].scaleX = 1;
grid[gx][gy].scaleY = 1;
}
}
}
selectedGem = null;
}
};
game.up = function (x, y, obj) {
if (selectedGem) {
selectedGem.scaleX = 1;
selectedGem.scaleY = 1;
// Find gem at release position
var releaseGem = null;
var found = false;
for (var gx = 0; gx < 10 && !found; gx++) {
for (var gy = 0; gy < 10 && !found; gy++) {
if (grid[gx][gy] && grid[gx][gy] !== selectedGem) {
var gemX = 304 + gx * 160;
var gemY = 526 + gy * 160;
var distance = Math.sqrt((x - gemX) * (x - gemX) + (y - gemY) * (y - gemY));
if (distance < 80) {
releaseGem = grid[gx][gy];
found = true;
}
}
}
}
// Try to swap if gems are adjacent
if (releaseGem && areAdjacent(selectedGem, releaseGem)) {
swapGems(selectedGem, releaseGem);
}
selectedGem = null;
}
};
// Initialize the game
initializeGrid();
updateUI();
// Show current level at start
if (currentLevel > 1) {
LK.effects.flashScreen(0x0080FF, 500);
}
game.update = function () {
// Game loop updates handled by individual gem classes and tween animations
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Gem = Container.expand(function (gemType) {
var self = Container.call(this);
self.gemType = gemType;
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var gemGraphics = self.attachAsset(gemType, {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = 304 + gridX * 160;
self.y = 526 + gridY * 160;
};
self.animateToPosition = function (targetX, targetY, callback) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (callback) callback();
}
});
};
self.down = function (x, y, obj) {
// Selection is now handled in game.down to prevent conflicts
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1,
scaleY: 1
}));
var gemTypes = ['diamond', 'emerald', 'ruby', 'sapphire', 'topaz'];
var grid = [];
var selectedGem = null;
var gameAnimating = false;
var currentLevel = storage.currentLevel || 1;
var maxLevel = storage.maxLevel || 1;
var movesRemaining = 30;
var chainMultiplier = 1;
var targetScore = currentLevel * 100; // Score needed to advance
// Initialize grid array
for (var x = 0; x < 10; x++) {
grid[x] = [];
for (var y = 0; y < 10; y++) {
grid[x][y] = null;
}
}
// Create grid background
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
var gridCell = game.addChild(LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
x: 304 + x * 160,
y: 526 + y * 160
}));
}
}
// UI Elements
var scoreText = new Text2('Puan: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var movesText = new Text2('Hamle: 30', {
size: 65,
fill: 0xFFFF00
});
movesText.anchor.set(0.5, 0);
movesText.y = 80;
LK.gui.top.addChild(movesText);
var levelText = new Text2('Seviye: 1', {
size: 65,
fill: 0x00FF00
});
levelText.anchor.set(0.5, 0);
levelText.y = 140;
LK.gui.top.addChild(levelText);
var targetText = new Text2('Hedef: 100', {
size: 55,
fill: 0xFFFFFF
});
targetText.anchor.set(0.5, 0);
targetText.y = 200;
LK.gui.top.addChild(targetText);
function getRandomGemType() {
// Higher levels have more gem types (more difficulty)
var availableTypes = Math.min(3 + Math.floor(currentLevel / 3), gemTypes.length);
return gemTypes[Math.floor(Math.random() * availableTypes)];
}
function createGem(x, y) {
var gemType = getRandomGemType();
var gem = new Gem(gemType);
gem.setGridPosition(x, y);
grid[x][y] = gem;
game.addChild(gem);
return gem;
}
function initializeGrid() {
// Set moves based on level difficulty
movesRemaining = Math.max(20, 40 - Math.floor(currentLevel / 2));
targetScore = currentLevel * 100 + (currentLevel - 1) * 50;
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
createGem(x, y);
}
}
// Remove initial matches
clearMatches(false);
}
function checkLevelComplete() {
if (LK.getScore() >= targetScore) {
// Level completed!
currentLevel++;
maxLevel = Math.max(maxLevel, currentLevel);
// Save progress
storage.currentLevel = currentLevel;
storage.maxLevel = maxLevel;
// Reset for next level
LK.setScore(0);
movesRemaining = Math.max(20, 40 - Math.floor(currentLevel / 2));
targetScore = currentLevel * 100 + (currentLevel - 1) * 50;
chainMultiplier = 1;
// Clear and regenerate grid for new level
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
if (grid[x][y]) {
grid[x][y].destroy();
grid[x][y] = null;
}
}
}
initializeGrid();
updateUI();
// Show level up message
LK.effects.flashScreen(0x00FF00, 1000);
}
}
function isValidPosition(x, y) {
return x >= 0 && x < 10 && y >= 0 && y < 10;
}
function swapGems(gem1, gem2) {
if (!gem1 || !gem2 || gem1.isAnimating || gem2.isAnimating) return false;
var tempX = gem1.gridX;
var tempY = gem1.gridY;
// Update grid positions
gem1.gridX = gem2.gridX;
gem1.gridY = gem2.gridY;
gem2.gridX = tempX;
gem2.gridY = tempY;
// Update grid array
grid[gem1.gridX][gem1.gridY] = gem1;
grid[gem2.gridX][gem2.gridY] = gem2;
// Animate to new positions
gameAnimating = true;
var animationsComplete = 0;
function checkMatches() {
if (animationsComplete === 2) {
LK.getSound('swap').play();
// Check for matches
var matches = findMatches();
if (matches.length > 0) {
movesRemaining--;
updateUI();
gameAnimating = false;
clearMatches(true);
} else {
// Deduct move for non-matching swap but keep gems in new positions
movesRemaining--;
updateUI();
gameAnimating = false;
}
}
}
gem1.animateToPosition(304 + gem1.gridX * 160, 526 + gem1.gridY * 160, function () {
animationsComplete++;
checkMatches();
});
gem2.animateToPosition(304 + gem2.gridX * 160, 526 + gem2.gridY * 160, function () {
animationsComplete++;
checkMatches();
});
return true;
}
function findMatches() {
var matches = [];
var checked = [];
// Initialize checked array
for (var x = 0; x < 10; x++) {
checked[x] = [];
for (var y = 0; y < 10; y++) {
checked[x][y] = false;
}
}
// Check horizontal matches
for (var y = 0; y < 10; y++) {
for (var x = 0; x < 8; x++) {
if (grid[x][y] && grid[x + 1][y] && grid[x + 2][y] && grid[x][y].gemType === grid[x + 1][y].gemType && grid[x][y].gemType === grid[x + 2][y].gemType) {
var matchLength = 3;
while (x + matchLength < 10 && grid[x + matchLength][y] && grid[x + matchLength][y].gemType === grid[x][y].gemType) {
matchLength++;
}
for (var i = 0; i < matchLength; i++) {
if (!checked[x + i][y]) {
matches.push({
x: x + i,
y: y
});
checked[x + i][y] = true;
}
}
x += matchLength - 1;
}
}
}
// Check vertical matches
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 8; y++) {
if (grid[x][y] && grid[x][y + 1] && grid[x][y + 2] && grid[x][y].gemType === grid[x][y + 1].gemType && grid[x][y].gemType === grid[x][y + 2].gemType) {
var matchLength = 3;
while (y + matchLength < 10 && grid[x][y + matchLength] && grid[x][y + matchLength].gemType === grid[x][y].gemType) {
matchLength++;
}
for (var i = 0; i < matchLength; i++) {
if (!checked[x][y + i]) {
matches.push({
x: x,
y: y + i
});
checked[x][y + i] = true;
}
}
y += matchLength - 1;
}
}
}
return matches;
}
function clearMatches(addScore) {
var matches = findMatches();
if (matches.length === 0) {
chainMultiplier = 1;
return false;
}
if (addScore) {
var points = matches.length * 10 * chainMultiplier;
LK.setScore(LK.getScore() + points);
chainMultiplier++;
LK.getSound('match').play();
}
// Remove matched gems
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (grid[match.x][match.y]) {
grid[match.x][match.y].destroy();
grid[match.x][match.y] = null;
}
}
// Drop gems down
gameAnimating = true;
var animationsRemaining = 0;
for (var x = 0; x < 10; x++) {
var writeIndex = 9;
for (var y = 9; y >= 0; y--) {
if (grid[x][y] !== null) {
if (writeIndex !== y) {
grid[x][writeIndex] = grid[x][y];
grid[x][y] = null;
grid[x][writeIndex].gridY = writeIndex;
animationsRemaining++;
grid[x][writeIndex].animateToPosition(304 + x * 160, 526 + writeIndex * 160, function () {
animationsRemaining--;
if (animationsRemaining === 0) {
fillEmptySpaces();
}
});
}
writeIndex--;
}
}
}
if (animationsRemaining === 0) {
fillEmptySpaces();
}
return true;
}
function fillEmptySpaces() {
var animationsRemaining = 0;
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
if (grid[x][y] === null) {
var gem = new Gem(getRandomGemType());
gem.gridX = x;
gem.gridY = y;
gem.x = 304 + x * 160;
gem.y = 526 + y * 160 - 1600;
grid[x][y] = gem;
game.addChild(gem);
animationsRemaining++;
gem.animateToPosition(304 + x * 160, 526 + y * 160, function () {
animationsRemaining--;
if (animationsRemaining === 0) {
gameAnimating = false;
// Check for new matches after falling
LK.setTimeout(function () {
clearMatches(true);
}, 100);
}
});
}
}
}
if (animationsRemaining === 0) {
gameAnimating = false;
LK.setTimeout(function () {
clearMatches(true);
}, 100);
}
}
function updateUI() {
scoreText.setText('Puan: ' + LK.getScore());
movesText.setText('Hamle: ' + movesRemaining);
levelText.setText('Seviye: ' + currentLevel);
targetText.setText('Hedef: ' + targetScore);
// Check level completion
checkLevelComplete();
// Check lose condition
if (movesRemaining <= 0 && LK.getScore() < targetScore) {
LK.showGameOver();
}
}
function areAdjacent(gem1, gem2) {
var dx = Math.abs(gem1.gridX - gem2.gridX);
var dy = Math.abs(gem1.gridY - gem2.gridY);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
game.down = function (x, y, obj) {
if (gameAnimating || movesRemaining <= 0) return;
// Find which gem was touched
var touchedGem = null;
for (var gx = 0; gx < 10; gx++) {
for (var gy = 0; gy < 10; gy++) {
if (grid[gx][gy]) {
var gemX = 304 + gx * 160;
var gemY = 526 + gy * 160;
var distance = Math.sqrt((x - gemX) * (x - gemX) + (y - gemY) * (y - gemY));
if (distance < 80) {
touchedGem = grid[gx][gy];
break;
}
}
}
if (touchedGem) break;
}
if (touchedGem) {
// If touching the same gem that's already selected, do nothing
if (selectedGem === touchedGem) {
return;
}
// Reset all gem scales first
for (var gx = 0; gx < 10; gx++) {
for (var gy = 0; gy < 10; gy++) {
if (grid[gx][gy]) {
grid[gx][gy].scaleX = 1;
grid[gx][gy].scaleY = 1;
}
}
}
// Select and scale the touched gem
selectedGem = touchedGem;
selectedGem.scaleX = 1.1;
selectedGem.scaleY = 1.1;
} else {
// Reset all gem scales if touching empty space
for (var gx = 0; gx < 10; gx++) {
for (var gy = 0; gy < 10; gy++) {
if (grid[gx][gy]) {
grid[gx][gy].scaleX = 1;
grid[gx][gy].scaleY = 1;
}
}
}
selectedGem = null;
}
};
game.up = function (x, y, obj) {
if (selectedGem) {
selectedGem.scaleX = 1;
selectedGem.scaleY = 1;
// Find gem at release position
var releaseGem = null;
var found = false;
for (var gx = 0; gx < 10 && !found; gx++) {
for (var gy = 0; gy < 10 && !found; gy++) {
if (grid[gx][gy] && grid[gx][gy] !== selectedGem) {
var gemX = 304 + gx * 160;
var gemY = 526 + gy * 160;
var distance = Math.sqrt((x - gemX) * (x - gemX) + (y - gemY) * (y - gemY));
if (distance < 80) {
releaseGem = grid[gx][gy];
found = true;
}
}
}
}
// Try to swap if gems are adjacent
if (releaseGem && areAdjacent(selectedGem, releaseGem)) {
swapGems(selectedGem, releaseGem);
}
selectedGem = null;
}
};
// Initialize the game
initializeGrid();
updateUI();
// Show current level at start
if (currentLevel > 1) {
LK.effects.flashScreen(0x0080FF, 500);
}
game.update = function () {
// Game loop updates handled by individual gem classes and tween animations
};