/**** * 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: 0xf7f7f7 }); /**** * Game Code ****/ // Abstract geometric pattern background // 1. Large colored ellipses (randomized positions, sizes, and colors) 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 20 moves --- var moveLimit = 20; var endgameCountdown = 20; // seconds var endgameTimer = null; var endgameTimerText = null; var endgameTimerInterval = null; var endgameTimerActive = false; // --- GUI --- 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 = 20; endgameTimerText.visible = true; endgameTimerText.setText('Süre: 20'); endgameTimerInterval = LK.setInterval(function () { if (gameOver) { LK.clearInterval(endgameTimerInterval); endgameTimerText.visible = false; return; } endgameCountdown--; endgameTimerText.setText('Süre: ' + 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('Süre bitti! Kaybettin.'); } }, 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++; clearMoveArrows(); 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) { 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); // Allow using the card by tapping the player token playerToken.down = function (x, y, obj) { if (cardRevealBombsUsed || gameOver) 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!'); // 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: 1500, height: 1200, 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("Escape the Adventure by Rolling the Dice!\n\n" + "• Roll the dice and move to a neighboring cell with the same number.\n" + "• Each cell has a number. You can only move to a cell if its number matches your dice.\n" + "• Beware: Some cells hide secret bombs!\n" + "• To escape, reach a cell next to the exit and roll a 6 to leave instantly!\n" + "• After 20 moves, a countdown timer starts. Hurry up!\n" + "• Use the red card once to reveal all bombs for 10 seconds.\n" + "• You can also use the red card by tapping your character!\n\n" + "Tap anywhere to start!", { size: 70, fill: "#fff", align: "center", font: "bold", padding: 30, wordWrap: true, wordWrapWidth: 1300 }); 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: 0xf7f7f7
});
/****
* Game Code
****/
// Abstract geometric pattern background
// 1. Large colored ellipses (randomized positions, sizes, and colors)
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 20 moves ---
var moveLimit = 20;
var endgameCountdown = 20; // seconds
var endgameTimer = null;
var endgameTimerText = null;
var endgameTimerInterval = null;
var endgameTimerActive = false;
// --- GUI ---
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 = 20;
endgameTimerText.visible = true;
endgameTimerText.setText('Süre: 20');
endgameTimerInterval = LK.setInterval(function () {
if (gameOver) {
LK.clearInterval(endgameTimerInterval);
endgameTimerText.visible = false;
return;
}
endgameCountdown--;
endgameTimerText.setText('Süre: ' + 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('Süre bitti! Kaybettin.');
}
}, 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++;
clearMoveArrows();
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) {
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);
// Allow using the card by tapping the player token
playerToken.down = function (x, y, obj) {
if (cardRevealBombsUsed || gameOver) 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!');
// 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: 1500,
height: 1200,
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("Escape the Adventure by Rolling the Dice!\n\n" + "• Roll the dice and move to a neighboring cell with the same number.\n" + "• Each cell has a number. You can only move to a cell if its number matches your dice.\n" + "• Beware: Some cells hide secret bombs!\n" + "• To escape, reach a cell next to the exit and roll a 6 to leave instantly!\n" + "• After 20 moves, a countdown timer starts. Hurry up!\n" + "• Use the red card once to reveal all bombs for 10 seconds.\n" + "• You can also use the red card by tapping your character!\n\n" + "Tap anywhere to start!", {
size: 70,
fill: "#fff",
align: "center",
font: "bold",
padding: 30,
wordWrap: true,
wordWrapWidth: 1300
});
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