User prompt
saniye olsun oyun bittiğinde puan/saniye oyuncunun puanı olsun
User prompt
son isteiğim 3 işlemi geri al
User prompt
çerçeve tek renk olsun, patlatılack balon renginde yanıp sönsün ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
çerçevenin tüm kenerları patlatılacak balon rengşnde olsun
User prompt
çerçeve patlatılacak renkte olsun
User prompt
oyunu kalın dikdörtgen çerçeve içine al
User prompt
patlatılacak renk yazısını sil
User prompt
patlatılacak renk ekranın ortasında konumlansın
User prompt
patlatılacak renği ekrana yazarmısın
User prompt
süre ve patlatılacak renk yazısı sanırım oyunun dışında konumlanmış görünmüyor
User prompt
süre yazsı ve patlatılacak renk ekranda görünmüyor
User prompt
senden istediğim son 3 değişikliği geri al
User prompt
senden istediğim son 2 değişikliği geri al
User prompt
renk yazan yazıyı ekranın alt ortasına konumlandır
User prompt
ren yazan yazıyı ekranın sol altına konumlandır
User prompt
Renk yazısını ekranın en sağına konumlandır
User prompt
son yapılan 3 düzeltme kodunu geri al
User prompt
son yapılan düzenlemeyi geri al
User prompt
en son işlemi geri al
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'anchor')' in or related to this line: 'timerTxt.anchor.set(0.5, 0);' Line Number: 163
User prompt
ekranın üst solunda puan, üst orta da zaman sağ üste ise renk yazısını konumlandır
User prompt
renkleri veren yazı hangi renk yazıyor ise o renkte olsun yazı
User prompt
renk yazan yazı yazdı renkte olsun
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'colorNameTopLeftText.style.fill = color; // Set text color to the actual balloon color' Line Number: 231
User prompt
ingilizce renkler siyah değil kendi renginde yazsın
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Balloon class var Balloon = Container.expand(function () { var self = Container.call(this); // Store color for logic self.color = self.color || 0xff0000; // Default red, will be overwritten on creation // Store grid position self.gridX = 0; self.gridY = 0; // Is this balloon popped? self.popped = false; // Attach balloon asset (ellipse shape) - will be replaced in buildGrid with correct color var balloonGraphics = self.attachAsset('balloon_red', { anchorX: 0.5, anchorY: 0.5 }); // Pop animation and logic self.pop = function () { if (self.popped) return; self.popped = true; // Animate scale down and fade out tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 250, easing: tween.easeIn, onFinish: function onFinish() { self.destroy(); } }); }; // Down event (touch/click) self.down = function (x, y, obj) { if (self.popped) return; // Only allow popping if this is the current color // Always compare as integer values to avoid color type mismatch if (parseInt(self.color, 10) !== parseInt(currentColor, 10)) return; // Find all connected balloons of the same color (side-by-side or vertical) var group = findConnectedBalloons(self.gridX, self.gridY, self.color); // Only pop if at least 2 connected (including self) if (group.length < 2) return; for (var i = 0; i < group.length; i++) { if (!group[i].popped) { group[i].pop(); } } // Update score (100 points per balloon) LK.setScore(LK.getScore() + group.length * 100); scoreTxt.setText(LK.getScore()); // After popping, let balloons above fall down to fill empty spaces LK.setTimeout(function () { for (var x = 0; x < GRID_COLS; x++) { // For each column, go from bottom to top for (var y = GRID_ROWS - 1; y >= 0; y--) { if (!balloons[x][y] || balloons[x][y].popped) { // Find the nearest non-popped balloon above for (var aboveY = y - 1; aboveY >= 0; aboveY--) { if (balloons[x][aboveY] && !balloons[x][aboveY].popped) { // Move this balloon down var b = balloons[x][aboveY]; // Update grid balloons[x][y] = b; balloons[x][aboveY] = null; b.gridY = y; // Animate drop var targetY = balloons[x][y].y = Math.floor((2732 - GRID_ROWS * balloonSize) / 2) + balloonSize / 2 + y * (balloonSize + balloonSpacing); tween(b, { y: targetY }, { duration: 200, easing: tween.easeIn }); break; } } } } } // After all drops, fill empty spots at the top with null (no new balloons) for (var x = 0; x < GRID_COLS; x++) { for (var y = 0; y < GRID_ROWS; y++) { if (!balloons[x][y] || balloons[x][y] && balloons[x][y].popped) { balloons[x][y] = null; } } } }, 260); // Wait for pop animation to finish }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xffffff }); /**** * Game Code ****/ // Balloon grid settings var GRID_COLS = 10; var GRID_ROWS = 12; var BALLOON_COLORS = [0xff4d4d, // red 0x4db8ff, // blue 0x4dff4d, // green 0xffe14d, // yellow 0xff4df7 // pink ]; var BALLOON_COLOR_NAMES = ['red', 'blue', 'green', 'yellow', 'pink']; // Balloon size and spacing var balloonSize = Math.floor(2048 / GRID_COLS); var balloonSpacing = 0; // No gap // Store balloons in a 2D array var balloons = []; // Store all balloon objects for easy iteration var allBalloons = []; // Current color to pop var currentColor = null; var currentColorIdx = 0; // Score text var scoreTxt = new Text2('0', { size: 120, fill: 0x222222 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Helper: create balloon asset for each color for (var i = 0; i < BALLOON_COLORS.length; i++) {} // Helper: set color indicator balloon at top right var colorIndicatorBalloon = null; // Add poppable color name text at top right var colorIndicatorText = null; // Add poppable color name text at top left (English, always visible) var colorNameTopLeftText = new Text2('', { size: 90, fill: 0x222222, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); colorNameTopLeftText.anchor.set(0, 0.5); // Position at top left, but leave 110px margin for menu icon colorNameTopLeftText.x = 110; colorNameTopLeftText.y = 40; LK.gui.top.addChild(colorNameTopLeftText); // (Removed popColorMainText at top center) // Background pulse tween state var bgPulseTween = null; var bgPulseState = { t: 0 }; // t: 0 (white), t: 1 (color) function setColorIndicator(color) { // Remove previous indicator if exists if (colorIndicatorBalloon) { colorIndicatorBalloon.destroy(); colorIndicatorBalloon = null; } // Remove previous color name text if exists if (colorIndicatorText) { colorIndicatorText.destroy(); colorIndicatorText = null; } // Find color index and name var idx = -1; for (var i = 0; i < BALLOON_COLORS.length; i++) { if (parseInt(BALLOON_COLORS[i], 10) === parseInt(color, 10)) { idx = i; break; } } if (idx === -1) return; var name = BALLOON_COLOR_NAMES[idx]; // Create indicator balloon colorIndicatorBalloon = LK.getAsset('balloon_' + name, { anchorX: 1, anchorY: 0, x: 2048 - 40, y: 40, scaleX: 1.2, scaleY: 1.2 }); // Add to GUI top right (not game, so it stays on top) LK.gui.topRight.addChild(colorIndicatorBalloon); // Create and add color name text colorIndicatorText = new Text2(name.toUpperCase(), { size: 90, fill: 0x222222, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); colorIndicatorText.anchor.set(1, 0.5); // Position text to the left of the balloon, vertically centered colorIndicatorText.x = 2048 - 180; colorIndicatorText.y = 40 + colorIndicatorBalloon.height * colorIndicatorBalloon.scaleY / 2; LK.gui.topRight.addChild(colorIndicatorText); // (Removed update of popColorMainText at top center) // Update the top left color name text (English, capitalized) and set its color to the actual color if (colorNameTopLeftText) { colorNameTopLeftText.setText(name.charAt(0).toUpperCase() + name.slice(1)); colorNameTopLeftText.style.fill = color; // Set text color to the actual balloon color } // Animate pulse (fade in/out forever) function pulseIndicator() { if (!colorIndicatorBalloon) return; colorIndicatorBalloon.alpha = 1; tween(colorIndicatorBalloon, { alpha: 0.3 }, { duration: 400, easing: tween.easeIn, onFinish: function onFinish() { if (!colorIndicatorBalloon) return; tween(colorIndicatorBalloon, { alpha: 1 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { pulseIndicator(); } }); } }); } pulseIndicator(); // --- Background pulse logic --- // Stop previous tween if any if (bgPulseTween) { tween.stop(bgPulseState, { t: true }); bgPulseTween = null; } // Helper to blend two colors function lerpColor(a, b, t) { var ar = a >> 16 & 0xFF, ag = a >> 8 & 0xFF, ab = a & 0xFF; var br = b >> 16 & 0xFF, bg = b >> 8 & 0xFF, bb = b & 0xFF; var rr = Math.round(ar + (br - ar) * t); var rg = Math.round(ag + (bg - ag) * t); var rb = Math.round(ab + (bb - ab) * t); return rr << 16 | rg << 8 | rb; } // Pulse between white and the poppable color function pulseBackground(toColor) { // Animate t: 0 -> 1 (white to color) bgPulseState.t = 0; function pulseToColor() { tween(bgPulseState, { t: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { pulseToWhite(); } }); } function pulseToWhite() { tween(bgPulseState, { t: 0 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { pulseToColor(); } }); } pulseToColor(); // Store for stopping later bgPulseTween = true; } pulseBackground(color); // Patch game.update to set backgroundColor each frame if (!game._bgPulsePatched) { var origUpdate = game.update; game.update = function () { // Set background color based on bgPulseState.t if (typeof bgPulseState.t === "number" && currentColor != null) { var bgCol = lerpColor(0xffffff, currentColor, bgPulseState.t); game.setBackgroundColor(bgCol); } if (origUpdate) origUpdate.apply(this, arguments); }; game._bgPulsePatched = true; } } // Helper: find all connected balloons of the same color (DFS, only side-by-side or vertical) function findConnectedBalloons(x, y, color) { var visited = {}; var group = []; function dfs(cx, cy) { var key = cx + ',' + cy; if (visited[key]) return; if (cx < 0 || cy < 0 || cx >= GRID_COLS || cy >= GRID_ROWS) return; var b = balloons[cx][cy]; if (!b || b.popped || parseInt(b.color, 10) !== parseInt(color, 10)) return; visited[key] = true; group.push(b); // Check neighbors (up, down, left, right) - no diagonal dfs(cx - 1, cy); // left dfs(cx + 1, cy); // right dfs(cx, cy - 1); // up dfs(cx, cy + 1); // down } dfs(x, y); return group; } // Helper: pick a new color (random, but must exist on board) function pickNewColor() { // Find all colors still present, and count how many of each var present = {}; for (var i = 0; i < allBalloons.length; i++) { var b = allBalloons[i]; if (!b.popped) { if (!present[b.color]) present[b.color] = 0; present[b.color]++; } } var presentColors = []; for (var i = 0; i < BALLOON_COLORS.length; i++) { if (present[BALLOON_COLORS[i]] && present[BALLOON_COLORS[i]] > 0) presentColors.push(BALLOON_COLORS[i]); } if (presentColors.length === 0) { // Win condition: all balloons popped LK.showYouWin(); return; } // Pick random color var idx = Math.floor(Math.random() * presentColors.length); currentColor = presentColors[idx]; setColorIndicator(currentColor); } // Build the balloon grid function buildGrid() { // Center grid var offsetX = Math.floor((2048 - GRID_COLS * balloonSize) / 2) + balloonSize / 2; var offsetY = Math.floor((2732 - GRID_ROWS * balloonSize) / 2) + balloonSize / 2; balloons = []; allBalloons = []; for (var x = 0; x < GRID_COLS; x++) { balloons[x] = []; for (var y = 0; y < GRID_ROWS; y++) { // Pick random color var colorIdx = Math.floor(Math.random() * BALLOON_COLORS.length); var color = BALLOON_COLORS[colorIdx]; var name = BALLOON_COLOR_NAMES[colorIdx]; var balloon = new Balloon(); balloon.color = color; balloon.gridX = x; balloon.gridY = y; // Set asset to correct color balloon.removeChildren(); balloon.attachAsset('balloon_' + name, { anchorX: 0.5, anchorY: 0.5 }); balloon.x = offsetX + x * (balloonSize + balloonSpacing); balloon.y = offsetY + y * (balloonSize + balloonSpacing); balloons[x][y] = balloon; allBalloons.push(balloon); game.addChild(balloon); } } } // Reset game state function resetGame() { LK.setScore(0); scoreTxt.setText('0'); // Remove all balloons for (var i = 0; i < allBalloons.length; i++) { allBalloons[i].destroy(); } buildGrid(); pickNewColor(); startElapsedTimer(); } // Timer for color change var colorTimer = null; function startColorTimer() { if (colorTimer) LK.clearInterval(colorTimer); colorTimer = LK.setInterval(function () { pickNewColor(); }, 3000); } // Timer for elapsed seconds var elapsedSeconds = 0; var elapsedTimer = null; var timerTxt = new Text2('Time: 0s', { size: 90, fill: 0x222222 }); timerTxt.anchor.set(0.5, 0); LK.gui.top.addChild(timerTxt); timerTxt.y = 240; function startElapsedTimer() { if (elapsedTimer) LK.clearInterval(elapsedTimer); elapsedSeconds = 0; timerTxt.setText('Time: 0s'); elapsedTimer = LK.setInterval(function () { elapsedSeconds++; timerTxt.setText('Time: ' + elapsedSeconds + 's'); }, 1000); } function stopElapsedTimer() { if (elapsedTimer) { LK.clearInterval(elapsedTimer); elapsedTimer = null; } } // Start game resetGame(); startColorTimer(); // Game update (not much needed) game.update = function () { // Check win condition var remaining = 0; for (var i = 0; i < allBalloons.length; i++) { if (!allBalloons[i].popped) remaining++; } if (remaining === 0) { stopElapsedTimer(); // Calculate score per second (100 points per balloon) var totalScore = LK.getScore(); var seconds = elapsedSeconds > 0 ? elapsedSeconds : 1; var scorePerSecond = Math.round(totalScore / seconds * 100) / 100; LK.showYouWin('Score: ' + totalScore + '\nTime: ' + seconds + 's\nScore/sec: ' + scorePerSecond); return; } // Check for at least one pair of adjacent same-color balloons (horizontal or vertical) var foundPair = false; for (var x = 0; x < GRID_COLS; x++) { for (var y = 0; y < GRID_ROWS; y++) { var b = balloons[x][y]; if (!b || b.popped) continue; // Check right neighbor if (x < GRID_COLS - 1) { var bRight = balloons[x + 1][y]; if (bRight && !bRight.popped && parseInt(b.color, 10) === parseInt(bRight.color, 10)) { foundPair = true; break; } } // Check down neighbor if (y < GRID_ROWS - 1) { var bDown = balloons[x][y + 1]; if (bDown && !bDown.popped && parseInt(b.color, 10) === parseInt(bDown.color, 10)) { foundPair = true; break; } } } if (foundPair) break; } // If no pair found, game over if (!foundPair) { stopElapsedTimer(); // Calculate score per second (100 points per balloon) var totalScore = LK.getScore(); var seconds = elapsedSeconds > 0 ? elapsedSeconds : 1; var scorePerSecond = Math.round(totalScore / seconds * 100) / 100; LK.showGameOver('Score: ' + totalScore + '\nTime: ' + seconds + 's\nScore/sec: ' + scorePerSecond); } }; // On game over or win, reset game game.onGameOver = function () { resetGame(); startColorTimer(); startElapsedTimer(); }; game.onYouWin = function () { resetGame(); startColorTimer(); startElapsedTimer(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Balloon class
var Balloon = Container.expand(function () {
var self = Container.call(this);
// Store color for logic
self.color = self.color || 0xff0000; // Default red, will be overwritten on creation
// Store grid position
self.gridX = 0;
self.gridY = 0;
// Is this balloon popped?
self.popped = false;
// Attach balloon asset (ellipse shape) - will be replaced in buildGrid with correct color
var balloonGraphics = self.attachAsset('balloon_red', {
anchorX: 0.5,
anchorY: 0.5
});
// Pop animation and logic
self.pop = function () {
if (self.popped) return;
self.popped = true;
// Animate scale down and fade out
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 250,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
};
// Down event (touch/click)
self.down = function (x, y, obj) {
if (self.popped) return;
// Only allow popping if this is the current color
// Always compare as integer values to avoid color type mismatch
if (parseInt(self.color, 10) !== parseInt(currentColor, 10)) return;
// Find all connected balloons of the same color (side-by-side or vertical)
var group = findConnectedBalloons(self.gridX, self.gridY, self.color);
// Only pop if at least 2 connected (including self)
if (group.length < 2) return;
for (var i = 0; i < group.length; i++) {
if (!group[i].popped) {
group[i].pop();
}
}
// Update score (100 points per balloon)
LK.setScore(LK.getScore() + group.length * 100);
scoreTxt.setText(LK.getScore());
// After popping, let balloons above fall down to fill empty spaces
LK.setTimeout(function () {
for (var x = 0; x < GRID_COLS; x++) {
// For each column, go from bottom to top
for (var y = GRID_ROWS - 1; y >= 0; y--) {
if (!balloons[x][y] || balloons[x][y].popped) {
// Find the nearest non-popped balloon above
for (var aboveY = y - 1; aboveY >= 0; aboveY--) {
if (balloons[x][aboveY] && !balloons[x][aboveY].popped) {
// Move this balloon down
var b = balloons[x][aboveY];
// Update grid
balloons[x][y] = b;
balloons[x][aboveY] = null;
b.gridY = y;
// Animate drop
var targetY = balloons[x][y].y = Math.floor((2732 - GRID_ROWS * balloonSize) / 2) + balloonSize / 2 + y * (balloonSize + balloonSpacing);
tween(b, {
y: targetY
}, {
duration: 200,
easing: tween.easeIn
});
break;
}
}
}
}
}
// After all drops, fill empty spots at the top with null (no new balloons)
for (var x = 0; x < GRID_COLS; x++) {
for (var y = 0; y < GRID_ROWS; y++) {
if (!balloons[x][y] || balloons[x][y] && balloons[x][y].popped) {
balloons[x][y] = null;
}
}
}
}, 260); // Wait for pop animation to finish
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
// Balloon grid settings
var GRID_COLS = 10;
var GRID_ROWS = 12;
var BALLOON_COLORS = [0xff4d4d,
// red
0x4db8ff,
// blue
0x4dff4d,
// green
0xffe14d,
// yellow
0xff4df7 // pink
];
var BALLOON_COLOR_NAMES = ['red', 'blue', 'green', 'yellow', 'pink'];
// Balloon size and spacing
var balloonSize = Math.floor(2048 / GRID_COLS);
var balloonSpacing = 0; // No gap
// Store balloons in a 2D array
var balloons = [];
// Store all balloon objects for easy iteration
var allBalloons = [];
// Current color to pop
var currentColor = null;
var currentColorIdx = 0;
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0x222222
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: create balloon asset for each color
for (var i = 0; i < BALLOON_COLORS.length; i++) {}
// Helper: set color indicator balloon at top right
var colorIndicatorBalloon = null;
// Add poppable color name text at top right
var colorIndicatorText = null;
// Add poppable color name text at top left (English, always visible)
var colorNameTopLeftText = new Text2('', {
size: 90,
fill: 0x222222,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
colorNameTopLeftText.anchor.set(0, 0.5);
// Position at top left, but leave 110px margin for menu icon
colorNameTopLeftText.x = 110;
colorNameTopLeftText.y = 40;
LK.gui.top.addChild(colorNameTopLeftText);
// (Removed popColorMainText at top center)
// Background pulse tween state
var bgPulseTween = null;
var bgPulseState = {
t: 0
}; // t: 0 (white), t: 1 (color)
function setColorIndicator(color) {
// Remove previous indicator if exists
if (colorIndicatorBalloon) {
colorIndicatorBalloon.destroy();
colorIndicatorBalloon = null;
}
// Remove previous color name text if exists
if (colorIndicatorText) {
colorIndicatorText.destroy();
colorIndicatorText = null;
}
// Find color index and name
var idx = -1;
for (var i = 0; i < BALLOON_COLORS.length; i++) {
if (parseInt(BALLOON_COLORS[i], 10) === parseInt(color, 10)) {
idx = i;
break;
}
}
if (idx === -1) return;
var name = BALLOON_COLOR_NAMES[idx];
// Create indicator balloon
colorIndicatorBalloon = LK.getAsset('balloon_' + name, {
anchorX: 1,
anchorY: 0,
x: 2048 - 40,
y: 40,
scaleX: 1.2,
scaleY: 1.2
});
// Add to GUI top right (not game, so it stays on top)
LK.gui.topRight.addChild(colorIndicatorBalloon);
// Create and add color name text
colorIndicatorText = new Text2(name.toUpperCase(), {
size: 90,
fill: 0x222222,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
colorIndicatorText.anchor.set(1, 0.5);
// Position text to the left of the balloon, vertically centered
colorIndicatorText.x = 2048 - 180;
colorIndicatorText.y = 40 + colorIndicatorBalloon.height * colorIndicatorBalloon.scaleY / 2;
LK.gui.topRight.addChild(colorIndicatorText);
// (Removed update of popColorMainText at top center)
// Update the top left color name text (English, capitalized) and set its color to the actual color
if (colorNameTopLeftText) {
colorNameTopLeftText.setText(name.charAt(0).toUpperCase() + name.slice(1));
colorNameTopLeftText.style.fill = color; // Set text color to the actual balloon color
}
// Animate pulse (fade in/out forever)
function pulseIndicator() {
if (!colorIndicatorBalloon) return;
colorIndicatorBalloon.alpha = 1;
tween(colorIndicatorBalloon, {
alpha: 0.3
}, {
duration: 400,
easing: tween.easeIn,
onFinish: function onFinish() {
if (!colorIndicatorBalloon) return;
tween(colorIndicatorBalloon, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
pulseIndicator();
}
});
}
});
}
pulseIndicator();
// --- Background pulse logic ---
// Stop previous tween if any
if (bgPulseTween) {
tween.stop(bgPulseState, {
t: true
});
bgPulseTween = null;
}
// Helper to blend two colors
function lerpColor(a, b, t) {
var ar = a >> 16 & 0xFF,
ag = a >> 8 & 0xFF,
ab = a & 0xFF;
var br = b >> 16 & 0xFF,
bg = b >> 8 & 0xFF,
bb = b & 0xFF;
var rr = Math.round(ar + (br - ar) * t);
var rg = Math.round(ag + (bg - ag) * t);
var rb = Math.round(ab + (bb - ab) * t);
return rr << 16 | rg << 8 | rb;
}
// Pulse between white and the poppable color
function pulseBackground(toColor) {
// Animate t: 0 -> 1 (white to color)
bgPulseState.t = 0;
function pulseToColor() {
tween(bgPulseState, {
t: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
pulseToWhite();
}
});
}
function pulseToWhite() {
tween(bgPulseState, {
t: 0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
pulseToColor();
}
});
}
pulseToColor();
// Store for stopping later
bgPulseTween = true;
}
pulseBackground(color);
// Patch game.update to set backgroundColor each frame
if (!game._bgPulsePatched) {
var origUpdate = game.update;
game.update = function () {
// Set background color based on bgPulseState.t
if (typeof bgPulseState.t === "number" && currentColor != null) {
var bgCol = lerpColor(0xffffff, currentColor, bgPulseState.t);
game.setBackgroundColor(bgCol);
}
if (origUpdate) origUpdate.apply(this, arguments);
};
game._bgPulsePatched = true;
}
}
// Helper: find all connected balloons of the same color (DFS, only side-by-side or vertical)
function findConnectedBalloons(x, y, color) {
var visited = {};
var group = [];
function dfs(cx, cy) {
var key = cx + ',' + cy;
if (visited[key]) return;
if (cx < 0 || cy < 0 || cx >= GRID_COLS || cy >= GRID_ROWS) return;
var b = balloons[cx][cy];
if (!b || b.popped || parseInt(b.color, 10) !== parseInt(color, 10)) return;
visited[key] = true;
group.push(b);
// Check neighbors (up, down, left, right) - no diagonal
dfs(cx - 1, cy); // left
dfs(cx + 1, cy); // right
dfs(cx, cy - 1); // up
dfs(cx, cy + 1); // down
}
dfs(x, y);
return group;
}
// Helper: pick a new color (random, but must exist on board)
function pickNewColor() {
// Find all colors still present, and count how many of each
var present = {};
for (var i = 0; i < allBalloons.length; i++) {
var b = allBalloons[i];
if (!b.popped) {
if (!present[b.color]) present[b.color] = 0;
present[b.color]++;
}
}
var presentColors = [];
for (var i = 0; i < BALLOON_COLORS.length; i++) {
if (present[BALLOON_COLORS[i]] && present[BALLOON_COLORS[i]] > 0) presentColors.push(BALLOON_COLORS[i]);
}
if (presentColors.length === 0) {
// Win condition: all balloons popped
LK.showYouWin();
return;
}
// Pick random color
var idx = Math.floor(Math.random() * presentColors.length);
currentColor = presentColors[idx];
setColorIndicator(currentColor);
}
// Build the balloon grid
function buildGrid() {
// Center grid
var offsetX = Math.floor((2048 - GRID_COLS * balloonSize) / 2) + balloonSize / 2;
var offsetY = Math.floor((2732 - GRID_ROWS * balloonSize) / 2) + balloonSize / 2;
balloons = [];
allBalloons = [];
for (var x = 0; x < GRID_COLS; x++) {
balloons[x] = [];
for (var y = 0; y < GRID_ROWS; y++) {
// Pick random color
var colorIdx = Math.floor(Math.random() * BALLOON_COLORS.length);
var color = BALLOON_COLORS[colorIdx];
var name = BALLOON_COLOR_NAMES[colorIdx];
var balloon = new Balloon();
balloon.color = color;
balloon.gridX = x;
balloon.gridY = y;
// Set asset to correct color
balloon.removeChildren();
balloon.attachAsset('balloon_' + name, {
anchorX: 0.5,
anchorY: 0.5
});
balloon.x = offsetX + x * (balloonSize + balloonSpacing);
balloon.y = offsetY + y * (balloonSize + balloonSpacing);
balloons[x][y] = balloon;
allBalloons.push(balloon);
game.addChild(balloon);
}
}
}
// Reset game state
function resetGame() {
LK.setScore(0);
scoreTxt.setText('0');
// Remove all balloons
for (var i = 0; i < allBalloons.length; i++) {
allBalloons[i].destroy();
}
buildGrid();
pickNewColor();
startElapsedTimer();
}
// Timer for color change
var colorTimer = null;
function startColorTimer() {
if (colorTimer) LK.clearInterval(colorTimer);
colorTimer = LK.setInterval(function () {
pickNewColor();
}, 3000);
}
// Timer for elapsed seconds
var elapsedSeconds = 0;
var elapsedTimer = null;
var timerTxt = new Text2('Time: 0s', {
size: 90,
fill: 0x222222
});
timerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timerTxt);
timerTxt.y = 240;
function startElapsedTimer() {
if (elapsedTimer) LK.clearInterval(elapsedTimer);
elapsedSeconds = 0;
timerTxt.setText('Time: 0s');
elapsedTimer = LK.setInterval(function () {
elapsedSeconds++;
timerTxt.setText('Time: ' + elapsedSeconds + 's');
}, 1000);
}
function stopElapsedTimer() {
if (elapsedTimer) {
LK.clearInterval(elapsedTimer);
elapsedTimer = null;
}
}
// Start game
resetGame();
startColorTimer();
// Game update (not much needed)
game.update = function () {
// Check win condition
var remaining = 0;
for (var i = 0; i < allBalloons.length; i++) {
if (!allBalloons[i].popped) remaining++;
}
if (remaining === 0) {
stopElapsedTimer();
// Calculate score per second (100 points per balloon)
var totalScore = LK.getScore();
var seconds = elapsedSeconds > 0 ? elapsedSeconds : 1;
var scorePerSecond = Math.round(totalScore / seconds * 100) / 100;
LK.showYouWin('Score: ' + totalScore + '\nTime: ' + seconds + 's\nScore/sec: ' + scorePerSecond);
return;
}
// Check for at least one pair of adjacent same-color balloons (horizontal or vertical)
var foundPair = false;
for (var x = 0; x < GRID_COLS; x++) {
for (var y = 0; y < GRID_ROWS; y++) {
var b = balloons[x][y];
if (!b || b.popped) continue;
// Check right neighbor
if (x < GRID_COLS - 1) {
var bRight = balloons[x + 1][y];
if (bRight && !bRight.popped && parseInt(b.color, 10) === parseInt(bRight.color, 10)) {
foundPair = true;
break;
}
}
// Check down neighbor
if (y < GRID_ROWS - 1) {
var bDown = balloons[x][y + 1];
if (bDown && !bDown.popped && parseInt(b.color, 10) === parseInt(bDown.color, 10)) {
foundPair = true;
break;
}
}
}
if (foundPair) break;
}
// If no pair found, game over
if (!foundPair) {
stopElapsedTimer();
// Calculate score per second (100 points per balloon)
var totalScore = LK.getScore();
var seconds = elapsedSeconds > 0 ? elapsedSeconds : 1;
var scorePerSecond = Math.round(totalScore / seconds * 100) / 100;
LK.showGameOver('Score: ' + totalScore + '\nTime: ' + seconds + 's\nScore/sec: ' + scorePerSecond);
}
};
// On game over or win, reset game
game.onGameOver = function () {
resetGame();
startColorTimer();
startElapsedTimer();
};
game.onYouWin = function () {
resetGame();
startColorTimer();
startElapsedTimer();
};