/****
* 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