User prompt
If the player collects 5000 points after pressing the go button, the game will not end and a new screen will open with the same character and speech bubble.
User prompt
Go! Butonuna bastıktan sonra story modda görüne herhangi bir yazı buton ve görüntü gözükmesin direk oyuna aktarsın
User prompt
Back butonunu alt kısimı yerleştir ve yanına "Go!" adlı bir buton yerleştir
User prompt
Konuşma yazısını çok az bir miktar alt kısma yaklaştır çok az bir miktar
User prompt
Story modda bulunan karakteri alt kısıma yerlestir ve konuşma baloncuğunu büyüt
User prompt
Yazı gözükmüyor alt alta yaz
User prompt
Story Mode butonuna tıkladıktan sonra gelen konuşma yazısını sil yerine "Hello, I've been stuck in this universe for a long time. My chance of escape depends on you. If you win this game, I can escape, but remember, you only have one chance." Yaz
User prompt
Story Mode butonuna bastıktan sonra gelen "Back" butonuna tıklayınca ana menüye dönülücek ve story mode butonuna tıklayınca görünmeyen bütün butonlar tekrar görülebilicek
User prompt
Butona tıklayınca ana ekranda bulunan hiçbir sey gozukmucek
User prompt
Extreme mode butonunun altına bir buton ekle bu butona tıklayınca butonlar gözükmücek sadece arka plan ve çıkan karakter ve karakterin konuşma balonu gözükücek
User prompt
Delete the button
User prompt
Bu butona tıklayınca bir ses çalsın
User prompt
Biraz daha yukarıda olsun ve yazı olmasın butonda
User prompt
Made by mavus dondurma yazısının üstüne kendine ait bir asseti bir buton yerleştir
User prompt
Dunyayı sil Made by mavus dondurma ve Version 1.0 yazılarını sol alta al
User prompt
MADE BY MAVUS DONDURMA ve Version 1.0 yazılarını sol üst köşeye al yeşil ve kırmızı gülen top butonlarını how to play butonunun üstüne aralarında boşluk olacak şekilde yerleştir
User prompt
Ekranın sol alt köşesine dünya yerleştir kendi etrafında dönmesin ama
User prompt
Ay ve dünyayı kaldir
User prompt
Let the moon and earth rotate more realistically ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Place the Earth and the Moon rotating around itself in the background and have them appear as separate assets. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Extreme Mod açıldığinda ekstra olarak ekran sarsılmaya başlasın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yeşil butonu assets kısmına yerlestir
User prompt
Yeşil butona tıklandığında ekran sarsıntisı sona ersin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: window.open is not a function' in or related to this line: 'var newWindow = window.open('about:blank', '_blank');' Line Number: 800
User prompt
İkı buton arasında biraz boşluk olsun ve yeşil topa tıklandığinda tıpkı diğer butonlara tıklandığında olduğu gibi bir sekme açılsın
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BlankScreen = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 9,
scaleY: 12
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.95;
self.addChild(background);
var titleText = new Text2('JUST JOKING', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
// Add some content to the blank screen
var contentText = new Text2('Click the green button', {
size: 80,
fill: 0x00FF00
});
contentText.anchor.set(0.5, 0.5);
contentText.x = 1024;
contentText.y = 800;
self.addChild(contentText);
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 2300;
self.addChild(backButton);
var backText = new Text2('BACK', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2300;
self.addChild(backText);
backButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
hideBlankScreen();
};
return self;
});
var FeedbackScreen = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 9,
scaleY: 12
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.95;
self.addChild(background);
var titleText = new Text2('FEEDBACK', {
size: 120,
fill: 0xFFAA00
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
// Feedback form instructions
var instructions = ['We would love to hear your thoughts!', '', 'What did you think of the game?', '• Was it fun and engaging?', '• Were the controls easy to use?', '• How was the difficulty level?', '• Any suggestions for improvement?', '', 'Thank you for playing MAVUS BABA!', 'Your feedback helps us make better games.', '', 'Contact us at:', 'INSTAGRAM: abdurrahim_scu'];
var yOffset = 650;
for (var i = 0; i < instructions.length; i++) {
var instructionText = new Text2(instructions[i], {
size: instructions[i] === '' ? 30 : instructions[i].startsWith('Contact') || instructions[i].includes('@') ? 50 : instructions[i].startsWith('•') ? 45 : instructions[i] === 'We would love to hear your thoughts!' ? 70 : instructions[i] === 'Thank you for playing MAVUS BABA!' ? 65 : 55,
fill: instructions[i].includes('@') ? 0x44FF44 : instructions[i].startsWith('•') ? 0xFFFF44 : instructions[i] === 'Thank you for playing MAVUS BABA!' ? 0xFFAA00 : 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = yOffset + i * 80;
self.addChild(instructionText);
}
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 2300;
self.addChild(backButton);
var backText = new Text2('BACK', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2300;
self.addChild(backText);
backButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
hideFeedbackScreen();
};
return self;
});
var Gem = Container.expand(function () {
var self = Container.call(this);
self.gemType = 0;
self.gridX = 0;
self.gridY = 0;
self.graphics = null;
self.isSelected = false;
self.isMatched = false;
self.isFalling = false;
self.isBomb = false;
self.init = function (type, gx, gy) {
self.gemType = type;
self.gridX = gx;
self.gridY = gy;
var gemTypes = ['gemRed', 'gemBlue', 'gemGreen', 'gemYellow', 'gemPurple', 'gemOrange', 'gemBomb'];
if (type === 6) {
self.isBomb = true;
}
self.graphics = self.attachAsset(gemTypes[type], {
anchorX: 0.5,
anchorY: 0.5
});
self.updatePosition();
};
self.updatePosition = function () {
var startX = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var startY = 400;
self.x = startX + self.gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = startY + self.gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.graphics.alpha = 0.7;
tween(self.graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200
});
} else {
self.graphics.alpha = 1.0;
tween(self.graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
};
self.fallTo = function (newY, callback) {
self.isFalling = true;
self.gridY = newY;
var newPosY = 400 + newY * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
y: newPosY
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.isFalling = false;
if (callback) callback();
}
});
};
self.destroy = function () {
self.isMatched = true;
// Play explosion sound effect
LK.getSound('explosion').play();
// Create explosion effect with scaling and rotation
tween(self.graphics, {
scaleX: 1.8,
scaleY: 1.8,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
self.explodeBomb = function () {
if (!self.isBomb) return;
// Create dramatic bomb explosion effect
tween(self.graphics, {
scaleX: 3,
scaleY: 3,
rotation: Math.PI * 4,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
// Add pulsing effect before explosion
tween(self.graphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
});
// Mark gems in 3x3 area for destruction
var gemsToDestroy = [];
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
var targetX = self.gridX + dx;
var targetY = self.gridY + dy;
if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
if (grid[targetX][targetY] && !grid[targetX][targetY].isMatched) {
gemsToDestroy.push({
x: targetX,
y: targetY
});
}
}
}
}
// Destroy gems with delay and explosion effects
for (var i = 0; i < gemsToDestroy.length; i++) {
(function (destroyData, index) {
LK.setTimeout(function () {
if (grid[destroyData.x][destroyData.y]) {
var gemToExplode = grid[destroyData.x][destroyData.y];
// Play explosion sound for each destroyed gem
LK.getSound('explosion').play();
// Create explosion effect for each gem
tween(gemToExplode.graphics, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * (1 + Math.random()),
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (gemToExplode.parent) {
gemToExplode.parent.removeChild(gemToExplode);
}
}
});
grid[destroyData.x][destroyData.y] = null;
}
}, i * 80);
})(gemsToDestroy[i], i);
}
// Add explosion score - in extreme mode, only count gems of the selected type
var scoringGems = gemsToDestroy.length;
if (gameMode === 'extreme') {
scoringGems = 0;
for (var j = 0; j < gemsToDestroy.length; j++) {
var destroyData = gemsToDestroy[j];
if (grid[destroyData.x] && grid[destroyData.x][destroyData.y] && grid[destroyData.x][destroyData.y].gemType === extremeGemType) {
scoringGems++;
}
}
}
var explosionScore = scoringGems * 50 * multiplier;
score += explosionScore;
updateScore();
// Play explosion sound
LK.getSound('explosion').play();
// Wait for all destruction then cascade and fill empty spaces
LK.setTimeout(function () {
cascadeGems();
// Ensure empty spaces are filled after bomb explosion
LK.setTimeout(function () {
fillEmptySpaces();
}, 100);
}, 500);
};
self.down = function (x, y, obj) {
if (!self.isFalling && !isProcessing) {
if (self.isBomb) {
isProcessing = true;
self.explodeBomb();
} else {
selectGem(self);
}
}
};
return self;
});
var HowToPlayScreen = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 9,
scaleY: 12
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.95;
self.addChild(background);
var titleText = new Text2('HOW TO PLAY', {
size: 120,
fill: 0x44FF44
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
// Game instructions text
var instructions = ['Match 3 or more gems of the same color', 'to clear them and earn points!', '', '• Tap gems to select them', '• Select adjacent gems to swap', '• Create cascades for bonus points', '• Match 4+ gems to create bombs', '• Bombs destroy 3x3 areas', '• Score multiplier increases with points', '• You have 60 seconds to score big!', '', 'EXTREME MODE:', 'Only one gem type scores points!'];
var yOffset = 650;
for (var i = 0; i < instructions.length; i++) {
var instructionText = new Text2(instructions[i], {
size: instructions[i] === '' ? 30 : instructions[i].startsWith('EXTREME') ? 80 : 55,
fill: instructions[i].startsWith('EXTREME') ? 0xFF4444 : instructions[i].startsWith('•') ? 0xFFFF44 : 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = yOffset + i * 90;
self.addChild(instructionText);
}
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 2300;
self.addChild(backButton);
var backText = new Text2('BACK', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2300;
self.addChild(backText);
backButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
hideHowToPlayScreen();
};
return self;
});
var OptionsMenu = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 6
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.9;
self.addChild(background);
var titleText = new Text2('Options', {
size: 150,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
self.addChild(titleText);
// Music Volume Toggle Button
var musicVolumeButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 0.6
});
musicVolumeButton.x = 1024;
musicVolumeButton.y = 1000;
self.addChild(musicVolumeButton);
// Get current music volume state
var isMusicOn = storage.musicVolume === undefined ? true : storage.musicVolume > 0;
var musicVolumeText = new Text2(isMusicOn ? 'Music: ON' : 'Music: OFF', {
size: 80,
fill: 0xFFFFFF
});
musicVolumeText.anchor.set(0.5, 0.5);
musicVolumeText.x = 1024;
musicVolumeText.y = 1000;
self.addChild(musicVolumeText);
musicVolumeButton.down = function (x, y, obj) {
// Toggle music volume
var currentVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
if (currentVolume > 0) {
// Turn music off
storage.musicVolume = 0;
musicVolumeText.setText('Music: OFF');
LK.stopMusic();
} else {
// Turn music on
storage.musicVolume = 1.0;
musicVolumeText.setText('Music: ON');
// Play appropriate music based on game state
if (gameState === 'playing') {
LK.playMusic('background', {
fade: {
start: 0,
end: 0.9,
duration: 500
}
});
} else if (gameState === 'menu' || gameState === 'options') {
LK.playMusic('background', {
fade: {
start: 0,
end: 0.8,
duration: 500
}
});
}
}
};
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 1200;
self.addChild(backButton);
var backText = new Text2('Back', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1200;
self.addChild(backText);
backButton.down = function (x, y, obj) {
hideOptionsMenu();
};
return self;
});
var StartScreen = Container.expand(function () {
var self = Container.call(this);
// Create animated star background
var stars = [];
for (var i = 0; i < 50; i++) {
var star = self.attachAsset('starBg', {
anchorX: 0.5,
anchorY: 0.5
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
stars.push(star);
// Animate each star with twinkling effect
tween(star, {
alpha: Math.random() * 0.3 + 0.1
}, {
duration: Math.random() * 2000 + 1000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
// Add gentle floating movement
tween(star, {
y: star.y + (Math.random() * 100 - 50)
}, {
duration: Math.random() * 4000 + 2000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
// Create 3D effect with shadow layers
var titleShadow3 = new Text2('MAVUS BABA', {
size: 200,
fill: 0x000000
});
titleShadow3.anchor.set(0.5, 0.5);
titleShadow3.x = 1032;
titleShadow3.y = 808;
self.addChild(titleShadow3);
var titleShadow2 = new Text2('MAVUS BABA', {
size: 200,
fill: 0x333333
});
titleShadow2.anchor.set(0.5, 0.5);
titleShadow2.x = 1028;
titleShadow2.y = 804;
self.addChild(titleShadow2);
var titleShadow1 = new Text2('MAVUS BABA', {
size: 200,
fill: 0x666666
});
titleShadow1.anchor.set(0.5, 0.5);
titleShadow1.x = 1026;
titleShadow1.y = 802;
self.addChild(titleShadow1);
var titleText = new Text2('MAVUS BABA', {
size: 200,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
self.addChild(titleText);
// Add 3D glow animation
tween(titleText, {
alpha: 0.8
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
alpha: 1.0
}, {
duration: 1500,
easing: tween.easeInOut
});
}
});
var startButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
startButton.x = 1024;
startButton.y = 1200;
self.addChild(startButton);
// Create 3D effect for Start text
var startShadow2 = new Text2('START', {
size: 100,
fill: 0x000000
});
startShadow2.anchor.set(0.5, 0.5);
startShadow2.x = 1028;
startShadow2.y = 1204;
self.addChild(startShadow2);
var startShadow1 = new Text2('START', {
size: 100,
fill: 0x444444
});
startShadow1.anchor.set(0.5, 0.5);
startShadow1.x = 1026;
startShadow1.y = 1202;
self.addChild(startShadow1);
var startText = new Text2('START', {
size: 100,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = 1024;
startText.y = 1200;
self.addChild(startText);
var optionsButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
optionsButton.x = 1024;
optionsButton.y = 1500;
self.addChild(optionsButton);
// Create 3D effect for Options text
var optionsShadow2 = new Text2('OPTIONS', {
size: 100,
fill: 0x000000
});
optionsShadow2.anchor.set(0.5, 0.5);
optionsShadow2.x = 1028;
optionsShadow2.y = 1504;
self.addChild(optionsShadow2);
var optionsShadow1 = new Text2('OPTIONS', {
size: 100,
fill: 0x444444
});
optionsShadow1.anchor.set(0.5, 0.5);
optionsShadow1.x = 1026;
optionsShadow1.y = 1502;
self.addChild(optionsShadow1);
var optionsText = new Text2('OPTIONS', {
size: 100,
fill: 0xFFFFFF
});
optionsText.anchor.set(0.5, 0.5);
optionsText.x = 1024;
optionsText.y = 1500;
self.addChild(optionsText);
// Add "MADE BY MAVUS DONDURMA" text to bottom left corner
var madeByText = new Text2('MADE BY MAVUS DONDURMA', {
size: 60,
fill: 0xCCCCCC
});
madeByText.anchor.set(0, 1);
madeByText.x = 150;
madeByText.y = 2632;
self.addChild(madeByText);
// Add version text under "Made by Mavus Dondurma"
var versionText = new Text2('Version 1.0', {
size: 40,
fill: 0x888888
});
versionText.anchor.set(0, 1);
versionText.x = 150;
versionText.y = 2680;
self.addChild(versionText);
startButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
startGame();
};
optionsButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
showOptionsMenu();
};
var extremeButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
extremeButton.x = 1024;
extremeButton.y = 1800;
self.addChild(extremeButton);
// Create 3D effect for Extreme Mode text
var extremeShadow2 = new Text2('EXTREME MODE', {
size: 80,
fill: 0x000000
});
extremeShadow2.anchor.set(0.5, 0.5);
extremeShadow2.x = 1028;
extremeShadow2.y = 1804;
self.addChild(extremeShadow2);
var extremeShadow1 = new Text2('EXTREME MODE', {
size: 80,
fill: 0x444444
});
extremeShadow1.anchor.set(0.5, 0.5);
extremeShadow1.x = 1026;
extremeShadow1.y = 1802;
self.addChild(extremeShadow1);
var extremeText = new Text2('EXTREME MODE', {
size: 80,
fill: 0xFF4444
});
extremeText.anchor.set(0.5, 0.5);
extremeText.x = 1024;
extremeText.y = 1800;
self.addChild(extremeText);
extremeButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
gameMode = 'extreme';
startGame();
};
// How to Play button at bottom right
var howToPlayButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 0.7
});
howToPlayButton.x = 1700;
howToPlayButton.y = 2400;
self.addChild(howToPlayButton);
// Create 3D effect for How to Play text
var howToPlayShadow2 = new Text2('HOW TO PLAY', {
size: 60,
fill: 0x000000
});
howToPlayShadow2.anchor.set(0.5, 0.5);
howToPlayShadow2.x = 1704;
howToPlayShadow2.y = 2404;
self.addChild(howToPlayShadow2);
var howToPlayShadow1 = new Text2('HOW TO PLAY', {
size: 60,
fill: 0x444444
});
howToPlayShadow1.anchor.set(0.5, 0.5);
howToPlayShadow1.x = 1702;
howToPlayShadow1.y = 2402;
self.addChild(howToPlayShadow1);
var howToPlayText = new Text2('HOW TO PLAY', {
size: 60,
fill: 0x44FF44
});
howToPlayText.anchor.set(0.5, 0.5);
howToPlayText.x = 1700;
howToPlayText.y = 2400;
self.addChild(howToPlayText);
howToPlayButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
showHowToPlayScreen();
};
// Feedback button at bottom right under How to Play
var feedbackButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 0.7
});
feedbackButton.x = 1700;
feedbackButton.y = 2550;
self.addChild(feedbackButton);
// Create 3D effect for Feedback text
var feedbackShadow2 = new Text2('FEEDBACK', {
size: 60,
fill: 0x000000
});
feedbackShadow2.anchor.set(0.5, 0.5);
feedbackShadow2.x = 1704;
feedbackShadow2.y = 2554;
self.addChild(feedbackShadow2);
var feedbackShadow1 = new Text2('FEEDBACK', {
size: 60,
fill: 0x444444
});
feedbackShadow1.anchor.set(0.5, 0.5);
feedbackShadow1.x = 1702;
feedbackShadow1.y = 2552;
self.addChild(feedbackShadow1);
var feedbackText = new Text2('FEEDBACK', {
size: 60,
fill: 0xFFAA00
});
feedbackText.anchor.set(0.5, 0.5);
feedbackText.x = 1700;
feedbackText.y = 2550;
self.addChild(feedbackText);
feedbackButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
showFeedbackScreen();
};
// Green smiley ball button above blank button
var greenButton = LK.getAsset('redSmileyBall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
greenButton.x = 350;
greenButton.y = 2200;
greenButton.tint = 0x00FF00; // Make it green
self.addChild(greenButton);
greenButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
// Open new tab/window
var newWindow = window.open('about:blank', '_blank');
if (newWindow) {
newWindow.document.write('<html><head><title>New Tab</title></head><body><h1>Hello from Green Button!</h1><p>This tab was opened by clicking the green smiley ball.</p></body></html>');
}
};
// Blank button with red smiley ball
var blankButton = LK.getAsset('redSmileyBall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
blankButton.x = 350;
blankButton.y = 2450;
self.addChild(blankButton);
// Face features removed - now just a plain red ball
blankButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
// Start continuous screen shake effect
startContinuousShake();
showBlankScreen();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 200;
var GEM_TYPES = 6;
var BOMB_TYPE = 6;
var grid = [];
var selectedGem = null;
var score = 0;
var multiplier = 1;
var isProcessing = false;
var cascadeCount = 0;
var gameTimeLeft = 60;
var gameTimer = null;
var timerTxt = null;
var gameMode = 'normal'; // 'normal' or 'extreme'
var extremeGemType = 0; // Only this gem type scores points in extreme mode
var extremeGemTxt = null;
// Game state management
var gameState = 'menu'; // 'menu', 'playing', 'options'
var startScreen = null;
var optionsMenu = null;
var gameElements = [];
// Spaceship for background animation
var spaceship = null;
// UFO for background animation
var ufo = null;
// Score display will be created when game starts
var scoreTxt = null;
var multiplierTxt = null;
// Initialize grid
function initializeGrid() {
var startX = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var startY = 400;
// Create background cells
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var cell = LK.getAsset('gridCell', {
anchorX: 0,
anchorY: 0,
alpha: 0.95
});
cell.x = startX + x * CELL_SIZE;
cell.y = startY + y * CELL_SIZE;
game.addChild(cell);
}
}
// Initialize grid array
for (var x = 0; x < GRID_SIZE; x++) {
grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
grid[x][y] = null;
}
}
// Fill grid with gems
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
createGem(x, y);
}
}
// Remove initial matches
removeInitialMatches();
}
function createGem(x, y) {
var gem = new Gem();
var gemType = Math.floor(Math.random() * GEM_TYPES);
gem.init(gemType, x, y);
grid[x][y] = gem;
game.addChild(gem);
return gem;
}
function removeInitialMatches() {
var hasMatches = true;
var attempts = 0;
while (hasMatches && attempts < 50) {
hasMatches = false;
attempts++;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && hasMatchAt(x, y)) {
// Regenerate this gem
var oldGem = grid[x][y];
if (oldGem.parent) {
oldGem.parent.removeChild(oldGem);
}
createGem(x, y);
hasMatches = true;
}
}
}
}
}
function selectGem(gem) {
if (selectedGem === gem) {
// Deselect
selectedGem.setSelected(false);
selectedGem = null;
return;
}
if (selectedGem === null) {
// First selection
selectedGem = gem;
gem.setSelected(true);
} else {
// Second selection - check if adjacent
if (areAdjacent(selectedGem, gem)) {
swapGems(selectedGem, gem);
}
selectedGem.setSelected(false);
selectedGem = null;
}
}
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;
}
function swapGems(gem1, gem2) {
if (isProcessing) return;
isProcessing = true;
// Store positions
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 swap
var gem1NewX = gem1.x;
var gem1NewY = gem1.y;
gem1.updatePosition();
var gem2NewX = gem2.x;
var gem2NewY = gem2.y;
gem2.updatePosition();
gem1.x = gem2NewX;
gem1.y = gem2NewY;
gem2.x = gem1NewX;
gem2.y = gem1NewY;
tween(gem1, {
x: gem1NewX,
y: gem1NewY
}, {
duration: 300
});
tween(gem2, {
x: gem2NewX,
y: gem2NewY
}, {
duration: 300,
onFinish: function onFinish() {
checkForMatches();
}
});
}
function hasMatchAt(x, y) {
if (!grid[x] || !grid[x][y]) return false;
var gemType = grid[x][y].gemType;
// Check horizontal
var hCount = 1;
// Check left
for (var i = x - 1; i >= 0 && grid[i][y] && grid[i][y].gemType === gemType; i--) {
hCount++;
}
// Check right
for (var i = x + 1; i < GRID_SIZE && grid[i][y] && grid[i][y].gemType === gemType; i++) {
hCount++;
}
if (hCount >= 3) return true;
// Check vertical
var vCount = 1;
// Check up
for (var i = y - 1; i >= 0 && grid[x][i] && grid[x][i].gemType === gemType; i--) {
vCount++;
}
// Check down
for (var i = y + 1; i < GRID_SIZE && grid[x][i] && grid[x][i].gemType === gemType; i++) {
vCount++;
}
return vCount >= 3;
}
function checkForMatches() {
var matches = [];
// Find all matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && hasMatchAt(x, y)) {
matches.push({
x: x,
y: y
});
}
}
}
if (matches.length > 0) {
cascadeCount++;
LK.getSound('match').play();
// Calculate score - in extreme mode, only count matches of the selected gem type
var scoringMatches = matches;
if (gameMode === 'extreme') {
scoringMatches = [];
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (grid[match.x] && grid[match.x][match.y] && grid[match.x][match.y].gemType === extremeGemType) {
scoringMatches.push(match);
}
}
}
var points = scoringMatches.length * 10 * multiplier * cascadeCount;
score += points;
updateScore();
// Create bomb if match is 4 or more gems
var shouldCreateBomb = matches.length >= 4;
var bombPosition = null;
if (shouldCreateBomb && matches.length > 0) {
bombPosition = matches[Math.floor(Math.random() * matches.length)];
}
// Mark matched gems for destruction
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;
}
}
// Create bomb after destruction
if (shouldCreateBomb && bombPosition) {
LK.setTimeout(function () {
if (grid[bombPosition.x][bombPosition.y] === null) {
var bomb = new Gem();
bomb.init(BOMB_TYPE, bombPosition.x, bombPosition.y);
grid[bombPosition.x][bombPosition.y] = bomb;
game.addChild(bomb);
// Animate bomb creation
bomb.graphics.scaleX = 0;
bomb.graphics.scaleY = 0;
tween(bomb.graphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
}
}, 200);
}
// Wait for destruction animation then cascade
LK.setTimeout(function () {
cascadeGems();
}, 400);
} else {
cascadeCount = 0;
isProcessing = false;
}
}
function cascadeGems() {
var needsCascade = false;
var fallPromises = 0;
// Process each column from left to right
for (var x = 0; x < GRID_SIZE; x++) {
// Compact the column - move all existing gems down to fill gaps
var compactedGems = [];
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] !== null) {
compactedGems.push(grid[x][y]);
grid[x][y] = null;
}
}
// Place compacted gems at the bottom of the column
var startY = GRID_SIZE - compactedGems.length;
for (var i = 0; i < compactedGems.length; i++) {
var gem = compactedGems[i];
var newY = startY + i;
var oldY = gem.gridY;
if (oldY !== newY) {
needsCascade = true;
grid[x][newY] = gem;
fallPromises++;
gem.fallTo(newY, function () {
fallPromises--;
if (fallPromises === 0) {
// Always fill empty spaces after cascading
fillEmptySpaces();
}
});
} else {
// Gem doesn't need to move
grid[x][newY] = gem;
}
}
}
// Always ensure empty spaces are filled, regardless of cascade
fillEmptySpaces();
if (needsCascade) {
LK.getSound('cascade').play();
}
}
function fillEmptySpaces() {
var newGemsCreated = 0;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] === null) {
createGem(x, y);
newGemsCreated++;
// Start gem above the screen and animate it falling
var startY = 400 - newGemsCreated * CELL_SIZE;
grid[x][y].y = startY;
tween(grid[x][y], {
y: 400 + y * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 500 + newGemsCreated * 50,
easing: tween.bounceOut
});
}
}
}
// Check for new matches after a delay
LK.setTimeout(function () {
checkForMatches();
}, 600);
}
function updateScore() {
if (scoreTxt) {
scoreTxt.setText('Score: ' + score);
}
// Update multiplier based on score
var newMultiplier = 1;
if (score >= 2500) newMultiplier = 5;else if (score >= 1000) newMultiplier = 4;else if (score >= 500) newMultiplier = 3;else if (score >= 100) newMultiplier = 2;
if (newMultiplier !== multiplier) {
multiplier = newMultiplier;
if (multiplierTxt) {
multiplierTxt.setText('Multiplier: x' + multiplier);
}
LK.effects.flashScreen(0x00ff00, 500);
}
// Win condition
if (score >= 5000) {
LK.showYouWin();
}
}
// Start continuous shake when game opens
startContinuousShake();
// Initialize start screen instead of game
showStartScreen();
game.update = function () {
// Game loop - handle any continuous updates here
};
function showStartScreen() {
gameState = 'menu';
gameMode = 'normal'; // Reset to normal mode when returning to menu
if (startScreen) {
game.removeChild(startScreen);
}
// Clear game timer if it exists
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
// Clear all game elements when returning to menu
for (var i = 0; i < gameElements.length; i++) {
if (gameElements[i].parent) {
gameElements[i].parent.removeChild(gameElements[i]);
}
}
gameElements = [];
// Clear grid elements
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x] && grid[x][y] && grid[x][y].parent) {
grid[x][y].parent.removeChild(grid[x][y]);
}
}
}
// Clear all children from game to ensure clean slate
while (game.children.length > 0) {
game.removeChild(game.children[0]);
}
startScreen = new StartScreen();
game.addChild(startScreen);
// Start spaceship animation
createSpaceship();
// Start UFO animation
createUfo();
// Start background music for start screen
var musicVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
if (musicVolume > 0) {
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.8,
duration: 2000
}
});
}
}
function startGame() {
gameState = 'playing';
if (startScreen) {
game.removeChild(startScreen);
startScreen = null;
}
if (optionsMenu) {
game.removeChild(optionsMenu);
optionsMenu = null;
}
// Clear any existing game elements
for (var i = 0; i < gameElements.length; i++) {
if (gameElements[i].parent) {
gameElements[i].parent.removeChild(gameElements[i]);
}
}
gameElements = [];
// Reset game state
grid = [];
selectedGem = null;
score = 0;
multiplier = 1;
isProcessing = false;
cascadeCount = 0;
gameTimeLeft = 60;
// Set up extreme mode if selected
if (gameMode === 'extreme') {
extremeGemType = Math.floor(Math.random() * GEM_TYPES);
}
// Clear existing timer
if (gameTimer) {
LK.clearInterval(gameTimer);
}
// Start countdown timer
gameTimer = LK.setInterval(function () {
gameTimeLeft--;
if (timerTxt) {
timerTxt.setText('Time: ' + gameTimeLeft);
}
// Change color when time is running low
if (gameTimeLeft <= 10 && timerTxt) {
timerTxt.fill = 0xFF0000;
} else if (gameTimeLeft <= 30 && timerTxt) {
timerTxt.fill = 0xFF8800;
}
// Game over when time runs out
if (gameTimeLeft <= 0) {
LK.clearInterval(gameTimer);
gameTimer = null;
LK.showGameOver();
}
}, 1000);
// Create animated star background for gameplay
for (var i = 0; i < 50; i++) {
var star = LK.getAsset('starBg', {
anchorX: 0.5,
anchorY: 0.5
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
game.addChild(star);
gameElements.push(star);
// Animate each star with twinkling effect
tween(star, {
alpha: Math.random() * 0.3 + 0.1
}, {
duration: Math.random() * 2000 + 1000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
// Add gentle floating movement
tween(star, {
y: star.y + (Math.random() * 100 - 50)
}, {
duration: Math.random() * 4000 + 2000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
// Initialize score display
scoreTxt = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(scoreTxt);
gameElements.push(scoreTxt);
multiplierTxt = new Text2('Multiplier: x1', {
size: 70,
fill: 0xFFFF00
});
multiplierTxt.anchor.set(0.5, 1);
multiplierTxt.y = -120;
LK.gui.bottom.addChild(multiplierTxt);
gameElements.push(multiplierTxt);
timerTxt = new Text2('Time: 60', {
size: 100,
fill: 0xFF4444
});
timerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timerTxt);
gameElements.push(timerTxt);
// Add extreme mode indicator if in extreme mode
if (gameMode === 'extreme') {
var gemTypeNames = ['Red', 'Blue', 'Green', 'Yellow', 'Purple', 'Orange'];
extremeGemTxt = new Text2('EXTREME MODE - Only ' + gemTypeNames[extremeGemType] + ' gems score!', {
size: 60,
fill: 0xFF4444
});
extremeGemTxt.anchor.set(0.5, 0);
extremeGemTxt.y = 120;
LK.gui.top.addChild(extremeGemTxt);
gameElements.push(extremeGemTxt);
}
// Create menu button
var menuButton = LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
menuButton.x = 1800;
menuButton.y = 200;
menuButton.alpha = 0.8;
game.addChild(menuButton);
gameElements.push(menuButton);
// Create menu button text
var menuButtonText = new Text2('MENU', {
size: 60,
fill: 0xFFFFFF
});
menuButtonText.anchor.set(0.5, 0.5);
menuButtonText.x = 1800;
menuButtonText.y = 200;
game.addChild(menuButtonText);
gameElements.push(menuButtonText);
// Add click handler for menu button
menuButton.down = function (x, y, obj) {
// Clear game timer
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
// Return to main menu
showStartScreen();
};
// Initialize the game
initializeGrid();
updateScore();
// Apply sound volume settings
updateAllSoundVolumes();
// Start background music with current volume setting
var musicVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
if (musicVolume > 0) {
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.9,
duration: 1000
}
});
}
// Continue spaceship animation during gameplay
if (!spaceship || !spaceship.parent) {
createSpaceship();
}
// Continue UFO animation during gameplay
if (!ufo || !ufo.parent) {
createUfo();
}
}
function showOptionsMenu() {
gameState = 'options';
if (optionsMenu) {
game.removeChild(optionsMenu);
}
optionsMenu = new OptionsMenu();
game.addChild(optionsMenu);
}
function hideOptionsMenu() {
gameState = 'menu';
if (optionsMenu) {
game.removeChild(optionsMenu);
optionsMenu = null;
}
}
function createSpaceship() {
if (spaceship) {
game.removeChild(spaceship);
}
spaceship = LK.getAsset('spaceship', {
anchorX: 0.5,
anchorY: 0.5
});
// Start from left side, random Y position
spaceship.x = -100;
spaceship.y = Math.random() * 1800 + 400; // Random position between 400 and 2200
spaceship.alpha = 0.3;
game.addChild(spaceship);
// Animate spaceship moving across screen
tween(spaceship, {
x: 2148 // Move to right edge
}, {
duration: Math.random() * 8000 + 12000,
// 12-20 seconds to cross screen
easing: tween.linear,
onFinish: function onFinish() {
// When spaceship reaches right edge, create a new one
LK.setTimeout(function () {
createSpaceship();
}, Math.random() * 5000 + 2000); // Wait 2-7 seconds before next spaceship
}
});
}
function createUfo() {
if (ufo) {
game.removeChild(ufo);
}
ufo = LK.getAsset('ufo', {
anchorX: 0.5,
anchorY: 0.5
});
// Start from right side, random Y position
ufo.x = 2148;
ufo.y = Math.random() * 1200 + 300; // Random position between 300 and 1500
ufo.alpha = 0.4;
game.addChild(ufo);
// Animate UFO moving across screen from right to left
tween(ufo, {
x: -150 // Move to left edge
}, {
duration: Math.random() * 10000 + 15000,
// 15-25 seconds to cross screen
easing: tween.linear,
onFinish: function onFinish() {
// When UFO reaches left edge, create a new one
LK.setTimeout(function () {
createUfo();
}, Math.random() * 8000 + 3000); // Wait 3-11 seconds before next UFO
}
});
// Add subtle bobbing motion to UFO
tween(ufo, {
y: ufo.y + 30
}, {
duration: 2000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
var howToPlayScreen = null;
function showHowToPlayScreen() {
gameState = 'howtoplay';
if (howToPlayScreen) {
game.removeChild(howToPlayScreen);
}
howToPlayScreen = new HowToPlayScreen();
game.addChild(howToPlayScreen);
}
function hideHowToPlayScreen() {
gameState = 'menu';
if (howToPlayScreen) {
game.removeChild(howToPlayScreen);
howToPlayScreen = null;
}
}
var feedbackScreen = null;
function showFeedbackScreen() {
gameState = 'feedback';
if (feedbackScreen) {
game.removeChild(feedbackScreen);
}
feedbackScreen = new FeedbackScreen();
game.addChild(feedbackScreen);
}
function hideFeedbackScreen() {
gameState = 'menu';
if (feedbackScreen) {
game.removeChild(feedbackScreen);
feedbackScreen = null;
}
}
var blankScreen = null;
var isShaking = false;
var shakeTimer = null;
function startContinuousShake() {
if (isShaking) return; // Already shaking
isShaking = true;
function performShake() {
if (!isShaking) return;
var shakeIntensity = 15;
var shakeX = (Math.random() - 0.5) * shakeIntensity;
var shakeY = (Math.random() - 0.5) * shakeIntensity;
tween(game, {
x: shakeX,
y: shakeY
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
// Continue shaking if still enabled
if (isShaking) {
shakeTimer = LK.setTimeout(performShake, 20);
} else {
// Reset position when shaking stops
tween(game, {
x: 0,
y: 0
}, {
duration: 100,
easing: tween.easeOut
});
}
}
});
}
performShake();
}
function stopContinuousShake() {
isShaking = false;
if (shakeTimer) {
LK.clearTimeout(shakeTimer);
shakeTimer = null;
}
}
function showBlankScreen() {
gameState = 'blank';
if (blankScreen) {
game.removeChild(blankScreen);
}
blankScreen = new BlankScreen();
game.addChild(blankScreen);
}
function hideBlankScreen() {
gameState = 'menu';
if (blankScreen) {
game.removeChild(blankScreen);
blankScreen = null;
}
}
function updateAllSoundVolumes() {
var musicVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
var soundEffectsVolume = storage.soundEffectsVolume === undefined ? 1.0 : storage.soundEffectsVolume;
// Re-initialize sound assets with new volumes
// Update background music volume if it's playing
if (musicVolume > 0) {
if (gameState === 'playing') {
LK.stopMusic();
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.9,
duration: 500
}
});
} else if (gameState === 'menu') {
LK.stopMusic();
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.8,
duration: 500
}
});
}
} else {
LK.stopMusic();
}
} /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BlankScreen = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 9,
scaleY: 12
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.95;
self.addChild(background);
var titleText = new Text2('JUST JOKING', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
// Add some content to the blank screen
var contentText = new Text2('Click the green button', {
size: 80,
fill: 0x00FF00
});
contentText.anchor.set(0.5, 0.5);
contentText.x = 1024;
contentText.y = 800;
self.addChild(contentText);
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 2300;
self.addChild(backButton);
var backText = new Text2('BACK', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2300;
self.addChild(backText);
backButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
hideBlankScreen();
};
return self;
});
var FeedbackScreen = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 9,
scaleY: 12
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.95;
self.addChild(background);
var titleText = new Text2('FEEDBACK', {
size: 120,
fill: 0xFFAA00
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
// Feedback form instructions
var instructions = ['We would love to hear your thoughts!', '', 'What did you think of the game?', '• Was it fun and engaging?', '• Were the controls easy to use?', '• How was the difficulty level?', '• Any suggestions for improvement?', '', 'Thank you for playing MAVUS BABA!', 'Your feedback helps us make better games.', '', 'Contact us at:', 'INSTAGRAM: abdurrahim_scu'];
var yOffset = 650;
for (var i = 0; i < instructions.length; i++) {
var instructionText = new Text2(instructions[i], {
size: instructions[i] === '' ? 30 : instructions[i].startsWith('Contact') || instructions[i].includes('@') ? 50 : instructions[i].startsWith('•') ? 45 : instructions[i] === 'We would love to hear your thoughts!' ? 70 : instructions[i] === 'Thank you for playing MAVUS BABA!' ? 65 : 55,
fill: instructions[i].includes('@') ? 0x44FF44 : instructions[i].startsWith('•') ? 0xFFFF44 : instructions[i] === 'Thank you for playing MAVUS BABA!' ? 0xFFAA00 : 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = yOffset + i * 80;
self.addChild(instructionText);
}
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 2300;
self.addChild(backButton);
var backText = new Text2('BACK', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2300;
self.addChild(backText);
backButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
hideFeedbackScreen();
};
return self;
});
var Gem = Container.expand(function () {
var self = Container.call(this);
self.gemType = 0;
self.gridX = 0;
self.gridY = 0;
self.graphics = null;
self.isSelected = false;
self.isMatched = false;
self.isFalling = false;
self.isBomb = false;
self.init = function (type, gx, gy) {
self.gemType = type;
self.gridX = gx;
self.gridY = gy;
var gemTypes = ['gemRed', 'gemBlue', 'gemGreen', 'gemYellow', 'gemPurple', 'gemOrange', 'gemBomb'];
if (type === 6) {
self.isBomb = true;
}
self.graphics = self.attachAsset(gemTypes[type], {
anchorX: 0.5,
anchorY: 0.5
});
self.updatePosition();
};
self.updatePosition = function () {
var startX = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var startY = 400;
self.x = startX + self.gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = startY + self.gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.graphics.alpha = 0.7;
tween(self.graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200
});
} else {
self.graphics.alpha = 1.0;
tween(self.graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
};
self.fallTo = function (newY, callback) {
self.isFalling = true;
self.gridY = newY;
var newPosY = 400 + newY * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
y: newPosY
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.isFalling = false;
if (callback) callback();
}
});
};
self.destroy = function () {
self.isMatched = true;
// Play explosion sound effect
LK.getSound('explosion').play();
// Create explosion effect with scaling and rotation
tween(self.graphics, {
scaleX: 1.8,
scaleY: 1.8,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
self.explodeBomb = function () {
if (!self.isBomb) return;
// Create dramatic bomb explosion effect
tween(self.graphics, {
scaleX: 3,
scaleY: 3,
rotation: Math.PI * 4,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
// Add pulsing effect before explosion
tween(self.graphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
});
// Mark gems in 3x3 area for destruction
var gemsToDestroy = [];
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
var targetX = self.gridX + dx;
var targetY = self.gridY + dy;
if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
if (grid[targetX][targetY] && !grid[targetX][targetY].isMatched) {
gemsToDestroy.push({
x: targetX,
y: targetY
});
}
}
}
}
// Destroy gems with delay and explosion effects
for (var i = 0; i < gemsToDestroy.length; i++) {
(function (destroyData, index) {
LK.setTimeout(function () {
if (grid[destroyData.x][destroyData.y]) {
var gemToExplode = grid[destroyData.x][destroyData.y];
// Play explosion sound for each destroyed gem
LK.getSound('explosion').play();
// Create explosion effect for each gem
tween(gemToExplode.graphics, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * (1 + Math.random()),
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (gemToExplode.parent) {
gemToExplode.parent.removeChild(gemToExplode);
}
}
});
grid[destroyData.x][destroyData.y] = null;
}
}, i * 80);
})(gemsToDestroy[i], i);
}
// Add explosion score - in extreme mode, only count gems of the selected type
var scoringGems = gemsToDestroy.length;
if (gameMode === 'extreme') {
scoringGems = 0;
for (var j = 0; j < gemsToDestroy.length; j++) {
var destroyData = gemsToDestroy[j];
if (grid[destroyData.x] && grid[destroyData.x][destroyData.y] && grid[destroyData.x][destroyData.y].gemType === extremeGemType) {
scoringGems++;
}
}
}
var explosionScore = scoringGems * 50 * multiplier;
score += explosionScore;
updateScore();
// Play explosion sound
LK.getSound('explosion').play();
// Wait for all destruction then cascade and fill empty spaces
LK.setTimeout(function () {
cascadeGems();
// Ensure empty spaces are filled after bomb explosion
LK.setTimeout(function () {
fillEmptySpaces();
}, 100);
}, 500);
};
self.down = function (x, y, obj) {
if (!self.isFalling && !isProcessing) {
if (self.isBomb) {
isProcessing = true;
self.explodeBomb();
} else {
selectGem(self);
}
}
};
return self;
});
var HowToPlayScreen = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 9,
scaleY: 12
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.95;
self.addChild(background);
var titleText = new Text2('HOW TO PLAY', {
size: 120,
fill: 0x44FF44
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
// Game instructions text
var instructions = ['Match 3 or more gems of the same color', 'to clear them and earn points!', '', '• Tap gems to select them', '• Select adjacent gems to swap', '• Create cascades for bonus points', '• Match 4+ gems to create bombs', '• Bombs destroy 3x3 areas', '• Score multiplier increases with points', '• You have 60 seconds to score big!', '', 'EXTREME MODE:', 'Only one gem type scores points!'];
var yOffset = 650;
for (var i = 0; i < instructions.length; i++) {
var instructionText = new Text2(instructions[i], {
size: instructions[i] === '' ? 30 : instructions[i].startsWith('EXTREME') ? 80 : 55,
fill: instructions[i].startsWith('EXTREME') ? 0xFF4444 : instructions[i].startsWith('•') ? 0xFFFF44 : 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = yOffset + i * 90;
self.addChild(instructionText);
}
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 2300;
self.addChild(backButton);
var backText = new Text2('BACK', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2300;
self.addChild(backText);
backButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
hideHowToPlayScreen();
};
return self;
});
var OptionsMenu = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 6
});
background.x = 1024;
background.y = 1366;
background.alpha = 0.9;
self.addChild(background);
var titleText = new Text2('Options', {
size: 150,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
self.addChild(titleText);
// Music Volume Toggle Button
var musicVolumeButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 0.6
});
musicVolumeButton.x = 1024;
musicVolumeButton.y = 1000;
self.addChild(musicVolumeButton);
// Get current music volume state
var isMusicOn = storage.musicVolume === undefined ? true : storage.musicVolume > 0;
var musicVolumeText = new Text2(isMusicOn ? 'Music: ON' : 'Music: OFF', {
size: 80,
fill: 0xFFFFFF
});
musicVolumeText.anchor.set(0.5, 0.5);
musicVolumeText.x = 1024;
musicVolumeText.y = 1000;
self.addChild(musicVolumeText);
musicVolumeButton.down = function (x, y, obj) {
// Toggle music volume
var currentVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
if (currentVolume > 0) {
// Turn music off
storage.musicVolume = 0;
musicVolumeText.setText('Music: OFF');
LK.stopMusic();
} else {
// Turn music on
storage.musicVolume = 1.0;
musicVolumeText.setText('Music: ON');
// Play appropriate music based on game state
if (gameState === 'playing') {
LK.playMusic('background', {
fade: {
start: 0,
end: 0.9,
duration: 500
}
});
} else if (gameState === 'menu' || gameState === 'options') {
LK.playMusic('background', {
fade: {
start: 0,
end: 0.8,
duration: 500
}
});
}
}
};
var backButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
backButton.x = 1024;
backButton.y = 1200;
self.addChild(backButton);
var backText = new Text2('Back', {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1200;
self.addChild(backText);
backButton.down = function (x, y, obj) {
hideOptionsMenu();
};
return self;
});
var StartScreen = Container.expand(function () {
var self = Container.call(this);
// Create animated star background
var stars = [];
for (var i = 0; i < 50; i++) {
var star = self.attachAsset('starBg', {
anchorX: 0.5,
anchorY: 0.5
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
stars.push(star);
// Animate each star with twinkling effect
tween(star, {
alpha: Math.random() * 0.3 + 0.1
}, {
duration: Math.random() * 2000 + 1000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
// Add gentle floating movement
tween(star, {
y: star.y + (Math.random() * 100 - 50)
}, {
duration: Math.random() * 4000 + 2000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
// Create 3D effect with shadow layers
var titleShadow3 = new Text2('MAVUS BABA', {
size: 200,
fill: 0x000000
});
titleShadow3.anchor.set(0.5, 0.5);
titleShadow3.x = 1032;
titleShadow3.y = 808;
self.addChild(titleShadow3);
var titleShadow2 = new Text2('MAVUS BABA', {
size: 200,
fill: 0x333333
});
titleShadow2.anchor.set(0.5, 0.5);
titleShadow2.x = 1028;
titleShadow2.y = 804;
self.addChild(titleShadow2);
var titleShadow1 = new Text2('MAVUS BABA', {
size: 200,
fill: 0x666666
});
titleShadow1.anchor.set(0.5, 0.5);
titleShadow1.x = 1026;
titleShadow1.y = 802;
self.addChild(titleShadow1);
var titleText = new Text2('MAVUS BABA', {
size: 200,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
self.addChild(titleText);
// Add 3D glow animation
tween(titleText, {
alpha: 0.8
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
alpha: 1.0
}, {
duration: 1500,
easing: tween.easeInOut
});
}
});
var startButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
startButton.x = 1024;
startButton.y = 1200;
self.addChild(startButton);
// Create 3D effect for Start text
var startShadow2 = new Text2('START', {
size: 100,
fill: 0x000000
});
startShadow2.anchor.set(0.5, 0.5);
startShadow2.x = 1028;
startShadow2.y = 1204;
self.addChild(startShadow2);
var startShadow1 = new Text2('START', {
size: 100,
fill: 0x444444
});
startShadow1.anchor.set(0.5, 0.5);
startShadow1.x = 1026;
startShadow1.y = 1202;
self.addChild(startShadow1);
var startText = new Text2('START', {
size: 100,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = 1024;
startText.y = 1200;
self.addChild(startText);
var optionsButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
optionsButton.x = 1024;
optionsButton.y = 1500;
self.addChild(optionsButton);
// Create 3D effect for Options text
var optionsShadow2 = new Text2('OPTIONS', {
size: 100,
fill: 0x000000
});
optionsShadow2.anchor.set(0.5, 0.5);
optionsShadow2.x = 1028;
optionsShadow2.y = 1504;
self.addChild(optionsShadow2);
var optionsShadow1 = new Text2('OPTIONS', {
size: 100,
fill: 0x444444
});
optionsShadow1.anchor.set(0.5, 0.5);
optionsShadow1.x = 1026;
optionsShadow1.y = 1502;
self.addChild(optionsShadow1);
var optionsText = new Text2('OPTIONS', {
size: 100,
fill: 0xFFFFFF
});
optionsText.anchor.set(0.5, 0.5);
optionsText.x = 1024;
optionsText.y = 1500;
self.addChild(optionsText);
// Add "MADE BY MAVUS DONDURMA" text to bottom left corner
var madeByText = new Text2('MADE BY MAVUS DONDURMA', {
size: 60,
fill: 0xCCCCCC
});
madeByText.anchor.set(0, 1);
madeByText.x = 150;
madeByText.y = 2632;
self.addChild(madeByText);
// Add version text under "Made by Mavus Dondurma"
var versionText = new Text2('Version 1.0', {
size: 40,
fill: 0x888888
});
versionText.anchor.set(0, 1);
versionText.x = 150;
versionText.y = 2680;
self.addChild(versionText);
startButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
startGame();
};
optionsButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
showOptionsMenu();
};
var extremeButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
extremeButton.x = 1024;
extremeButton.y = 1800;
self.addChild(extremeButton);
// Create 3D effect for Extreme Mode text
var extremeShadow2 = new Text2('EXTREME MODE', {
size: 80,
fill: 0x000000
});
extremeShadow2.anchor.set(0.5, 0.5);
extremeShadow2.x = 1028;
extremeShadow2.y = 1804;
self.addChild(extremeShadow2);
var extremeShadow1 = new Text2('EXTREME MODE', {
size: 80,
fill: 0x444444
});
extremeShadow1.anchor.set(0.5, 0.5);
extremeShadow1.x = 1026;
extremeShadow1.y = 1802;
self.addChild(extremeShadow1);
var extremeText = new Text2('EXTREME MODE', {
size: 80,
fill: 0xFF4444
});
extremeText.anchor.set(0.5, 0.5);
extremeText.x = 1024;
extremeText.y = 1800;
self.addChild(extremeText);
extremeButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
gameMode = 'extreme';
startGame();
};
// How to Play button at bottom right
var howToPlayButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 0.7
});
howToPlayButton.x = 1700;
howToPlayButton.y = 2400;
self.addChild(howToPlayButton);
// Create 3D effect for How to Play text
var howToPlayShadow2 = new Text2('HOW TO PLAY', {
size: 60,
fill: 0x000000
});
howToPlayShadow2.anchor.set(0.5, 0.5);
howToPlayShadow2.x = 1704;
howToPlayShadow2.y = 2404;
self.addChild(howToPlayShadow2);
var howToPlayShadow1 = new Text2('HOW TO PLAY', {
size: 60,
fill: 0x444444
});
howToPlayShadow1.anchor.set(0.5, 0.5);
howToPlayShadow1.x = 1702;
howToPlayShadow1.y = 2402;
self.addChild(howToPlayShadow1);
var howToPlayText = new Text2('HOW TO PLAY', {
size: 60,
fill: 0x44FF44
});
howToPlayText.anchor.set(0.5, 0.5);
howToPlayText.x = 1700;
howToPlayText.y = 2400;
self.addChild(howToPlayText);
howToPlayButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
showHowToPlayScreen();
};
// Feedback button at bottom right under How to Play
var feedbackButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 0.7
});
feedbackButton.x = 1700;
feedbackButton.y = 2550;
self.addChild(feedbackButton);
// Create 3D effect for Feedback text
var feedbackShadow2 = new Text2('FEEDBACK', {
size: 60,
fill: 0x000000
});
feedbackShadow2.anchor.set(0.5, 0.5);
feedbackShadow2.x = 1704;
feedbackShadow2.y = 2554;
self.addChild(feedbackShadow2);
var feedbackShadow1 = new Text2('FEEDBACK', {
size: 60,
fill: 0x444444
});
feedbackShadow1.anchor.set(0.5, 0.5);
feedbackShadow1.x = 1702;
feedbackShadow1.y = 2552;
self.addChild(feedbackShadow1);
var feedbackText = new Text2('FEEDBACK', {
size: 60,
fill: 0xFFAA00
});
feedbackText.anchor.set(0.5, 0.5);
feedbackText.x = 1700;
feedbackText.y = 2550;
self.addChild(feedbackText);
feedbackButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
showFeedbackScreen();
};
// Green smiley ball button above blank button
var greenButton = LK.getAsset('redSmileyBall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
greenButton.x = 350;
greenButton.y = 2200;
greenButton.tint = 0x00FF00; // Make it green
self.addChild(greenButton);
greenButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
// Open new tab/window
var newWindow = window.open('about:blank', '_blank');
if (newWindow) {
newWindow.document.write('<html><head><title>New Tab</title></head><body><h1>Hello from Green Button!</h1><p>This tab was opened by clicking the green smiley ball.</p></body></html>');
}
};
// Blank button with red smiley ball
var blankButton = LK.getAsset('redSmileyBall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
blankButton.x = 350;
blankButton.y = 2450;
self.addChild(blankButton);
// Face features removed - now just a plain red ball
blankButton.down = function (x, y, obj) {
LK.getSound('buttonClick').play();
// Start continuous screen shake effect
startContinuousShake();
showBlankScreen();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 200;
var GEM_TYPES = 6;
var BOMB_TYPE = 6;
var grid = [];
var selectedGem = null;
var score = 0;
var multiplier = 1;
var isProcessing = false;
var cascadeCount = 0;
var gameTimeLeft = 60;
var gameTimer = null;
var timerTxt = null;
var gameMode = 'normal'; // 'normal' or 'extreme'
var extremeGemType = 0; // Only this gem type scores points in extreme mode
var extremeGemTxt = null;
// Game state management
var gameState = 'menu'; // 'menu', 'playing', 'options'
var startScreen = null;
var optionsMenu = null;
var gameElements = [];
// Spaceship for background animation
var spaceship = null;
// UFO for background animation
var ufo = null;
// Score display will be created when game starts
var scoreTxt = null;
var multiplierTxt = null;
// Initialize grid
function initializeGrid() {
var startX = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var startY = 400;
// Create background cells
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var cell = LK.getAsset('gridCell', {
anchorX: 0,
anchorY: 0,
alpha: 0.95
});
cell.x = startX + x * CELL_SIZE;
cell.y = startY + y * CELL_SIZE;
game.addChild(cell);
}
}
// Initialize grid array
for (var x = 0; x < GRID_SIZE; x++) {
grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
grid[x][y] = null;
}
}
// Fill grid with gems
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
createGem(x, y);
}
}
// Remove initial matches
removeInitialMatches();
}
function createGem(x, y) {
var gem = new Gem();
var gemType = Math.floor(Math.random() * GEM_TYPES);
gem.init(gemType, x, y);
grid[x][y] = gem;
game.addChild(gem);
return gem;
}
function removeInitialMatches() {
var hasMatches = true;
var attempts = 0;
while (hasMatches && attempts < 50) {
hasMatches = false;
attempts++;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && hasMatchAt(x, y)) {
// Regenerate this gem
var oldGem = grid[x][y];
if (oldGem.parent) {
oldGem.parent.removeChild(oldGem);
}
createGem(x, y);
hasMatches = true;
}
}
}
}
}
function selectGem(gem) {
if (selectedGem === gem) {
// Deselect
selectedGem.setSelected(false);
selectedGem = null;
return;
}
if (selectedGem === null) {
// First selection
selectedGem = gem;
gem.setSelected(true);
} else {
// Second selection - check if adjacent
if (areAdjacent(selectedGem, gem)) {
swapGems(selectedGem, gem);
}
selectedGem.setSelected(false);
selectedGem = null;
}
}
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;
}
function swapGems(gem1, gem2) {
if (isProcessing) return;
isProcessing = true;
// Store positions
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 swap
var gem1NewX = gem1.x;
var gem1NewY = gem1.y;
gem1.updatePosition();
var gem2NewX = gem2.x;
var gem2NewY = gem2.y;
gem2.updatePosition();
gem1.x = gem2NewX;
gem1.y = gem2NewY;
gem2.x = gem1NewX;
gem2.y = gem1NewY;
tween(gem1, {
x: gem1NewX,
y: gem1NewY
}, {
duration: 300
});
tween(gem2, {
x: gem2NewX,
y: gem2NewY
}, {
duration: 300,
onFinish: function onFinish() {
checkForMatches();
}
});
}
function hasMatchAt(x, y) {
if (!grid[x] || !grid[x][y]) return false;
var gemType = grid[x][y].gemType;
// Check horizontal
var hCount = 1;
// Check left
for (var i = x - 1; i >= 0 && grid[i][y] && grid[i][y].gemType === gemType; i--) {
hCount++;
}
// Check right
for (var i = x + 1; i < GRID_SIZE && grid[i][y] && grid[i][y].gemType === gemType; i++) {
hCount++;
}
if (hCount >= 3) return true;
// Check vertical
var vCount = 1;
// Check up
for (var i = y - 1; i >= 0 && grid[x][i] && grid[x][i].gemType === gemType; i--) {
vCount++;
}
// Check down
for (var i = y + 1; i < GRID_SIZE && grid[x][i] && grid[x][i].gemType === gemType; i++) {
vCount++;
}
return vCount >= 3;
}
function checkForMatches() {
var matches = [];
// Find all matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] && hasMatchAt(x, y)) {
matches.push({
x: x,
y: y
});
}
}
}
if (matches.length > 0) {
cascadeCount++;
LK.getSound('match').play();
// Calculate score - in extreme mode, only count matches of the selected gem type
var scoringMatches = matches;
if (gameMode === 'extreme') {
scoringMatches = [];
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (grid[match.x] && grid[match.x][match.y] && grid[match.x][match.y].gemType === extremeGemType) {
scoringMatches.push(match);
}
}
}
var points = scoringMatches.length * 10 * multiplier * cascadeCount;
score += points;
updateScore();
// Create bomb if match is 4 or more gems
var shouldCreateBomb = matches.length >= 4;
var bombPosition = null;
if (shouldCreateBomb && matches.length > 0) {
bombPosition = matches[Math.floor(Math.random() * matches.length)];
}
// Mark matched gems for destruction
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;
}
}
// Create bomb after destruction
if (shouldCreateBomb && bombPosition) {
LK.setTimeout(function () {
if (grid[bombPosition.x][bombPosition.y] === null) {
var bomb = new Gem();
bomb.init(BOMB_TYPE, bombPosition.x, bombPosition.y);
grid[bombPosition.x][bombPosition.y] = bomb;
game.addChild(bomb);
// Animate bomb creation
bomb.graphics.scaleX = 0;
bomb.graphics.scaleY = 0;
tween(bomb.graphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
}
}, 200);
}
// Wait for destruction animation then cascade
LK.setTimeout(function () {
cascadeGems();
}, 400);
} else {
cascadeCount = 0;
isProcessing = false;
}
}
function cascadeGems() {
var needsCascade = false;
var fallPromises = 0;
// Process each column from left to right
for (var x = 0; x < GRID_SIZE; x++) {
// Compact the column - move all existing gems down to fill gaps
var compactedGems = [];
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] !== null) {
compactedGems.push(grid[x][y]);
grid[x][y] = null;
}
}
// Place compacted gems at the bottom of the column
var startY = GRID_SIZE - compactedGems.length;
for (var i = 0; i < compactedGems.length; i++) {
var gem = compactedGems[i];
var newY = startY + i;
var oldY = gem.gridY;
if (oldY !== newY) {
needsCascade = true;
grid[x][newY] = gem;
fallPromises++;
gem.fallTo(newY, function () {
fallPromises--;
if (fallPromises === 0) {
// Always fill empty spaces after cascading
fillEmptySpaces();
}
});
} else {
// Gem doesn't need to move
grid[x][newY] = gem;
}
}
}
// Always ensure empty spaces are filled, regardless of cascade
fillEmptySpaces();
if (needsCascade) {
LK.getSound('cascade').play();
}
}
function fillEmptySpaces() {
var newGemsCreated = 0;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] === null) {
createGem(x, y);
newGemsCreated++;
// Start gem above the screen and animate it falling
var startY = 400 - newGemsCreated * CELL_SIZE;
grid[x][y].y = startY;
tween(grid[x][y], {
y: 400 + y * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 500 + newGemsCreated * 50,
easing: tween.bounceOut
});
}
}
}
// Check for new matches after a delay
LK.setTimeout(function () {
checkForMatches();
}, 600);
}
function updateScore() {
if (scoreTxt) {
scoreTxt.setText('Score: ' + score);
}
// Update multiplier based on score
var newMultiplier = 1;
if (score >= 2500) newMultiplier = 5;else if (score >= 1000) newMultiplier = 4;else if (score >= 500) newMultiplier = 3;else if (score >= 100) newMultiplier = 2;
if (newMultiplier !== multiplier) {
multiplier = newMultiplier;
if (multiplierTxt) {
multiplierTxt.setText('Multiplier: x' + multiplier);
}
LK.effects.flashScreen(0x00ff00, 500);
}
// Win condition
if (score >= 5000) {
LK.showYouWin();
}
}
// Start continuous shake when game opens
startContinuousShake();
// Initialize start screen instead of game
showStartScreen();
game.update = function () {
// Game loop - handle any continuous updates here
};
function showStartScreen() {
gameState = 'menu';
gameMode = 'normal'; // Reset to normal mode when returning to menu
if (startScreen) {
game.removeChild(startScreen);
}
// Clear game timer if it exists
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
// Clear all game elements when returning to menu
for (var i = 0; i < gameElements.length; i++) {
if (gameElements[i].parent) {
gameElements[i].parent.removeChild(gameElements[i]);
}
}
gameElements = [];
// Clear grid elements
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x] && grid[x][y] && grid[x][y].parent) {
grid[x][y].parent.removeChild(grid[x][y]);
}
}
}
// Clear all children from game to ensure clean slate
while (game.children.length > 0) {
game.removeChild(game.children[0]);
}
startScreen = new StartScreen();
game.addChild(startScreen);
// Start spaceship animation
createSpaceship();
// Start UFO animation
createUfo();
// Start background music for start screen
var musicVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
if (musicVolume > 0) {
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.8,
duration: 2000
}
});
}
}
function startGame() {
gameState = 'playing';
if (startScreen) {
game.removeChild(startScreen);
startScreen = null;
}
if (optionsMenu) {
game.removeChild(optionsMenu);
optionsMenu = null;
}
// Clear any existing game elements
for (var i = 0; i < gameElements.length; i++) {
if (gameElements[i].parent) {
gameElements[i].parent.removeChild(gameElements[i]);
}
}
gameElements = [];
// Reset game state
grid = [];
selectedGem = null;
score = 0;
multiplier = 1;
isProcessing = false;
cascadeCount = 0;
gameTimeLeft = 60;
// Set up extreme mode if selected
if (gameMode === 'extreme') {
extremeGemType = Math.floor(Math.random() * GEM_TYPES);
}
// Clear existing timer
if (gameTimer) {
LK.clearInterval(gameTimer);
}
// Start countdown timer
gameTimer = LK.setInterval(function () {
gameTimeLeft--;
if (timerTxt) {
timerTxt.setText('Time: ' + gameTimeLeft);
}
// Change color when time is running low
if (gameTimeLeft <= 10 && timerTxt) {
timerTxt.fill = 0xFF0000;
} else if (gameTimeLeft <= 30 && timerTxt) {
timerTxt.fill = 0xFF8800;
}
// Game over when time runs out
if (gameTimeLeft <= 0) {
LK.clearInterval(gameTimer);
gameTimer = null;
LK.showGameOver();
}
}, 1000);
// Create animated star background for gameplay
for (var i = 0; i < 50; i++) {
var star = LK.getAsset('starBg', {
anchorX: 0.5,
anchorY: 0.5
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
game.addChild(star);
gameElements.push(star);
// Animate each star with twinkling effect
tween(star, {
alpha: Math.random() * 0.3 + 0.1
}, {
duration: Math.random() * 2000 + 1000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
// Add gentle floating movement
tween(star, {
y: star.y + (Math.random() * 100 - 50)
}, {
duration: Math.random() * 4000 + 2000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
// Initialize score display
scoreTxt = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(scoreTxt);
gameElements.push(scoreTxt);
multiplierTxt = new Text2('Multiplier: x1', {
size: 70,
fill: 0xFFFF00
});
multiplierTxt.anchor.set(0.5, 1);
multiplierTxt.y = -120;
LK.gui.bottom.addChild(multiplierTxt);
gameElements.push(multiplierTxt);
timerTxt = new Text2('Time: 60', {
size: 100,
fill: 0xFF4444
});
timerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timerTxt);
gameElements.push(timerTxt);
// Add extreme mode indicator if in extreme mode
if (gameMode === 'extreme') {
var gemTypeNames = ['Red', 'Blue', 'Green', 'Yellow', 'Purple', 'Orange'];
extremeGemTxt = new Text2('EXTREME MODE - Only ' + gemTypeNames[extremeGemType] + ' gems score!', {
size: 60,
fill: 0xFF4444
});
extremeGemTxt.anchor.set(0.5, 0);
extremeGemTxt.y = 120;
LK.gui.top.addChild(extremeGemTxt);
gameElements.push(extremeGemTxt);
}
// Create menu button
var menuButton = LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
menuButton.x = 1800;
menuButton.y = 200;
menuButton.alpha = 0.8;
game.addChild(menuButton);
gameElements.push(menuButton);
// Create menu button text
var menuButtonText = new Text2('MENU', {
size: 60,
fill: 0xFFFFFF
});
menuButtonText.anchor.set(0.5, 0.5);
menuButtonText.x = 1800;
menuButtonText.y = 200;
game.addChild(menuButtonText);
gameElements.push(menuButtonText);
// Add click handler for menu button
menuButton.down = function (x, y, obj) {
// Clear game timer
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
// Return to main menu
showStartScreen();
};
// Initialize the game
initializeGrid();
updateScore();
// Apply sound volume settings
updateAllSoundVolumes();
// Start background music with current volume setting
var musicVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
if (musicVolume > 0) {
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.9,
duration: 1000
}
});
}
// Continue spaceship animation during gameplay
if (!spaceship || !spaceship.parent) {
createSpaceship();
}
// Continue UFO animation during gameplay
if (!ufo || !ufo.parent) {
createUfo();
}
}
function showOptionsMenu() {
gameState = 'options';
if (optionsMenu) {
game.removeChild(optionsMenu);
}
optionsMenu = new OptionsMenu();
game.addChild(optionsMenu);
}
function hideOptionsMenu() {
gameState = 'menu';
if (optionsMenu) {
game.removeChild(optionsMenu);
optionsMenu = null;
}
}
function createSpaceship() {
if (spaceship) {
game.removeChild(spaceship);
}
spaceship = LK.getAsset('spaceship', {
anchorX: 0.5,
anchorY: 0.5
});
// Start from left side, random Y position
spaceship.x = -100;
spaceship.y = Math.random() * 1800 + 400; // Random position between 400 and 2200
spaceship.alpha = 0.3;
game.addChild(spaceship);
// Animate spaceship moving across screen
tween(spaceship, {
x: 2148 // Move to right edge
}, {
duration: Math.random() * 8000 + 12000,
// 12-20 seconds to cross screen
easing: tween.linear,
onFinish: function onFinish() {
// When spaceship reaches right edge, create a new one
LK.setTimeout(function () {
createSpaceship();
}, Math.random() * 5000 + 2000); // Wait 2-7 seconds before next spaceship
}
});
}
function createUfo() {
if (ufo) {
game.removeChild(ufo);
}
ufo = LK.getAsset('ufo', {
anchorX: 0.5,
anchorY: 0.5
});
// Start from right side, random Y position
ufo.x = 2148;
ufo.y = Math.random() * 1200 + 300; // Random position between 300 and 1500
ufo.alpha = 0.4;
game.addChild(ufo);
// Animate UFO moving across screen from right to left
tween(ufo, {
x: -150 // Move to left edge
}, {
duration: Math.random() * 10000 + 15000,
// 15-25 seconds to cross screen
easing: tween.linear,
onFinish: function onFinish() {
// When UFO reaches left edge, create a new one
LK.setTimeout(function () {
createUfo();
}, Math.random() * 8000 + 3000); // Wait 3-11 seconds before next UFO
}
});
// Add subtle bobbing motion to UFO
tween(ufo, {
y: ufo.y + 30
}, {
duration: 2000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
var howToPlayScreen = null;
function showHowToPlayScreen() {
gameState = 'howtoplay';
if (howToPlayScreen) {
game.removeChild(howToPlayScreen);
}
howToPlayScreen = new HowToPlayScreen();
game.addChild(howToPlayScreen);
}
function hideHowToPlayScreen() {
gameState = 'menu';
if (howToPlayScreen) {
game.removeChild(howToPlayScreen);
howToPlayScreen = null;
}
}
var feedbackScreen = null;
function showFeedbackScreen() {
gameState = 'feedback';
if (feedbackScreen) {
game.removeChild(feedbackScreen);
}
feedbackScreen = new FeedbackScreen();
game.addChild(feedbackScreen);
}
function hideFeedbackScreen() {
gameState = 'menu';
if (feedbackScreen) {
game.removeChild(feedbackScreen);
feedbackScreen = null;
}
}
var blankScreen = null;
var isShaking = false;
var shakeTimer = null;
function startContinuousShake() {
if (isShaking) return; // Already shaking
isShaking = true;
function performShake() {
if (!isShaking) return;
var shakeIntensity = 15;
var shakeX = (Math.random() - 0.5) * shakeIntensity;
var shakeY = (Math.random() - 0.5) * shakeIntensity;
tween(game, {
x: shakeX,
y: shakeY
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
// Continue shaking if still enabled
if (isShaking) {
shakeTimer = LK.setTimeout(performShake, 20);
} else {
// Reset position when shaking stops
tween(game, {
x: 0,
y: 0
}, {
duration: 100,
easing: tween.easeOut
});
}
}
});
}
performShake();
}
function stopContinuousShake() {
isShaking = false;
if (shakeTimer) {
LK.clearTimeout(shakeTimer);
shakeTimer = null;
}
}
function showBlankScreen() {
gameState = 'blank';
if (blankScreen) {
game.removeChild(blankScreen);
}
blankScreen = new BlankScreen();
game.addChild(blankScreen);
}
function hideBlankScreen() {
gameState = 'menu';
if (blankScreen) {
game.removeChild(blankScreen);
blankScreen = null;
}
}
function updateAllSoundVolumes() {
var musicVolume = storage.musicVolume === undefined ? 1.0 : storage.musicVolume;
var soundEffectsVolume = storage.soundEffectsVolume === undefined ? 1.0 : storage.soundEffectsVolume;
// Re-initialize sound assets with new volumes
// Update background music volume if it's playing
if (musicVolume > 0) {
if (gameState === 'playing') {
LK.stopMusic();
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.9,
duration: 500
}
});
} else if (gameState === 'menu') {
LK.stopMusic();
LK.playMusic('background', {
fade: {
start: 0,
end: musicVolume * 0.8,
duration: 500
}
});
}
} else {
LK.stopMusic();
}
}
red smiley ball. In-Game asset. 2d. High contrast. No shadows
Blue smiley ball. In-Game asset. 2d. High contrast. No shadows
Green smiley face. In-Game asset. 2d. High contrast. No shadows
Orange smiley ball. In-Game asset. 2d. High contrast. No shadows
Purple smiley ball. In-Game asset. 2d. High contrast. No shadows
Yellow smiley ball. In-Game asset. 2d. High contrast. No shadows
Bomba. In-Game asset. 2d. High contrast. No shadows
Star. In-Game asset. 2d. High contrast. No shadows
Spaceship. In-Game asset. 2d. High contrast. No shadows
A UFO with aliens inside. In-Game asset. 2d. High contrast. No shadows
Red smiley face. In-Game asset. 2d. High contrast. No shadows
Green smiley ball. In-Game asset. 2d. High contrast. No shadows
Male Cyber Character. In-Game asset. 2d. High contrast. No shadows
Vertical rocket. In-Game asset. 2d. High contrast. No shadows