User prompt
oyundakş son değişikliği kaldır
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof sayaBarBg !== "undefined" && sayaBarBg !== null && typeof sayaBarBg.x !== "undefined" && typeof sayaBarBg.y !== "undefined") {' Line Number: 1399
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof sayaBarBg !== "undefined" && sayaBarBg !== null && typeof sayaBarBg.x !== "undefined" && typeof sayaBarBg.y !== "undefined" && (typeof sayaBarBg[0] !== "undefined" || typeof sayaBarBg['0'] !== "undefined" || true)) {' Line Number: 1399
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof sayaBarBg !== "undefined" && sayaBarBg !== null && typeof sayaBarBg.x !== "undefined" && typeof sayaBarBg.y !== "undefined") {' Line Number: 1399
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof sayaBarBg !== "undefined" && sayaBarBg && typeof sayaBarBg.x !== "undefined" && typeof sayaBarBg.y !== "undefined") {' Line Number: 1399
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof sayaBarBg !== "undefined" && typeof sayaBarBg.x !== "undefined" && typeof sayaBarBg.y !== "undefined") {' Line Number: 1399
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof sayaBarBg !== "undefined" && sayaBarBg) {' Line Number: 1399
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'game.update = function () {' Line Number: 1384
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'game.update = function () {' Line Number: 1384
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'game.update = function () {' Line Number: 1384
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'game.update = function () {' Line Number: 1384
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'game.update = function () {' Line Number: 1384
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'game.update = function () {' Line Number: 1384
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'game.update = function () {' Line Number: 1384
User prompt
barı biraz biyit ve bar yani saniye barı saat şeklinde olsun
User prompt
Please fix the bug: 'Timeout.tick error: scoreBarBg is not defined' in or related to this line: 'var barTargetX = scoreBarBg.x + scoreBarBg.width * 0.5;' Line Number: 621
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'down')' in or related to this line: 'var _oldInfoPopupDown2 = infoPopup.down;' Line Number: 1109
User prompt
şiimdi saniye sayan bir bar ekle bu bar zarın hemen tanında olsun
User prompt
para barını biraz çok az alta al
User prompt
sayaç barını eklermisin
User prompt
sayaç zarın yanında gözüksün ve rengi beyaz olsun
User prompt
ONLİNE BİR ŞEY YAPABİLİRMİSİN YANİ İNSANLARIN OYUNU KAÇ SANİYEDE BİTİRDİĞİ İLE ALAKALI ALTTA BİR SAYAÇ OLSUN VE OYU BİTİNCE DURSUN VE OYUN BİTİNCE SIRALAMA GÖZÜKSÜN DİĞER OYNAYANLARIN YAPTIĞI
User prompt
PARA BARI YÜZ SAYISINA ULAŞINCA DURSUN VE BEN BOMBA ÖZELLİĞİNİ KULLANINCA BİRKEZ DAHA PARA BARI SIFIRLANSIN BEN KULLANMADAN SIFIRLANMASIN
User prompt
PARA BARI ÖZELLİĞİ KULLANINCA SIFIRLANSIN
User prompt
GERİ SAYIM BAŞLADIĞINDA EKRANDA GÖRÜNSÜN VE HER 100 DOLAR KAZANDIĞIMIZDA VE O PARAYLA BOMBA GÖRME HAKKIMIZI KULLANDIĞIMIZ DA PARA SIFIRLANSIN VE 2 CAN KARTINI SADECE BİRKEZ KULLNABİLELİM ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Dice visual var Dice = Container.expand(function () { var self = Container.call(this); self.value = 1; self.bg = self.attachAsset('diceBg', { width: diceSize, height: diceSize, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.text = new Text2('1', { size: 160, fill: 0x222222 }); self.text.anchor.set(0.5, 0.5); self.addChild(self.text); self.setValue = function (v) { self.value = v; self.text.setText(v + ''); }; // Animate dice roll self.rollAnim = function (finalValue, cb) { var rollTimes = 12; var i = 0; var _roll = function roll() { if (i < rollTimes) { var val = 1 + Math.floor(Math.random() * 6); self.setValue(val); i++; LK.setTimeout(_roll, 40 + i * 10); } else { self.setValue(finalValue); if (cb) cb(); } }; _roll(); }; return self; }); // GridCell: Represents a single cell in the grid var GridCell = Container.expand(function () { var self = Container.call(this); // Properties self.gridX = 0; self.gridY = 0; self.value = 1; // 1-6 self.hasBomb = false; self.isExit = false; self.isRevealed = false; // Visuals self.bg = self.attachAsset('cellBg', { width: cellSize - 8, height: cellSize - 8, color: 0xeeeeee, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.valueText = new Text2('', { size: 100, fill: 0x222222 }); self.valueText.anchor.set(0.5, 0.5); self.addChild(self.valueText); // Reveal cell (show value, bomb, or exit) self.reveal = function () { self.isRevealed = true; if (self.isExit) { self.bg.color = 0x44bb44; self.valueText.setText('Exit'); self.valueText.setStyle({ fill: 0xFFFFFF }); } else if (self.hasBomb) { self.bg.color = 0xbb2222; self.valueText.setText('💣'); self.valueText.setStyle({ fill: 0xFFFFFF }); } else { self.bg.color = 0xcccccc; self.valueText.setText(self.value + ''); self.valueText.setStyle({ fill: 0x222222 }); } }; // Hide cell (for unrevealed state) self.hide = function () { self.isRevealed = false; self.bg.color = 0xeeeeee; self.valueText.setText(self.value + ''); // Always show the cell value, even when hidden }; // Highlight for possible move self.highlight = function () { self.bg.color = 0x4488ff; }; // Remove highlight self.unhighlight = function () { if (!self.isRevealed) { self.bg.color = 0xeeeeee; } else if (self.isExit) { self.bg.color = 0x44bb44; } else if (self.hasBomb) { self.bg.color = 0xbb2222; } else { self.bg.color = 0xcccccc; } }; return self; }); // Player token var PlayerToken = Container.expand(function () { var self = Container.call(this); self.token = self.attachAsset('playerToken', { width: cellSize * 0.85, height: cellSize * 0.85, color: 0x2266cc, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x800080 }); /**** * Game Code ****/ // 1. Large colored ellipses (randomized positions, sizes, and colors) // Abstract geometric pattern background var geoBgEllipses = []; for (var i = 0; i < 7; i++) { var ellipse = LK.getAsset('cellBg', { width: 600 + Math.random() * 900, height: 400 + Math.random() * 900, color: [0x6ec6ff, 0xf7e9b0, 0xfad82b, 0x23272b, 0x44bb44, 0xbb2222, 0x3a4060][i % 7], shape: 'ellipse', anchorX: 0.5, anchorY: 0.5, alpha: 0.13 + Math.random() * 0.13 }); ellipse.x = 200 + Math.random() * 1648; ellipse.y = 200 + Math.random() * 2332; ellipse.zIndex = -1000 + i; game.addChild(ellipse); geoBgEllipses.push(ellipse); } // 2. Overlapping rotated rectangles (boxes) for (var i = 0; i < 8; i++) { var box = LK.getAsset('cellBg', { width: 300 + Math.random() * 700, height: 80 + Math.random() * 220, color: [0x23272b, 0x4488ff, 0xf6d96b, 0x181a1d, 0xcccccc, 0xfad82b, 0x3a4060][i % 7], shape: 'box', anchorX: 0.5, anchorY: 0.5, alpha: 0.10 + Math.random() * 0.10 }); box.x = 200 + Math.random() * 1648; box.y = 200 + Math.random() * 2332; box.rotation = Math.random() * Math.PI * 2; box.zIndex = -990 + i; game.addChild(box); } // 3. Scattered small circles for extra pattern for (var i = 0; i < 18; i++) { var circ = LK.getAsset('cellBg', { width: 60 + Math.random() * 80, height: 60 + Math.random() * 80, color: [0xfad82b, 0x4488ff, 0xbb2222, 0x44bb44, 0x6ec6ff][i % 5], shape: 'ellipse', anchorX: 0.5, anchorY: 0.5, alpha: 0.18 + Math.random() * 0.10 }); circ.x = 80 + Math.random() * 1888; circ.y = 80 + Math.random() * 2572; circ.zIndex = -970 + i; game.addChild(circ); } // 4. Diagonal stripes (long thin rectangles) for (var i = 0; i < 4; i++) { var stripe = LK.getAsset('cellBg', { width: 2048, height: 32 + Math.random() * 32, color: [0x23272b, 0x3a4060, 0xfad82b, 0x4488ff][i % 4], shape: 'box', anchorX: 0, anchorY: 0, alpha: 0.08 + Math.random() * 0.07 }); stripe.x = 0; stripe.y = 400 + i * 500 + Math.random() * 200; stripe.rotation = (Math.random() - 0.5) * 0.5; stripe.zIndex = -950 + i; game.addChild(stripe); } // No per-frame logic needed // Check if exit is adjacent and not already game over if (!gameOver && playerPos && typeof playerPos.x === "number" && typeof playerPos.y === "number") { var neighbors = getNeighbors(playerPos.x, playerPos.y); for (var i = 0; i < neighbors.length; i++) { if (neighbors[i].isExit) { // End game immediately and show replay option stopEndgameTimer(); neighbors[i].reveal(); LK.effects.flashScreen(0x44bb44, 900); gameOver = true; LK.setTimeout(function () { LK.showYouWin(); }, 900); infoText.setText('You reached the exit!'); break; } } } var gridSize = 8; var cellSize = Math.floor(2000 / gridSize); // Increased cell size for better visibility var gridOffsetX = Math.floor((2048 - cellSize * gridSize) / 2); var gridOffsetY = 250; // Move grid up a bit to fit larger elements var diceSize = 340; // Larger dice // --- State --- var grid = []; var playerPos = { x: 0, y: 0 }; var exitPos = { x: 0, y: 0 }; var playerToken = null; var dice = null; var canRoll = true; var possibleMoves = []; var gameOver = false; var moveCount = 0; var bombCount = 10; // Number of bombs // --- Timer for endgame after 15 moves --- var moveLimit = 15; var endgameCountdown = 30; // seconds var endgameTimer = null; var endgameTimerText = null; var endgameTimerInterval = null; var endgameTimerActive = false; // --- GUI --- // --- Score Bar --- var score = 0; var scoreBarBg = LK.getAsset('cellBg', { width: 500, height: 38, color: 0x222222, shape: 'box', anchorX: 0, anchorY: 0.5, alpha: 0.7 }); scoreBarBg.x = 124; // leave 100px for menu, 24px margin scoreBarBg.y = 120; scoreBarBg.zIndex = 10000; LK.gui.top.addChild(scoreBarBg); var scoreBarFill = LK.getAsset('cellBg', { width: 0, height: 32, color: 0x22cc44, shape: 'box', anchorX: 0, anchorY: 0.5, alpha: 0.95 }); scoreBarFill.x = 127; scoreBarFill.y = 120; scoreBarFill.zIndex = 10001; LK.gui.top.addChild(scoreBarFill); var scoreText = new Text2('0', { size: 36, fill: "#fff", font: "bold", align: "center" }); scoreText.anchor.set(0.5, 0.5); scoreText.x = 124 + 500 / 2; scoreText.y = 120; scoreText.zIndex = 10002; LK.gui.top.addChild(scoreText); function updateScoreBar(newScore) { scoreText.setText(newScore + ''); var maxScore = gridSize * gridSize * 10; var targetWidth = Math.max(0, Math.min(1, newScore / maxScore)) * 494; tween(scoreBarFill, { width: targetWidth }, { duration: 400, easing: tween.cubicOut }); } // --- Heart Bar (Life Bar) --- var maxHearts = 2; var currentHearts = 1; var heartBar = []; var heartBarX = 2048 - 220; var heartBarY = 120; function drawHeartBar() { // Remove old hearts for (var i = 0; i < heartBar.length; i++) { if (heartBar[i].parent) LK.gui.top.removeChild(heartBar[i]); } heartBar = []; for (var i = 0; i < maxHearts; i++) { var heart = LK.getAsset('cellBg', { width: 60, height: 60, color: i < currentHearts ? 0xff3366 : 0x888888, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5, alpha: 0.93 }); heart.x = heartBarX + i * 70; heart.y = heartBarY; heart.zIndex = 10010 + i; LK.gui.top.addChild(heart); heartBar.push(heart); } } drawHeartBar(); // --- Animated +10 floating text --- function showScoreAnim(x, y, text) { var plusText = new Text2(text || '+$20', { size: 44, fill: 0x22CC44, font: "bold", align: "center" }); plusText.anchor.set(0.5, 0.5); plusText.x = x; plusText.y = y; plusText.alpha = 1; plusText.zIndex = 10010; game.addChild(plusText); tween(plusText, { y: y - 90, alpha: 0 }, { duration: 700, easing: tween.cubicOut, onComplete: function onComplete() { if (plusText.parent) plusText.parent.removeChild(plusText); } }); } var infoText = new Text2('', { size: 70, fill: 0x333333 }); infoText.anchor.set(0.5, 0); LK.gui.top.addChild(infoText); // Timer text (hidden by default) endgameTimerText = new Text2('', { size: 80, fill: 0xBB2222, font: "bold", align: "center" }); endgameTimerText.anchor.set(0.5, 0); endgameTimerText.x = 2048 / 2; endgameTimerText.y = 180; endgameTimerText.visible = false; LK.gui.top.addChild(endgameTimerText); // Helper to start the 20s countdown function startEndgameTimer() { if (endgameTimerActive) return; endgameTimerActive = true; endgameCountdown = 30; endgameTimerText.visible = true; endgameTimerText.setText('Time: 30'); // Show timer text on screen when countdown starts endgameTimerText.visible = true; endgameTimerInterval = LK.setInterval(function () { if (gameOver) { LK.clearInterval(endgameTimerInterval); endgameTimerText.visible = false; return; } endgameCountdown--; endgameTimerText.setText('Time: ' + endgameCountdown); if (endgameCountdown <= 0) { LK.clearInterval(endgameTimerInterval); endgameTimerText.visible = false; gameOver = true; LK.effects.flashScreen(0xbb2222, 900); LK.setTimeout(function () { LK.showGameOver(); }, 900); infoText.setText('Time is up! You lost.'); } }, 1000); } // Helper to stop the timer (on win/lose) function stopEndgameTimer() { if (endgameTimerInterval) { LK.clearInterval(endgameTimerInterval); endgameTimerInterval = null; } endgameTimerText.visible = false; endgameTimerActive = false; } // --- Functions --- // Generate grid with random values, bombs, and exit function generateGrid() { grid = []; // Place bombs var bombCells = []; while (bombCells.length < bombCount) { var bx = Math.floor(Math.random() * gridSize); var by = Math.floor(Math.random() * gridSize); if (bx === 0 && by === 0 || bombCells.some(function (b) { return b.x === bx && b.y === by; })) continue; bombCells.push({ x: bx, y: by }); } // Place exit do { exitPos.x = Math.floor(Math.random() * gridSize); exitPos.y = Math.floor(Math.random() * gridSize); } while (exitPos.x === 0 && exitPos.y === 0 || bombCells.some(function (b) { return b.x === exitPos.x && b.y === exitPos.y; })); // Build grid for (var y = 0; y < gridSize; y++) { var row = []; for (var x = 0; x < gridSize; x++) { var cell = new GridCell(); cell.gridX = x; cell.gridY = y; cell.x = gridOffsetX + x * cellSize + cellSize / 2; cell.y = gridOffsetY + y * cellSize + cellSize / 2; cell.value = 1 + Math.floor(Math.random() * 6); cell.hasBomb = bombCells.some(function (b) { return b.x === x && b.y === y; }); cell.isExit = x === exitPos.x && y === exitPos.y; if (cell.isExit) { cell.value = 6; // Exit cell always has value 6 cell.reveal(); // Always show exit cell } else { cell.hide(); } game.addChild(cell); row.push(cell); } grid.push(row); } } // Get neighbors of (x, y) function getNeighbors(x, y) { var neighbors = []; for (var dx = -1; dx <= 1; dx++) { for (var dy = -1; dy <= 1; dy++) { if (dx === 0 && dy === 0) continue; var nx = x + dx; var ny = y + dy; if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize) { neighbors.push(grid[ny][nx]); } } } return neighbors; } // Highlight possible moves for current dice value // --- Arrow UI for multiple moves --- var moveArrows = []; function clearMoveArrows() { for (var i = 0; i < moveArrows.length; i++) { if (moveArrows[i] && moveArrows[i].parent) { moveArrows[i].parent.removeChild(moveArrows[i]); } } moveArrows = []; } function createArrowForCell(cell, idx) { // Use a yellow box as arrow for now, can be replaced with a real arrow asset var arrow = LK.getAsset('diceTap', { width: cellSize * 0.35, height: cellSize * 0.35, color: 0xfad82b, anchorX: 0.5, anchorY: 0.5, alpha: 0.85 }); arrow.x = cell.x; arrow.y = cell.y; arrow.zIndex = 1000 + idx; arrow.down = function (x, y, obj) { if (!canRoll && !gameOver) { movePlayerTo(cell); clearMoveArrows(); } }; game.addChild(arrow); moveArrows.push(arrow); } function highlightPossibleMoves(diceValue) { possibleMoves = []; clearMoveArrows(); var neighbors = getNeighbors(playerPos.x, playerPos.y); for (var i = 0; i < neighbors.length; i++) { var cell = neighbors[i]; if (!cell.isRevealed && cell.value === diceValue) { cell.highlight(); possibleMoves.push(cell); } } // If only one possible move, auto-move if (possibleMoves.length === 1) { // Delay slightly for UX LK.setTimeout(function () { if (!canRoll && !gameOver) { movePlayerTo(possibleMoves[0]); clearMoveArrows(); } }, 350); } else if (possibleMoves.length > 1) { // Show arrows for each possible move for (var i = 0; i < possibleMoves.length; i++) { createArrowForCell(possibleMoves[i], i); } } } // Remove all highlights function clearHighlights() { for (var y = 0; y < gridSize; y++) { for (var x = 0; x < gridSize; x++) { grid[y][x].unhighlight(); // Always keep exit cell revealed if (grid[y][x].isExit) { grid[y][x].reveal(); } } } clearMoveArrows(); } // Move player to cell function movePlayerTo(cell) { playerPos.x = cell.gridX; playerPos.y = cell.gridY; moveCount++; // --- Score logic: +20 per cell moved --- score += 20; // If score reaches or exceeds 100, reset to 0 and allow bomb reveal card again if (score >= 100) { score = 0; cardRevealBombsUsed = false; cardRevealBombsBtn.setText('Bombaları Göster'); cardRevealBombsBtn.alpha = 1; infoText.setText('You earned $100! Card is available again.'); } updateScoreBar(score); // --- Money bundle animation: animate a money bundle from the cell to the score bar --- (function animateMoneyBundle() { // Create a money bundle asset (use cellBg as a green box for now) var moneyBundle = LK.getAsset('cellBg', { width: cellSize * 0.38, height: cellSize * 0.24, color: 0x22cc44, shape: 'box', anchorX: 0.5, anchorY: 0.5, alpha: 1, zIndex: 10010 }); moneyBundle.x = cell.x; moneyBundle.y = cell.y - cellSize * 0.18; game.addChild(moneyBundle); // Animate directly to the score bar and disappear var barTargetX = scoreBarBg.x + scoreBarBg.width * 0.5; var barTargetY = scoreBarBg.y; // Convert GUI coordinates to game coordinates for smooth animation var guiToGameX = barTargetX; var guiToGameY = barTargetY + 60; // visually align with bar tween(moneyBundle, { x: guiToGameX, y: guiToGameY, scaleX: 0.7, scaleY: 0.7, alpha: 0.0 }, { duration: 600, easing: tween.cubicInOut, onComplete: function onComplete() { if (moneyBundle.parent) moneyBundle.parent.removeChild(moneyBundle); } }); })(); updateScoreBar(score); showScoreAnim(cell.x, cell.y - cellSize * 0.35, '+$20'); clearMoveArrows(); // --- Extra card use if score bar reaches 100 (only once) --- if (!movePlayerTo._extraCardGiven && score >= 100) { movePlayerTo._extraCardGiven = true; cardRevealBombsUsed = false; cardRevealBombsBtn.setText('Bombaları Göster'); cardRevealBombsBtn.alpha = 1; infoText.setText('Tebrikler! Kartı tekrar kullanabilirsin.'); } tween(playerToken, { x: cell.x, y: cell.y }, { duration: 220, easing: tween.cubicOut }); cell.reveal(); // Start endgame timer after 20th move if (moveCount === moveLimit) { startEndgameTimer(); } if (cell.hasBomb) { if (currentHearts > 1) { // Use shield instead of dying currentHearts = 1; drawHeartBar(); infoText.setText('You hit a bomb! Shield used, 1 life left.'); // Animate heart bar for (var i = 0; i < heartBar.length; i++) { tween(heartBar[i], { scaleX: 1.3, scaleY: 1.3 }, { duration: 180, easing: tween.cubicOut, onComplete: function (h) { return function () { tween(h, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.cubicIn }); }; }(heartBar[i]) }); } // Reveal the bomb cell, but do not end the game cell.reveal(); LK.effects.flashScreen(0xff0000, 600); // Remove highlights and allow next move canRoll = true; clearHighlights(); grid[exitPos.y][exitPos.x].reveal(); return; } stopEndgameTimer(); // --- Shatter animation for the bomb cell --- var shatterPieces = []; var pieceCount = 12 + Math.floor(Math.random() * 4); for (var i = 0; i < pieceCount; i++) { var angle = Math.PI * 2 * (i / pieceCount) + Math.random() * 0.2; var dist = cellSize * (0.7 + Math.random() * 0.7); var px = cell.x + Math.cos(angle) * (cellSize * 0.08 + Math.random() * cellSize * 0.08); var py = cell.y + Math.sin(angle) * (cellSize * 0.08 + Math.random() * cellSize * 0.08); var piece = LK.getAsset('cellBg', { width: cellSize * (0.18 + Math.random() * 0.13), height: cellSize * (0.18 + Math.random() * 0.13), color: 0xbb2222, shape: 'box', anchorX: 0.5, anchorY: 0.5, alpha: 0.92 }); piece.x = px; piece.y = py; piece.zIndex = 10000 + i; game.addChild(piece); shatterPieces.push(piece); // Animate each piece flying outward, rotating and fading (function (p, a, d) { var tx = cell.x + Math.cos(a) * d; var ty = cell.y + Math.sin(a) * d; var rot = (Math.random() - 0.5) * Math.PI * 1.2; tween(p, { x: tx, y: ty, rotation: rot, alpha: 0 }, { duration: 650 + Math.random() * 250, easing: tween.cubicOut, onComplete: function onComplete() { if (p.parent) p.parent.removeChild(p); } }); })(piece, angle, dist); } // Hide the cell's background and valueText for the shatter effect cell.bg.visible = false; cell.valueText.visible = false; // --- Black smoke after shatter --- LK.setTimeout(function () { var postSmoke = LK.getAsset('cellBg', { width: cellSize * 1.5, height: cellSize * 1.5, color: 0x111111, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5, alpha: 0.55 }); postSmoke.x = cell.x; postSmoke.y = cell.y; postSmoke.zIndex = 9997; game.addChild(postSmoke); tween(postSmoke, { scaleX: 2.8, scaleY: 2.8, alpha: 0 }, { duration: 1200, easing: tween.cubicOut, onComplete: function onComplete() { if (postSmoke.parent) postSmoke.parent.removeChild(postSmoke); } }); }, 320); // --- Existing explosion and smoke/particle effects --- var explosion = LK.getAsset('cellBg', { width: cellSize * 1.1, height: cellSize * 1.1, color: 0xffe066, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5, alpha: 0.85 }); explosion.x = cell.x; explosion.y = cell.y; explosion.zIndex = 9999; game.addChild(explosion); // Black smoke effect (grows and fades) var smoke = LK.getAsset('cellBg', { width: cellSize * 1.2, height: cellSize * 1.2, color: 0x111111, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5, alpha: 0.45 }); smoke.x = cell.x; smoke.y = cell.y; smoke.zIndex = 9998; game.addChild(smoke); tween(smoke, { scaleX: 2.5, scaleY: 2.5, alpha: 0 }, { duration: 900, easing: tween.cubicOut, onComplete: function onComplete() { if (smoke.parent) smoke.parent.removeChild(smoke); } }); // Particle burst (black debris) for (var i = 0; i < 16; i++) { var angle = Math.PI * 2 * (i / 16) + Math.random() * 0.2; var dist = cellSize * (0.7 + Math.random() * 0.7); var px = cell.x + Math.cos(angle) * 10; var py = cell.y + Math.sin(angle) * 10; var particle = LK.getAsset('cellBg', { width: 22 + Math.random() * 16, height: 22 + Math.random() * 16, color: 0x222222, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5, alpha: 0.7 + Math.random() * 0.2 }); particle.x = px; particle.y = py; particle.zIndex = 9999; game.addChild(particle); (function (p, a, d) { tween(p, { x: cell.x + Math.cos(a) * d, y: cell.y + Math.sin(a) * d, alpha: 0, scaleX: 0.7 + Math.random() * 0.5, scaleY: 0.7 + Math.random() * 0.5 }, { duration: 700 + Math.random() * 300, easing: tween.cubicOut, onComplete: function onComplete() { if (p.parent) p.parent.removeChild(p); } }); })(particle, angle, dist); } // Animate: grow and fade out tween(explosion, { scaleX: 2.2, scaleY: 2.2, alpha: 0 }, { duration: 600, easing: tween.cubicOut, onComplete: function onComplete() { if (explosion.parent) explosion.parent.removeChild(explosion); } }); LK.effects.flashScreen(0xff0000, 900); gameOver = true; LK.setTimeout(function () { LK.showGameOver(); }, 900); infoText.setText('Bomba! Oyun bitti.'); return; } if (cell.isExit) { stopEndgameTimer(); LK.effects.flashScreen(0x44bb44, 900); gameOver = true; LK.setTimeout(function () { LK.showYouWin(); }, 900); infoText.setText('Congratulations! You reached the exit.'); return; } infoText.setText('Move: ' + moveCount); canRoll = true; clearHighlights(); // Always keep exit cell revealed grid[exitPos.y][exitPos.x].reveal(); } // Handle tap on a cell function onCellDown(x, y, obj) { if (!canRoll && !gameOver) { // If arrows are present, only allow move via arrow tap if (moveArrows.length > 0) return; // Only allow move if the tapped cell is in possibleMoves (highlighted and matches dice) for (var i = 0; i < possibleMoves.length; i++) { if (possibleMoves[i] === obj) { movePlayerTo(obj); break; } } } } // Roll the dice function rollDice() { if (!canRoll || gameOver) return; canRoll = false; // Play dice roll sound LK.getSound('diceRoll').play(); var diceValue = 1 + Math.floor(Math.random() * 6); dice.rollAnim(diceValue, function () { highlightPossibleMoves(diceValue); // Check if exit is adjacent and matches dice value var exitIsPossible = false; var exitCell = null; var neighbors = getNeighbors(playerPos.x, playerPos.y); for (var i = 0; i < neighbors.length; i++) { if (neighbors[i].isExit) { exitCell = neighbors[i]; if (neighbors[i].value === diceValue) { exitIsPossible = true; break; } } } // If exit is adjacent and dice is 6, win immediately (regardless of exit cell value) if (exitCell && diceValue === 6) { stopEndgameTimer(); exitCell.reveal(); LK.effects.flashScreen(0x44bb44, 900); gameOver = true; LK.setTimeout(function () { LK.showYouWin(); }, 900); infoText.setText('Rolled a 6! You reached the exit.'); return; } if (possibleMoves.length === 0 && !exitIsPossible) { // No moves and exit is not possible, allow unlimited reroll canRoll = true; infoText.setText('No moves! You can roll the dice again.'); } else { infoText.setText('Move: ' + moveCount + ' | Dice: ' + diceValue); } }); } // --- Setup --- // Create grid, player, dice generateGrid(); // Reveal start cell playerPos.x = 0; playerPos.y = 0; grid[0][0].reveal(); // Player token playerToken = new PlayerToken(); playerToken.x = grid[0][0].x; playerToken.y = grid[0][0].y; game.addChild(playerToken); // --- Double-tap logic for shield (second life) --- var lastTapTime = 0; var tapCount = 0; var shieldUsed = false; // Only allow shield to be used once per game playerToken.down = function (x, y, obj) { if (gameOver) return; var now = Date.now(); if (now - lastTapTime < 400) { tapCount++; } else { tapCount = 1; } lastTapTime = now; // Double-tap: activate shield (second life) if (tapCount === 2) { tapCount = 0; if (shieldUsed) { infoText.setText('Shield can only be used once per game!'); return; } if (currentHearts === 1) { currentHearts = 2; shieldUsed = true; drawHeartBar(); infoText.setText('Shield activated! You now have 2 lives.'); // Animate hearts for (var i = 0; i < heartBar.length; i++) { tween(heartBar[i], { scaleX: 1.3, scaleY: 1.3 }, { duration: 180, easing: tween.cubicOut, onComplete: function (h) { return function () { tween(h, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.cubicIn }); }; }(heartBar[i]) }); } } else { infoText.setText('You already have 2 lives!'); } return; } // Single tap: use bomb reveal card if (cardRevealBombsUsed) return; cardRevealBombsUsed = true; cardRevealBombsBtn.setText('Kullanıldı'); cardRevealBombsBtn.alpha = 0.5; showAllBombsTemporarily(); }; // Dice dice = new Dice(); dice.x = 2048 / 2; dice.y = gridOffsetY + cellSize * gridSize + diceSize / 2 + 60; game.addChild(dice); // --- Card: Reveal Bombs (single use) --- var cardRevealBombsUsed = false; var cardRevealBombsBtn = new Text2('💣 Bombaları Göster', { size: 60, fill: "#fff", font: "bold", padding: 18, align: "center", background: 0xBB2222 }); cardRevealBombsBtn.anchor.set(0.5, 0); cardRevealBombsBtn.x = 2048 / 2; cardRevealBombsBtn.y = 80; cardRevealBombsBtn.interactive = true; cardRevealBombsBtn.buttonMode = true; LK.gui.top.addChild(cardRevealBombsBtn); function showAllBombsTemporarily() { // Reveal all bombs for (var y = 0; y < gridSize; y++) { for (var x = 0; x < gridSize; x++) { var cell = grid[y][x]; if (cell.hasBomb && !cell.isRevealed) { cell.reveal(); cell._wasTempRevealed = true; } } } infoText.setText('Bombs are visible for 10 seconds!'); // Reset score to 0 when bomb reveal card is used score = 0; updateScoreBar(score); // Hide bombs again after 10 seconds LK.setTimeout(function () { for (var y = 0; y < gridSize; y++) { for (var x = 0; x < gridSize; x++) { var cell = grid[y][x]; if (cell._wasTempRevealed) { cell.hide(); cell._wasTempRevealed = false; } } } infoText.setText('Card used. Move: ' + moveCount); }, 10000); } cardRevealBombsBtn.down = function (x, y, obj) { if (cardRevealBombsUsed || gameOver) return; cardRevealBombsUsed = true; cardRevealBombsBtn.setText('Kullanıldı'); cardRevealBombsBtn.alpha = 0.5; showAllBombsTemporarily(); }; // Dice tap area (invisible, for touch) var diceTapArea = LK.getAsset('diceTap', { width: diceSize + 60, height: diceSize + 60, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5, alpha: 0.01 }); diceTapArea.x = dice.x; diceTapArea.y = dice.y; game.addChild(diceTapArea); // Info text infoText.setText('Roll the dice to start!'); // --- Show info popup at game start --- var infoPopupBg = LK.getAsset('cellBg', { width: 1800, height: 1450, color: 0x181c22, anchorX: 0.5, anchorY: 0.5, alpha: 0.98 }); infoPopupBg.x = 2048 / 2; infoPopupBg.y = 2732 / 2; infoPopupBg.zIndex = 99999; var infoPopupText = new Text2("Each time you move to a new square, you earn $20 and the green score bar fills up with animation.\n" + "If the bar reaches 100, you can use the card one more time (only once per game).\n\n" + "NEW CARD: If you double-tap your character, you gain a shield (2 lives). If you step on a bomb with the shield, you don't die, but lose the shield instead!\n\n" + "• Roll the dice, move to a neighboring cell with the same number.\n" + "• Some cells have hidden bombs. Be careful!\n" + "• After 15 moves, a 30 second countdown starts. Hurry up!\n" + "• You can use the red card once to reveal all bombs for 10 seconds.\n" + "• You can also use the card by tapping your character.\n" + "• Double-tap your character to activate the shield (2 lives).\n\n" + "Tap anywhere to start!", { size: 56, fill: "#000", align: "center", font: "bold", padding: 18, wordWrap: true, wordWrapWidth: 1400 }); infoPopupText.anchor.set(0.5, 0.5); infoPopupText.x = 2048 / 2; infoPopupText.y = 2732 / 2; var infoPopup = new Container(); infoPopup.addChild(infoPopupBg); infoPopup.addChild(infoPopupText); game.addChild(infoPopup); infoPopup.down = function (x, y, obj) { if (infoPopup && infoPopup.parent) { infoPopup.parent.removeChild(infoPopup); // Restore English start text after closing info popup infoText.setText('Roll the dice to start!'); } }; infoPopupBg.down = infoPopup.down; infoPopupText.down = infoPopup.down; // --- Event Handlers --- // Dice tap diceTapArea.down = function (x, y, obj) { if (canRoll && !gameOver) { rollDice(); } }; // Cell tap for (var y = 0; y < gridSize; y++) { for (var x = 0; x < gridSize; x++) { grid[y][x].down = onCellDown; } } // --- Game update (not used, but required) --- game.update = function () { // No per-frame logic needed };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Dice visual
var Dice = Container.expand(function () {
var self = Container.call(this);
self.value = 1;
self.bg = self.attachAsset('diceBg', {
width: diceSize,
height: diceSize,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.text = new Text2('1', {
size: 160,
fill: 0x222222
});
self.text.anchor.set(0.5, 0.5);
self.addChild(self.text);
self.setValue = function (v) {
self.value = v;
self.text.setText(v + '');
};
// Animate dice roll
self.rollAnim = function (finalValue, cb) {
var rollTimes = 12;
var i = 0;
var _roll = function roll() {
if (i < rollTimes) {
var val = 1 + Math.floor(Math.random() * 6);
self.setValue(val);
i++;
LK.setTimeout(_roll, 40 + i * 10);
} else {
self.setValue(finalValue);
if (cb) cb();
}
};
_roll();
};
return self;
});
// GridCell: Represents a single cell in the grid
var GridCell = Container.expand(function () {
var self = Container.call(this);
// Properties
self.gridX = 0;
self.gridY = 0;
self.value = 1; // 1-6
self.hasBomb = false;
self.isExit = false;
self.isRevealed = false;
// Visuals
self.bg = self.attachAsset('cellBg', {
width: cellSize - 8,
height: cellSize - 8,
color: 0xeeeeee,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.valueText = new Text2('', {
size: 100,
fill: 0x222222
});
self.valueText.anchor.set(0.5, 0.5);
self.addChild(self.valueText);
// Reveal cell (show value, bomb, or exit)
self.reveal = function () {
self.isRevealed = true;
if (self.isExit) {
self.bg.color = 0x44bb44;
self.valueText.setText('Exit');
self.valueText.setStyle({
fill: 0xFFFFFF
});
} else if (self.hasBomb) {
self.bg.color = 0xbb2222;
self.valueText.setText('💣');
self.valueText.setStyle({
fill: 0xFFFFFF
});
} else {
self.bg.color = 0xcccccc;
self.valueText.setText(self.value + '');
self.valueText.setStyle({
fill: 0x222222
});
}
};
// Hide cell (for unrevealed state)
self.hide = function () {
self.isRevealed = false;
self.bg.color = 0xeeeeee;
self.valueText.setText(self.value + ''); // Always show the cell value, even when hidden
};
// Highlight for possible move
self.highlight = function () {
self.bg.color = 0x4488ff;
};
// Remove highlight
self.unhighlight = function () {
if (!self.isRevealed) {
self.bg.color = 0xeeeeee;
} else if (self.isExit) {
self.bg.color = 0x44bb44;
} else if (self.hasBomb) {
self.bg.color = 0xbb2222;
} else {
self.bg.color = 0xcccccc;
}
};
return self;
});
// Player token
var PlayerToken = Container.expand(function () {
var self = Container.call(this);
self.token = self.attachAsset('playerToken', {
width: cellSize * 0.85,
height: cellSize * 0.85,
color: 0x2266cc,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x800080
});
/****
* Game Code
****/
// 1. Large colored ellipses (randomized positions, sizes, and colors)
// Abstract geometric pattern background
var geoBgEllipses = [];
for (var i = 0; i < 7; i++) {
var ellipse = LK.getAsset('cellBg', {
width: 600 + Math.random() * 900,
height: 400 + Math.random() * 900,
color: [0x6ec6ff, 0xf7e9b0, 0xfad82b, 0x23272b, 0x44bb44, 0xbb2222, 0x3a4060][i % 7],
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.13 + Math.random() * 0.13
});
ellipse.x = 200 + Math.random() * 1648;
ellipse.y = 200 + Math.random() * 2332;
ellipse.zIndex = -1000 + i;
game.addChild(ellipse);
geoBgEllipses.push(ellipse);
}
// 2. Overlapping rotated rectangles (boxes)
for (var i = 0; i < 8; i++) {
var box = LK.getAsset('cellBg', {
width: 300 + Math.random() * 700,
height: 80 + Math.random() * 220,
color: [0x23272b, 0x4488ff, 0xf6d96b, 0x181a1d, 0xcccccc, 0xfad82b, 0x3a4060][i % 7],
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.10 + Math.random() * 0.10
});
box.x = 200 + Math.random() * 1648;
box.y = 200 + Math.random() * 2332;
box.rotation = Math.random() * Math.PI * 2;
box.zIndex = -990 + i;
game.addChild(box);
}
// 3. Scattered small circles for extra pattern
for (var i = 0; i < 18; i++) {
var circ = LK.getAsset('cellBg', {
width: 60 + Math.random() * 80,
height: 60 + Math.random() * 80,
color: [0xfad82b, 0x4488ff, 0xbb2222, 0x44bb44, 0x6ec6ff][i % 5],
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.18 + Math.random() * 0.10
});
circ.x = 80 + Math.random() * 1888;
circ.y = 80 + Math.random() * 2572;
circ.zIndex = -970 + i;
game.addChild(circ);
}
// 4. Diagonal stripes (long thin rectangles)
for (var i = 0; i < 4; i++) {
var stripe = LK.getAsset('cellBg', {
width: 2048,
height: 32 + Math.random() * 32,
color: [0x23272b, 0x3a4060, 0xfad82b, 0x4488ff][i % 4],
shape: 'box',
anchorX: 0,
anchorY: 0,
alpha: 0.08 + Math.random() * 0.07
});
stripe.x = 0;
stripe.y = 400 + i * 500 + Math.random() * 200;
stripe.rotation = (Math.random() - 0.5) * 0.5;
stripe.zIndex = -950 + i;
game.addChild(stripe);
}
// No per-frame logic needed
// Check if exit is adjacent and not already game over
if (!gameOver && playerPos && typeof playerPos.x === "number" && typeof playerPos.y === "number") {
var neighbors = getNeighbors(playerPos.x, playerPos.y);
for (var i = 0; i < neighbors.length; i++) {
if (neighbors[i].isExit) {
// End game immediately and show replay option
stopEndgameTimer();
neighbors[i].reveal();
LK.effects.flashScreen(0x44bb44, 900);
gameOver = true;
LK.setTimeout(function () {
LK.showYouWin();
}, 900);
infoText.setText('You reached the exit!');
break;
}
}
}
var gridSize = 8;
var cellSize = Math.floor(2000 / gridSize); // Increased cell size for better visibility
var gridOffsetX = Math.floor((2048 - cellSize * gridSize) / 2);
var gridOffsetY = 250; // Move grid up a bit to fit larger elements
var diceSize = 340; // Larger dice
// --- State ---
var grid = [];
var playerPos = {
x: 0,
y: 0
};
var exitPos = {
x: 0,
y: 0
};
var playerToken = null;
var dice = null;
var canRoll = true;
var possibleMoves = [];
var gameOver = false;
var moveCount = 0;
var bombCount = 10; // Number of bombs
// --- Timer for endgame after 15 moves ---
var moveLimit = 15;
var endgameCountdown = 30; // seconds
var endgameTimer = null;
var endgameTimerText = null;
var endgameTimerInterval = null;
var endgameTimerActive = false;
// --- GUI ---
// --- Score Bar ---
var score = 0;
var scoreBarBg = LK.getAsset('cellBg', {
width: 500,
height: 38,
color: 0x222222,
shape: 'box',
anchorX: 0,
anchorY: 0.5,
alpha: 0.7
});
scoreBarBg.x = 124; // leave 100px for menu, 24px margin
scoreBarBg.y = 120;
scoreBarBg.zIndex = 10000;
LK.gui.top.addChild(scoreBarBg);
var scoreBarFill = LK.getAsset('cellBg', {
width: 0,
height: 32,
color: 0x22cc44,
shape: 'box',
anchorX: 0,
anchorY: 0.5,
alpha: 0.95
});
scoreBarFill.x = 127;
scoreBarFill.y = 120;
scoreBarFill.zIndex = 10001;
LK.gui.top.addChild(scoreBarFill);
var scoreText = new Text2('0', {
size: 36,
fill: "#fff",
font: "bold",
align: "center"
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 124 + 500 / 2;
scoreText.y = 120;
scoreText.zIndex = 10002;
LK.gui.top.addChild(scoreText);
function updateScoreBar(newScore) {
scoreText.setText(newScore + '');
var maxScore = gridSize * gridSize * 10;
var targetWidth = Math.max(0, Math.min(1, newScore / maxScore)) * 494;
tween(scoreBarFill, {
width: targetWidth
}, {
duration: 400,
easing: tween.cubicOut
});
}
// --- Heart Bar (Life Bar) ---
var maxHearts = 2;
var currentHearts = 1;
var heartBar = [];
var heartBarX = 2048 - 220;
var heartBarY = 120;
function drawHeartBar() {
// Remove old hearts
for (var i = 0; i < heartBar.length; i++) {
if (heartBar[i].parent) LK.gui.top.removeChild(heartBar[i]);
}
heartBar = [];
for (var i = 0; i < maxHearts; i++) {
var heart = LK.getAsset('cellBg', {
width: 60,
height: 60,
color: i < currentHearts ? 0xff3366 : 0x888888,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.93
});
heart.x = heartBarX + i * 70;
heart.y = heartBarY;
heart.zIndex = 10010 + i;
LK.gui.top.addChild(heart);
heartBar.push(heart);
}
}
drawHeartBar();
// --- Animated +10 floating text ---
function showScoreAnim(x, y, text) {
var plusText = new Text2(text || '+$20', {
size: 44,
fill: 0x22CC44,
font: "bold",
align: "center"
});
plusText.anchor.set(0.5, 0.5);
plusText.x = x;
plusText.y = y;
plusText.alpha = 1;
plusText.zIndex = 10010;
game.addChild(plusText);
tween(plusText, {
y: y - 90,
alpha: 0
}, {
duration: 700,
easing: tween.cubicOut,
onComplete: function onComplete() {
if (plusText.parent) plusText.parent.removeChild(plusText);
}
});
}
var infoText = new Text2('', {
size: 70,
fill: 0x333333
});
infoText.anchor.set(0.5, 0);
LK.gui.top.addChild(infoText);
// Timer text (hidden by default)
endgameTimerText = new Text2('', {
size: 80,
fill: 0xBB2222,
font: "bold",
align: "center"
});
endgameTimerText.anchor.set(0.5, 0);
endgameTimerText.x = 2048 / 2;
endgameTimerText.y = 180;
endgameTimerText.visible = false;
LK.gui.top.addChild(endgameTimerText);
// Helper to start the 20s countdown
function startEndgameTimer() {
if (endgameTimerActive) return;
endgameTimerActive = true;
endgameCountdown = 30;
endgameTimerText.visible = true;
endgameTimerText.setText('Time: 30');
// Show timer text on screen when countdown starts
endgameTimerText.visible = true;
endgameTimerInterval = LK.setInterval(function () {
if (gameOver) {
LK.clearInterval(endgameTimerInterval);
endgameTimerText.visible = false;
return;
}
endgameCountdown--;
endgameTimerText.setText('Time: ' + endgameCountdown);
if (endgameCountdown <= 0) {
LK.clearInterval(endgameTimerInterval);
endgameTimerText.visible = false;
gameOver = true;
LK.effects.flashScreen(0xbb2222, 900);
LK.setTimeout(function () {
LK.showGameOver();
}, 900);
infoText.setText('Time is up! You lost.');
}
}, 1000);
}
// Helper to stop the timer (on win/lose)
function stopEndgameTimer() {
if (endgameTimerInterval) {
LK.clearInterval(endgameTimerInterval);
endgameTimerInterval = null;
}
endgameTimerText.visible = false;
endgameTimerActive = false;
}
// --- Functions ---
// Generate grid with random values, bombs, and exit
function generateGrid() {
grid = [];
// Place bombs
var bombCells = [];
while (bombCells.length < bombCount) {
var bx = Math.floor(Math.random() * gridSize);
var by = Math.floor(Math.random() * gridSize);
if (bx === 0 && by === 0 || bombCells.some(function (b) {
return b.x === bx && b.y === by;
})) continue;
bombCells.push({
x: bx,
y: by
});
}
// Place exit
do {
exitPos.x = Math.floor(Math.random() * gridSize);
exitPos.y = Math.floor(Math.random() * gridSize);
} while (exitPos.x === 0 && exitPos.y === 0 || bombCells.some(function (b) {
return b.x === exitPos.x && b.y === exitPos.y;
}));
// Build grid
for (var y = 0; y < gridSize; y++) {
var row = [];
for (var x = 0; x < gridSize; x++) {
var cell = new GridCell();
cell.gridX = x;
cell.gridY = y;
cell.x = gridOffsetX + x * cellSize + cellSize / 2;
cell.y = gridOffsetY + y * cellSize + cellSize / 2;
cell.value = 1 + Math.floor(Math.random() * 6);
cell.hasBomb = bombCells.some(function (b) {
return b.x === x && b.y === y;
});
cell.isExit = x === exitPos.x && y === exitPos.y;
if (cell.isExit) {
cell.value = 6; // Exit cell always has value 6
cell.reveal(); // Always show exit cell
} else {
cell.hide();
}
game.addChild(cell);
row.push(cell);
}
grid.push(row);
}
}
// Get neighbors of (x, y)
function getNeighbors(x, y) {
var neighbors = [];
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (dx === 0 && dy === 0) continue;
var nx = x + dx;
var ny = y + dy;
if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize) {
neighbors.push(grid[ny][nx]);
}
}
}
return neighbors;
}
// Highlight possible moves for current dice value
// --- Arrow UI for multiple moves ---
var moveArrows = [];
function clearMoveArrows() {
for (var i = 0; i < moveArrows.length; i++) {
if (moveArrows[i] && moveArrows[i].parent) {
moveArrows[i].parent.removeChild(moveArrows[i]);
}
}
moveArrows = [];
}
function createArrowForCell(cell, idx) {
// Use a yellow box as arrow for now, can be replaced with a real arrow asset
var arrow = LK.getAsset('diceTap', {
width: cellSize * 0.35,
height: cellSize * 0.35,
color: 0xfad82b,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.85
});
arrow.x = cell.x;
arrow.y = cell.y;
arrow.zIndex = 1000 + idx;
arrow.down = function (x, y, obj) {
if (!canRoll && !gameOver) {
movePlayerTo(cell);
clearMoveArrows();
}
};
game.addChild(arrow);
moveArrows.push(arrow);
}
function highlightPossibleMoves(diceValue) {
possibleMoves = [];
clearMoveArrows();
var neighbors = getNeighbors(playerPos.x, playerPos.y);
for (var i = 0; i < neighbors.length; i++) {
var cell = neighbors[i];
if (!cell.isRevealed && cell.value === diceValue) {
cell.highlight();
possibleMoves.push(cell);
}
}
// If only one possible move, auto-move
if (possibleMoves.length === 1) {
// Delay slightly for UX
LK.setTimeout(function () {
if (!canRoll && !gameOver) {
movePlayerTo(possibleMoves[0]);
clearMoveArrows();
}
}, 350);
} else if (possibleMoves.length > 1) {
// Show arrows for each possible move
for (var i = 0; i < possibleMoves.length; i++) {
createArrowForCell(possibleMoves[i], i);
}
}
}
// Remove all highlights
function clearHighlights() {
for (var y = 0; y < gridSize; y++) {
for (var x = 0; x < gridSize; x++) {
grid[y][x].unhighlight();
// Always keep exit cell revealed
if (grid[y][x].isExit) {
grid[y][x].reveal();
}
}
}
clearMoveArrows();
}
// Move player to cell
function movePlayerTo(cell) {
playerPos.x = cell.gridX;
playerPos.y = cell.gridY;
moveCount++;
// --- Score logic: +20 per cell moved ---
score += 20;
// If score reaches or exceeds 100, reset to 0 and allow bomb reveal card again
if (score >= 100) {
score = 0;
cardRevealBombsUsed = false;
cardRevealBombsBtn.setText('Bombaları Göster');
cardRevealBombsBtn.alpha = 1;
infoText.setText('You earned $100! Card is available again.');
}
updateScoreBar(score);
// --- Money bundle animation: animate a money bundle from the cell to the score bar ---
(function animateMoneyBundle() {
// Create a money bundle asset (use cellBg as a green box for now)
var moneyBundle = LK.getAsset('cellBg', {
width: cellSize * 0.38,
height: cellSize * 0.24,
color: 0x22cc44,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
alpha: 1,
zIndex: 10010
});
moneyBundle.x = cell.x;
moneyBundle.y = cell.y - cellSize * 0.18;
game.addChild(moneyBundle);
// Animate directly to the score bar and disappear
var barTargetX = scoreBarBg.x + scoreBarBg.width * 0.5;
var barTargetY = scoreBarBg.y;
// Convert GUI coordinates to game coordinates for smooth animation
var guiToGameX = barTargetX;
var guiToGameY = barTargetY + 60; // visually align with bar
tween(moneyBundle, {
x: guiToGameX,
y: guiToGameY,
scaleX: 0.7,
scaleY: 0.7,
alpha: 0.0
}, {
duration: 600,
easing: tween.cubicInOut,
onComplete: function onComplete() {
if (moneyBundle.parent) moneyBundle.parent.removeChild(moneyBundle);
}
});
})();
updateScoreBar(score);
showScoreAnim(cell.x, cell.y - cellSize * 0.35, '+$20');
clearMoveArrows();
// --- Extra card use if score bar reaches 100 (only once) ---
if (!movePlayerTo._extraCardGiven && score >= 100) {
movePlayerTo._extraCardGiven = true;
cardRevealBombsUsed = false;
cardRevealBombsBtn.setText('Bombaları Göster');
cardRevealBombsBtn.alpha = 1;
infoText.setText('Tebrikler! Kartı tekrar kullanabilirsin.');
}
tween(playerToken, {
x: cell.x,
y: cell.y
}, {
duration: 220,
easing: tween.cubicOut
});
cell.reveal();
// Start endgame timer after 20th move
if (moveCount === moveLimit) {
startEndgameTimer();
}
if (cell.hasBomb) {
if (currentHearts > 1) {
// Use shield instead of dying
currentHearts = 1;
drawHeartBar();
infoText.setText('You hit a bomb! Shield used, 1 life left.');
// Animate heart bar
for (var i = 0; i < heartBar.length; i++) {
tween(heartBar[i], {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 180,
easing: tween.cubicOut,
onComplete: function (h) {
return function () {
tween(h, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.cubicIn
});
};
}(heartBar[i])
});
}
// Reveal the bomb cell, but do not end the game
cell.reveal();
LK.effects.flashScreen(0xff0000, 600);
// Remove highlights and allow next move
canRoll = true;
clearHighlights();
grid[exitPos.y][exitPos.x].reveal();
return;
}
stopEndgameTimer();
// --- Shatter animation for the bomb cell ---
var shatterPieces = [];
var pieceCount = 12 + Math.floor(Math.random() * 4);
for (var i = 0; i < pieceCount; i++) {
var angle = Math.PI * 2 * (i / pieceCount) + Math.random() * 0.2;
var dist = cellSize * (0.7 + Math.random() * 0.7);
var px = cell.x + Math.cos(angle) * (cellSize * 0.08 + Math.random() * cellSize * 0.08);
var py = cell.y + Math.sin(angle) * (cellSize * 0.08 + Math.random() * cellSize * 0.08);
var piece = LK.getAsset('cellBg', {
width: cellSize * (0.18 + Math.random() * 0.13),
height: cellSize * (0.18 + Math.random() * 0.13),
color: 0xbb2222,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.92
});
piece.x = px;
piece.y = py;
piece.zIndex = 10000 + i;
game.addChild(piece);
shatterPieces.push(piece);
// Animate each piece flying outward, rotating and fading
(function (p, a, d) {
var tx = cell.x + Math.cos(a) * d;
var ty = cell.y + Math.sin(a) * d;
var rot = (Math.random() - 0.5) * Math.PI * 1.2;
tween(p, {
x: tx,
y: ty,
rotation: rot,
alpha: 0
}, {
duration: 650 + Math.random() * 250,
easing: tween.cubicOut,
onComplete: function onComplete() {
if (p.parent) p.parent.removeChild(p);
}
});
})(piece, angle, dist);
}
// Hide the cell's background and valueText for the shatter effect
cell.bg.visible = false;
cell.valueText.visible = false;
// --- Black smoke after shatter ---
LK.setTimeout(function () {
var postSmoke = LK.getAsset('cellBg', {
width: cellSize * 1.5,
height: cellSize * 1.5,
color: 0x111111,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.55
});
postSmoke.x = cell.x;
postSmoke.y = cell.y;
postSmoke.zIndex = 9997;
game.addChild(postSmoke);
tween(postSmoke, {
scaleX: 2.8,
scaleY: 2.8,
alpha: 0
}, {
duration: 1200,
easing: tween.cubicOut,
onComplete: function onComplete() {
if (postSmoke.parent) postSmoke.parent.removeChild(postSmoke);
}
});
}, 320);
// --- Existing explosion and smoke/particle effects ---
var explosion = LK.getAsset('cellBg', {
width: cellSize * 1.1,
height: cellSize * 1.1,
color: 0xffe066,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.85
});
explosion.x = cell.x;
explosion.y = cell.y;
explosion.zIndex = 9999;
game.addChild(explosion);
// Black smoke effect (grows and fades)
var smoke = LK.getAsset('cellBg', {
width: cellSize * 1.2,
height: cellSize * 1.2,
color: 0x111111,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.45
});
smoke.x = cell.x;
smoke.y = cell.y;
smoke.zIndex = 9998;
game.addChild(smoke);
tween(smoke, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 900,
easing: tween.cubicOut,
onComplete: function onComplete() {
if (smoke.parent) smoke.parent.removeChild(smoke);
}
});
// Particle burst (black debris)
for (var i = 0; i < 16; i++) {
var angle = Math.PI * 2 * (i / 16) + Math.random() * 0.2;
var dist = cellSize * (0.7 + Math.random() * 0.7);
var px = cell.x + Math.cos(angle) * 10;
var py = cell.y + Math.sin(angle) * 10;
var particle = LK.getAsset('cellBg', {
width: 22 + Math.random() * 16,
height: 22 + Math.random() * 16,
color: 0x222222,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7 + Math.random() * 0.2
});
particle.x = px;
particle.y = py;
particle.zIndex = 9999;
game.addChild(particle);
(function (p, a, d) {
tween(p, {
x: cell.x + Math.cos(a) * d,
y: cell.y + Math.sin(a) * d,
alpha: 0,
scaleX: 0.7 + Math.random() * 0.5,
scaleY: 0.7 + Math.random() * 0.5
}, {
duration: 700 + Math.random() * 300,
easing: tween.cubicOut,
onComplete: function onComplete() {
if (p.parent) p.parent.removeChild(p);
}
});
})(particle, angle, dist);
}
// Animate: grow and fade out
tween(explosion, {
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
}, {
duration: 600,
easing: tween.cubicOut,
onComplete: function onComplete() {
if (explosion.parent) explosion.parent.removeChild(explosion);
}
});
LK.effects.flashScreen(0xff0000, 900);
gameOver = true;
LK.setTimeout(function () {
LK.showGameOver();
}, 900);
infoText.setText('Bomba! Oyun bitti.');
return;
}
if (cell.isExit) {
stopEndgameTimer();
LK.effects.flashScreen(0x44bb44, 900);
gameOver = true;
LK.setTimeout(function () {
LK.showYouWin();
}, 900);
infoText.setText('Congratulations! You reached the exit.');
return;
}
infoText.setText('Move: ' + moveCount);
canRoll = true;
clearHighlights();
// Always keep exit cell revealed
grid[exitPos.y][exitPos.x].reveal();
}
// Handle tap on a cell
function onCellDown(x, y, obj) {
if (!canRoll && !gameOver) {
// If arrows are present, only allow move via arrow tap
if (moveArrows.length > 0) return;
// Only allow move if the tapped cell is in possibleMoves (highlighted and matches dice)
for (var i = 0; i < possibleMoves.length; i++) {
if (possibleMoves[i] === obj) {
movePlayerTo(obj);
break;
}
}
}
}
// Roll the dice
function rollDice() {
if (!canRoll || gameOver) return;
canRoll = false;
// Play dice roll sound
LK.getSound('diceRoll').play();
var diceValue = 1 + Math.floor(Math.random() * 6);
dice.rollAnim(diceValue, function () {
highlightPossibleMoves(diceValue);
// Check if exit is adjacent and matches dice value
var exitIsPossible = false;
var exitCell = null;
var neighbors = getNeighbors(playerPos.x, playerPos.y);
for (var i = 0; i < neighbors.length; i++) {
if (neighbors[i].isExit) {
exitCell = neighbors[i];
if (neighbors[i].value === diceValue) {
exitIsPossible = true;
break;
}
}
}
// If exit is adjacent and dice is 6, win immediately (regardless of exit cell value)
if (exitCell && diceValue === 6) {
stopEndgameTimer();
exitCell.reveal();
LK.effects.flashScreen(0x44bb44, 900);
gameOver = true;
LK.setTimeout(function () {
LK.showYouWin();
}, 900);
infoText.setText('Rolled a 6! You reached the exit.');
return;
}
if (possibleMoves.length === 0 && !exitIsPossible) {
// No moves and exit is not possible, allow unlimited reroll
canRoll = true;
infoText.setText('No moves! You can roll the dice again.');
} else {
infoText.setText('Move: ' + moveCount + ' | Dice: ' + diceValue);
}
});
}
// --- Setup ---
// Create grid, player, dice
generateGrid();
// Reveal start cell
playerPos.x = 0;
playerPos.y = 0;
grid[0][0].reveal();
// Player token
playerToken = new PlayerToken();
playerToken.x = grid[0][0].x;
playerToken.y = grid[0][0].y;
game.addChild(playerToken);
// --- Double-tap logic for shield (second life) ---
var lastTapTime = 0;
var tapCount = 0;
var shieldUsed = false; // Only allow shield to be used once per game
playerToken.down = function (x, y, obj) {
if (gameOver) return;
var now = Date.now();
if (now - lastTapTime < 400) {
tapCount++;
} else {
tapCount = 1;
}
lastTapTime = now;
// Double-tap: activate shield (second life)
if (tapCount === 2) {
tapCount = 0;
if (shieldUsed) {
infoText.setText('Shield can only be used once per game!');
return;
}
if (currentHearts === 1) {
currentHearts = 2;
shieldUsed = true;
drawHeartBar();
infoText.setText('Shield activated! You now have 2 lives.');
// Animate hearts
for (var i = 0; i < heartBar.length; i++) {
tween(heartBar[i], {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 180,
easing: tween.cubicOut,
onComplete: function (h) {
return function () {
tween(h, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.cubicIn
});
};
}(heartBar[i])
});
}
} else {
infoText.setText('You already have 2 lives!');
}
return;
}
// Single tap: use bomb reveal card
if (cardRevealBombsUsed) return;
cardRevealBombsUsed = true;
cardRevealBombsBtn.setText('Kullanıldı');
cardRevealBombsBtn.alpha = 0.5;
showAllBombsTemporarily();
};
// Dice
dice = new Dice();
dice.x = 2048 / 2;
dice.y = gridOffsetY + cellSize * gridSize + diceSize / 2 + 60;
game.addChild(dice);
// --- Card: Reveal Bombs (single use) ---
var cardRevealBombsUsed = false;
var cardRevealBombsBtn = new Text2('💣 Bombaları Göster', {
size: 60,
fill: "#fff",
font: "bold",
padding: 18,
align: "center",
background: 0xBB2222
});
cardRevealBombsBtn.anchor.set(0.5, 0);
cardRevealBombsBtn.x = 2048 / 2;
cardRevealBombsBtn.y = 80;
cardRevealBombsBtn.interactive = true;
cardRevealBombsBtn.buttonMode = true;
LK.gui.top.addChild(cardRevealBombsBtn);
function showAllBombsTemporarily() {
// Reveal all bombs
for (var y = 0; y < gridSize; y++) {
for (var x = 0; x < gridSize; x++) {
var cell = grid[y][x];
if (cell.hasBomb && !cell.isRevealed) {
cell.reveal();
cell._wasTempRevealed = true;
}
}
}
infoText.setText('Bombs are visible for 10 seconds!');
// Reset score to 0 when bomb reveal card is used
score = 0;
updateScoreBar(score);
// Hide bombs again after 10 seconds
LK.setTimeout(function () {
for (var y = 0; y < gridSize; y++) {
for (var x = 0; x < gridSize; x++) {
var cell = grid[y][x];
if (cell._wasTempRevealed) {
cell.hide();
cell._wasTempRevealed = false;
}
}
}
infoText.setText('Card used. Move: ' + moveCount);
}, 10000);
}
cardRevealBombsBtn.down = function (x, y, obj) {
if (cardRevealBombsUsed || gameOver) return;
cardRevealBombsUsed = true;
cardRevealBombsBtn.setText('Kullanıldı');
cardRevealBombsBtn.alpha = 0.5;
showAllBombsTemporarily();
};
// Dice tap area (invisible, for touch)
var diceTapArea = LK.getAsset('diceTap', {
width: diceSize + 60,
height: diceSize + 60,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.01
});
diceTapArea.x = dice.x;
diceTapArea.y = dice.y;
game.addChild(diceTapArea);
// Info text
infoText.setText('Roll the dice to start!');
// --- Show info popup at game start ---
var infoPopupBg = LK.getAsset('cellBg', {
width: 1800,
height: 1450,
color: 0x181c22,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.98
});
infoPopupBg.x = 2048 / 2;
infoPopupBg.y = 2732 / 2;
infoPopupBg.zIndex = 99999;
var infoPopupText = new Text2("Each time you move to a new square, you earn $20 and the green score bar fills up with animation.\n" + "If the bar reaches 100, you can use the card one more time (only once per game).\n\n" + "NEW CARD: If you double-tap your character, you gain a shield (2 lives). If you step on a bomb with the shield, you don't die, but lose the shield instead!\n\n" + "• Roll the dice, move to a neighboring cell with the same number.\n" + "• Some cells have hidden bombs. Be careful!\n" + "• After 15 moves, a 30 second countdown starts. Hurry up!\n" + "• You can use the red card once to reveal all bombs for 10 seconds.\n" + "• You can also use the card by tapping your character.\n" + "• Double-tap your character to activate the shield (2 lives).\n\n" + "Tap anywhere to start!", {
size: 56,
fill: "#000",
align: "center",
font: "bold",
padding: 18,
wordWrap: true,
wordWrapWidth: 1400
});
infoPopupText.anchor.set(0.5, 0.5);
infoPopupText.x = 2048 / 2;
infoPopupText.y = 2732 / 2;
var infoPopup = new Container();
infoPopup.addChild(infoPopupBg);
infoPopup.addChild(infoPopupText);
game.addChild(infoPopup);
infoPopup.down = function (x, y, obj) {
if (infoPopup && infoPopup.parent) {
infoPopup.parent.removeChild(infoPopup);
// Restore English start text after closing info popup
infoText.setText('Roll the dice to start!');
}
};
infoPopupBg.down = infoPopup.down;
infoPopupText.down = infoPopup.down;
// --- Event Handlers ---
// Dice tap
diceTapArea.down = function (x, y, obj) {
if (canRoll && !gameOver) {
rollDice();
}
};
// Cell tap
for (var y = 0; y < gridSize; y++) {
for (var x = 0; x < gridSize; x++) {
grid[y][x].down = onCellDown;
}
}
// --- Game update (not used, but required) ---
game.update = function () {
// No per-frame logic needed
};
ıdk . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
ıdk . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
ıdk . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
red and big x. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat