/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var GasTank = Container.expand(function () { var self = Container.call(this); var tankGraphics = self.attachAsset('gasTank', { anchorX: 0.5, anchorY: 0.5 }); self.gridX = 0; self.gridY = 0; self.collected = false; self.collect = function () { if (!self.collected) { self.collected = true; tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, onFinish: function onFinish() { self.visible = false; } }); LK.getSound('collect').play(); return true; } return false; }; self.setPosition = function (x, y) { self.gridX = x; self.gridY = y; self.x = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2; self.y = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2; }; return self; }); var GridCell = Container.expand(function () { var self = Container.call(this); var cellGraphics = self.attachAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); self.gridX = 0; self.gridY = 0; self.isEmpty = true; self.highlight = function (intensity) { tween(cellGraphics, { alpha: intensity }, { duration: 200 }); }; self.resetHighlight = function () { tween(cellGraphics, { alpha: 0.3 }, { duration: 200 }); }; return self; }); var HidingSpot = Container.expand(function () { var self = Container.call(this); var spotGraphics = self.attachAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, alpha: 0.1, tint: 0x0000FF }); self.gridX = 0; self.gridY = 0; self.highlight = function () { tween(spotGraphics, { alpha: 0.5, tint: 0x00AAFF }, { duration: 200 }); }; self.resetHighlight = function () { tween(spotGraphics, { alpha: 0.1, tint: 0x0000FF }, { duration: 200 }); }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.gridX = 0; self.gridY = 0; self.moveTo = function (x, y) { self.gridX = x; self.gridY = y; // Calculate actual screen position based on grid var targetX = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2; var targetY = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2; tween(self, { x: targetX, y: targetY }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { LK.getSound('move').play(); } }); }; return self; }); var Shark = Container.expand(function () { var self = Container.call(this); var sharkGraphics = self.attachAsset('shark', { anchorX: 0.5, anchorY: 0.5 }); self.gridX = 9; self.gridY = 9; self.moveTo = function (x, y) { self.gridX = x; self.gridY = y; // Calculate actual screen position based on grid var targetX = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2; var targetY = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2; tween(self, { x: targetX, y: targetY }, { duration: 300, easing: tween.bounceOut }); }; return self; }); var Shark2 = Container.expand(function () { var self = Container.call(this); var sharkGraphics = self.attachAsset('shark', { anchorX: 0.5, anchorY: 0.5, tint: 0x0000FF // Blue tint to distinguish it }); self.gridX = 0; self.gridY = 9; self.moveTo = function (x, y) { self.gridX = x; self.gridY = y; // Calculate actual screen position based on grid var targetX = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2; var targetY = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2; tween(self, { x: targetX, y: targetY }, { duration: 300, easing: tween.bounceOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Constants var GRID_SIZE = 10; var CELL_SIZE = 204; // 2048 / 10 ~= 204 var GRID_OFFSET_X = (2048 - GRID_SIZE * CELL_SIZE) / 2; var GRID_OFFSET_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2; var TOTAL_GAS_TANKS = 10; // Game state variables var grid = []; var gridContainer = new Container(); var player; var shark; var shark2; var gasTanks = []; var collectedTanks = 0; var gameActive = true; var turnCount = 0; var playerMoved = false; var sharkHidden = false; var shark2Hidden = false; var sharkDisappearTurns = 0; var shark2DisappearTurns = 0; var sharkLastX = 0; var sharkLastY = 0; var shark2LastX = 0; var shark2LastY = 0; var hidingSpots = []; var playerHiding = false; var hideButtonActive = false; var currentLevel = 1; // Start at level 1 // UI elements var statusText = new Text2('Find the gas tanks!', { size: 50, fill: 0xFFFFFF }); var scoreText = new Text2('Gas Tanks: 0/' + TOTAL_GAS_TANKS, { size: 50, fill: 0xFFFFFF }); var warningText = new Text2('', { size: 60, fill: 0xFF0000 }); // Initialize grid function initGrid() { var gridBackground = LK.getAsset('gridOutline', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, width: CELL_SIZE * GRID_SIZE, height: CELL_SIZE * GRID_SIZE, alpha: 0.2 }); game.addChild(gridBackground); game.addChild(gridContainer); for (var y = 0; y < GRID_SIZE; y++) { grid[y] = []; for (var x = 0; x < GRID_SIZE; x++) { var cell = new GridCell(); cell.x = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2; cell.y = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2; cell.gridX = x; cell.gridY = y; gridContainer.addChild(cell); grid[y][x] = cell; // Cell clicks will be handled by game.down cell.down = function (x, y, obj) { // Let the game handle this via global click detection }; } } } // Initialize player function initPlayer() { player = new Player(); player.gridX = 0; player.gridY = 0; player.x = GRID_OFFSET_X + player.gridX * CELL_SIZE + CELL_SIZE / 2; player.y = GRID_OFFSET_Y + player.gridY * CELL_SIZE + CELL_SIZE / 2; // Add click handler for player player.down = function (x, y, obj) { // Just a visual indication that player was clicked tween(player, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(player, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); }; game.addChild(player); } // Initialize shark function initShark() { shark = new Shark(); shark.gridX = 9; shark.gridY = 9; shark.x = GRID_OFFSET_X + shark.gridX * CELL_SIZE + CELL_SIZE / 2; shark.y = GRID_OFFSET_Y + shark.gridY * CELL_SIZE + CELL_SIZE / 2; game.addChild(shark); // Add second shark for level 3 if (currentLevel === 3) { shark2 = new Shark2(); shark2.gridX = 0; shark2.gridY = 9; shark2.x = GRID_OFFSET_X + shark2.gridX * CELL_SIZE + CELL_SIZE / 2; shark2.y = GRID_OFFSET_Y + shark2.gridY * CELL_SIZE + CELL_SIZE / 2; game.addChild(shark2); } } // Initialize gas tanks function initGasTanks() { // Create a list of all possible positions var positions = []; for (var y = 0; y < GRID_SIZE; y++) { for (var x = 0; x < GRID_SIZE; x++) { // Avoid player and shark starting positions if (x === 0 && y === 0 || x === 9 && y === 9) { continue; } positions.push({ x: x, y: y }); } } // Shuffle the positions for (var i = positions.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = positions[i]; positions[i] = positions[j]; positions[j] = temp; } // Place gas tanks for (var i = 0; i < TOTAL_GAS_TANKS; i++) { var pos = positions[i]; var gasTank = new GasTank(); gasTank.setPosition(pos.x, pos.y); gasTanks.push(gasTank); game.addChild(gasTank); } } // Initialize UI function initUI() { statusText.anchor.set(0.5, 0); statusText.y = 50; statusText.x = 2048 / 2; LK.gui.top.addChild(statusText); scoreText.anchor.set(0, 0); scoreText.y = 50; scoreText.x = 50; LK.gui.topRight.addChild(scoreText); warningText.anchor.set(0.5, 1); warningText.y = -50; LK.gui.bottom.addChild(warningText); // Hide button removed } // Handle cell clicks for player movement function handleCellClick(x, y) { if (!gameActive || playerMoved) return; // Check if the clicked cell is adjacent to the player var dx = Math.abs(x - player.gridX); var dy = Math.abs(y - player.gridY); if (dx === 1 && dy === 0 || dx === 0 && dy === 1) { movePlayer(x, y); playerMoved = true; // Schedule shark movement after player moves LK.setTimeout(function () { if (gameActive) { moveShark(); checkCollisions(); playerMoved = false; } }, 500); } } // Move player to new position function movePlayer(x, y) { player.moveTo(x, y); // Check if player collected a gas tank for (var i = 0; i < gasTanks.length; i++) { var tank = gasTanks[i]; if (!tank.collected && tank.gridX === x && tank.gridY === y) { if (tank.collect()) { collectedTanks++; updateScore(); if (collectedTanks >= TOTAL_GAS_TANKS) { gameWon(); } } } } turnCount++; } // Move shark towards player function moveShark() { // Handle shark disappearance every 7 turns if (turnCount % 7 === 0 && turnCount > 0 && !sharkHidden) { sharkHidden = true; sharkDisappearTurns = currentLevel === 1 ? 3 : 2; // Level 1: 3 turns, Level 2/3: 2 turns sharkLastX = shark.gridX; sharkLastY = shark.gridY; shark.alpha = 0; statusText.setText("The shark disappeared!"); warningText.setText(""); return; } // Handle shark hidden state if (sharkHidden) { sharkDisappearTurns--; if (sharkDisappearTurns <= 0) { // Shark reappears sharkHidden = false; shark.alpha = 1; shark.moveTo(sharkLastX, sharkLastY); statusText.setText("The shark reappeared!"); LK.effects.flashScreen(0xFF0000, 300); // Update warning based on distance updateWarning(); return; } statusText.setText("Shark reappears in " + sharkDisappearTurns + " turns"); return; } // Handle second shark in level 3 if (currentLevel === 3 && shark2) { // Handle shark2 disappearance every 5 turns (different pattern than first shark) if (turnCount % 5 === 0 && turnCount > 0 && !shark2Hidden) { shark2Hidden = true; shark2DisappearTurns = 1; // Always 1 turn for second shark shark2LastX = shark2.gridX; shark2LastY = shark2.gridY; shark2.alpha = 0; // Don't overwrite main shark messages if (!sharkHidden) { statusText.setText("The blue shark disappeared!"); } } // Handle shark2 hidden state if (shark2Hidden) { shark2DisappearTurns--; if (shark2DisappearTurns <= 0) { // Shark2 reappears shark2Hidden = false; shark2.alpha = 1; shark2.moveTo(shark2LastX, shark2LastY); if (!sharkHidden) { statusText.setText("The blue shark reappeared!"); LK.effects.flashScreen(0x0000FF, 300); } } } // Move shark2 if it's visible if (!shark2Hidden) { if (playerHiding) { // Random movement for shark2 when player is hiding var directions = [{ x: 1, y: 0 }, { x: -1, y: 0 }, { x: 0, y: 1 }, { x: 0, y: -1 }]; var randomDir = directions[Math.floor(Math.random() * directions.length)]; var newX = shark2.gridX + randomDir.x; var newY = shark2.gridY + randomDir.y; // Make sure we don't go out of bounds newX = Math.max(0, Math.min(GRID_SIZE - 1, newX)); newY = Math.max(0, Math.min(GRID_SIZE - 1, newY)); shark2.moveTo(newX, newY); } else { // Shark2 uses a different strategy - move diagonally when possible var dx = player.gridX - shark2.gridX; var dy = player.gridY - shark2.gridY; var newX = shark2.gridX; var newY = shark2.gridY; // Try to move diagonally when possible if (dx !== 0 && dy !== 0) { newX = shark2.gridX + (dx > 0 ? 1 : -1); newY = shark2.gridY + (dy > 0 ? 1 : -1); } else if (dx !== 0) { newX = shark2.gridX + (dx > 0 ? 1 : -1); } else if (dy !== 0) { newY = shark2.gridY + (dy > 0 ? 1 : -1); } // Make sure we don't go out of bounds newX = Math.max(0, Math.min(GRID_SIZE - 1, newX)); newY = Math.max(0, Math.min(GRID_SIZE - 1, newY)); shark2.moveTo(newX, newY); } } } // If player is hiding, move randomly if (playerHiding) { // Random movement var directions = [{ x: 1, y: 0 }, { x: -1, y: 0 }, { x: 0, y: 1 }, { x: 0, y: -1 }]; var randomDir = directions[Math.floor(Math.random() * directions.length)]; var newX = shark.gridX + randomDir.x; var newY = shark.gridY + randomDir.y; // Make sure we don't go out of bounds newX = Math.max(0, Math.min(GRID_SIZE - 1, newX)); newY = Math.max(0, Math.min(GRID_SIZE - 1, newY)); shark.moveTo(newX, newY); updateWarning(); return; } // Normal shark movement // Simple pathfinding - move toward player var dx = player.gridX - shark.gridX; var dy = player.gridY - shark.gridY; var newX = shark.gridX; var newY = shark.gridY; // First try to move horizontally or vertically if (Math.abs(dx) > Math.abs(dy)) { newX = shark.gridX + (dx > 0 ? 1 : -1); } else { newY = shark.gridY + (dy > 0 ? 1 : -1); } // Make sure we don't go out of bounds newX = Math.max(0, Math.min(GRID_SIZE - 1, newX)); newY = Math.max(0, Math.min(GRID_SIZE - 1, newY)); shark.moveTo(newX, newY); // Update warning based on distance updateWarning(); } // Update warning message based on distance to shark function updateWarning() { // Don't show warnings if both sharks are hidden in level 3 if (sharkHidden && (currentLevel < 3 || shark2Hidden)) { warningText.setText(""); return; } var distance = Math.abs(player.gridX - shark.gridX) + Math.abs(player.gridY - shark.gridY); // For level 3, check distance to second shark if it exists and is visible var distance2 = Infinity; if (currentLevel === 3 && shark2 && !shark2Hidden) { distance2 = Math.abs(player.gridX - shark2.gridX) + Math.abs(player.gridY - shark2.gridY); // Use the shorter distance for warning distance = Math.min(distance, distance2); // If the closer shark is the blue one, change the warning message if (distance2 < distance) { if (distance <= 1) { warningText.setText("BLUE SHARK RIGHT NEXT TO YOU!"); if (warningText.style) warningText.style.fill = "#0000FF"; LK.getSound('warning').play(); LK.effects.flashScreen(0x0000FF, 300); return; } } } if (distance <= 1) { warningText.setText("IT'S RIGHT NEXT TO YOU!"); if (warningText.style) warningText.style.fill = "#FF0000"; LK.getSound('warning').play(); LK.effects.flashScreen(0xFF0000, 300); } else if (distance <= 3) { warningText.setText("You can hear it breathing..."); if (warningText.style) warningText.style.fill = "#FF3300"; LK.getSound('warning').play(); } else if (distance <= 5) { warningText.setText("It's getting closer..."); if (warningText.style) warningText.style.fill = "#FF6600"; } else if (distance <= 8) { warningText.setText("Something is hunting you"); if (warningText.style) warningText.style.fill = "#FFCC00"; } else { warningText.setText(""); } } // Check if shark caught player function checkCollisions() { if (!sharkHidden && !playerHiding && shark.gridX === player.gridX && shark.gridY === player.gridY) { gameOver(); return; } // Check if shark2 caught player in level 3 if (currentLevel === 3 && shark2 && !shark2Hidden && !playerHiding && shark2.gridX === player.gridX && shark2.gridY === player.gridY) { statusText.setText("THE BLUE SHARK GOT YOU!"); gameOver(); } } // Update score display function updateScore() { scoreText.setText("Gas Tanks: " + collectedTanks + "/" + TOTAL_GAS_TANKS); } // Game over function gameOver() { gameActive = false; statusText.setText("THE SHARK GOT YOU!"); if (statusText.style) statusText.style.fill = "#FF0000"; LK.effects.flashScreen(0xFF0000, 1000); LK.setTimeout(function () { LK.showGameOver(); }, 1500); } // Game won function gameWon() { if (currentLevel === 1) { // Advance to next level instead of showing win currentLevel = 2; statusText.setText("LEVEL COMPLETE! Starting Level 2..."); if (statusText.style) statusText.style.fill = "#00FF00"; LK.effects.flashScreen(0x00FF00, 1000); LK.setTimeout(function () { resetForLevel2(); }, 1500); } else if (currentLevel === 2) { // Advance to level 3 currentLevel = 3; statusText.setText("LEVEL COMPLETE! Starting Level 3..."); if (statusText.style) statusText.style.fill = "#00FF00"; LK.effects.flashScreen(0x00FF00, 1000); LK.setTimeout(function () { resetForLevel3(); }, 1500); } else { // Final level complete gameActive = false; statusText.setText("YOU ESCAPED!"); if (statusText.style) statusText.style.fill = "#00FF00"; LK.effects.flashScreen(0x00FF00, 1000); LK.setTimeout(function () { LK.showYouWin(); }, 1500); } } // Initialize hiding spots function initHidingSpots() { // Create random hiding spots (3-5 spots) var numSpots = 3 + Math.floor(Math.random() * 3); var positions = []; // Create a list of all possible positions for (var y = 0; y < GRID_SIZE; y++) { for (var x = 0; x < GRID_SIZE; x++) { // Avoid player and shark starting positions if (x === 0 && y === 0 || x === 9 && y === 9) { continue; } positions.push({ x: x, y: y }); } } // Shuffle the positions for (var i = positions.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = positions[i]; positions[i] = positions[j]; positions[j] = temp; } // Place hiding spots for (var i = 0; i < numSpots; i++) { var pos = positions[i]; var hidingSpot = new HidingSpot(); hidingSpot.gridX = pos.x; hidingSpot.gridY = pos.y; hidingSpot.x = GRID_OFFSET_X + pos.x * CELL_SIZE + CELL_SIZE / 2; hidingSpot.y = GRID_OFFSET_Y + pos.y * CELL_SIZE + CELL_SIZE / 2; hidingSpots.push(hidingSpot); gridContainer.addChild(hidingSpot); } } // Highlight valid moves function highlightValidMoves() { // Reset all highlights for (var y = 0; y < GRID_SIZE; y++) { for (var x = 0; x < GRID_SIZE; x++) { grid[y][x].resetHighlight(); } } // Highlight hiding spots for (var i = 0; i < hidingSpots.length; i++) { var spot = hidingSpots[i]; spot.resetHighlight(); // If player is on a hiding spot, highlight it if (player.gridX === spot.gridX && player.gridY === spot.gridY) { spot.highlight(); } } // Don't highlight moves when hiding if (playerHiding) { return; } // Highlight valid moves var directions = [{ x: 1, y: 0 }, { x: -1, y: 0 }, { x: 0, y: 1 }, { x: 0, y: -1 }]; for (var i = 0; i < directions.length; i++) { var newX = player.gridX + directions[i].x; var newY = player.gridY + directions[i].y; if (newX >= 0 && newX < GRID_SIZE && newY >= 0 && newY < GRID_SIZE) { grid[newY][newX].highlight(0.5); } } } // Initialize game function initGame() { initGrid(); initPlayer(); initShark(); initGasTanks(); initHidingSpots(); initUI(); updateScore(); highlightValidMoves(); LK.playMusic('bgmusic'); } // Start the game initGame(); // Reset game state for level 2 function resetForLevel2() { // Clear existing game elements for (var i = 0; i < gasTanks.length; i++) { if (gasTanks[i].parent) { gasTanks[i].parent.removeChild(gasTanks[i]); } } for (var i = 0; i < hidingSpots.length; i++) { if (hidingSpots[i].parent) { hidingSpots[i].parent.removeChild(hidingSpots[i]); } } // Reset variables gasTanks = []; collectedTanks = 0; turnCount = 0; playerMoved = false; sharkHidden = false; sharkDisappearTurns = 0; hidingSpots = []; playerHiding = false; // Reset player and shark positions player.moveTo(0, 0); shark.moveTo(9, 9); shark.alpha = 1; // Initialize level 2 elements initGasTanks(); initHidingSpots(); // Update UI statusText.setText("LEVEL 2: The shark only disappears for 2 turns now!"); if (statusText.style) statusText.style.fill = "#FFFFFF"; updateScore(); highlightValidMoves(); // Re-enable gameplay gameActive = true; } // Reset game state for level 3 function resetForLevel3() { // Clear existing game elements for (var i = 0; i < gasTanks.length; i++) { if (gasTanks[i].parent) { gasTanks[i].parent.removeChild(gasTanks[i]); } } for (var i = 0; i < hidingSpots.length; i++) { if (hidingSpots[i].parent) { hidingSpots[i].parent.removeChild(hidingSpots[i]); } } // Reset variables gasTanks = []; collectedTanks = 0; turnCount = 0; playerMoved = false; sharkHidden = false; shark2Hidden = false; sharkDisappearTurns = 0; shark2DisappearTurns = 0; hidingSpots = []; playerHiding = false; // Reset player and shark positions player.moveTo(0, 0); shark.moveTo(9, 9); shark.alpha = 1; // Initialize level 3 elements initGasTanks(); initHidingSpots(); initShark(); // This will create the second shark // Update UI statusText.setText("LEVEL 3: Now there are TWO sharks hunting you!"); if (statusText.style) statusText.style.fill = "#FFFFFF"; updateScore(); highlightValidMoves(); // Re-enable gameplay gameActive = true; } // Game update loop game.update = function () { // Highlight valid moves when player is able to move if (gameActive && !playerMoved) { highlightValidMoves(); } }; // Game event handlers game.down = function (x, y, obj) { if (!gameActive || playerMoved || playerHiding) return; // Convert click coordinates to grid coordinates var gridX = Math.floor((x - GRID_OFFSET_X) / CELL_SIZE); var gridY = Math.floor((y - GRID_OFFSET_Y) / CELL_SIZE); // Check if click is within grid boundaries if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) { // Check if the clicked cell is adjacent to the player var dx = Math.abs(gridX - player.gridX); var dy = Math.abs(gridY - player.gridY); if (dx === 1 && dy === 0 || dx === 0 && dy === 1) { // Highlight the clicked cell briefly grid[gridY][gridX].highlight(0.7); // Move player to the clicked cell movePlayer(gridX, gridY); playerMoved = true; // Schedule shark movement after player moves LK.setTimeout(function () { if (gameActive) { moveShark(); checkCollisions(); playerMoved = false; highlightValidMoves(); } }, 500); } } }; game.move = function (x, y, obj) { // For debugging purposes // console.log("Mouse position: " + x + ", " + y); }; game.up = function (x, y, obj) { // No additional handling needed };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var GasTank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('gasTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 0;
self.gridY = 0;
self.collected = false;
self.collect = function () {
if (!self.collected) {
self.collected = true;
tween(self, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
LK.getSound('collect').play();
return true;
}
return false;
};
self.setPosition = function (x, y) {
self.gridX = x;
self.gridY = y;
self.x = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2;
};
return self;
});
var GridCell = Container.expand(function () {
var self = Container.call(this);
var cellGraphics = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.gridX = 0;
self.gridY = 0;
self.isEmpty = true;
self.highlight = function (intensity) {
tween(cellGraphics, {
alpha: intensity
}, {
duration: 200
});
};
self.resetHighlight = function () {
tween(cellGraphics, {
alpha: 0.3
}, {
duration: 200
});
};
return self;
});
var HidingSpot = Container.expand(function () {
var self = Container.call(this);
var spotGraphics = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1,
tint: 0x0000FF
});
self.gridX = 0;
self.gridY = 0;
self.highlight = function () {
tween(spotGraphics, {
alpha: 0.5,
tint: 0x00AAFF
}, {
duration: 200
});
};
self.resetHighlight = function () {
tween(spotGraphics, {
alpha: 0.1,
tint: 0x0000FF
}, {
duration: 200
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 0;
self.gridY = 0;
self.moveTo = function (x, y) {
self.gridX = x;
self.gridY = y;
// Calculate actual screen position based on grid
var targetX = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2;
var targetY = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.getSound('move').play();
}
});
};
return self;
});
var Shark = Container.expand(function () {
var self = Container.call(this);
var sharkGraphics = self.attachAsset('shark', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 9;
self.gridY = 9;
self.moveTo = function (x, y) {
self.gridX = x;
self.gridY = y;
// Calculate actual screen position based on grid
var targetX = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2;
var targetY = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.bounceOut
});
};
return self;
});
var Shark2 = Container.expand(function () {
var self = Container.call(this);
var sharkGraphics = self.attachAsset('shark', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x0000FF // Blue tint to distinguish it
});
self.gridX = 0;
self.gridY = 9;
self.moveTo = function (x, y) {
self.gridX = x;
self.gridY = y;
// Calculate actual screen position based on grid
var targetX = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2;
var targetY = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.bounceOut
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Constants
var GRID_SIZE = 10;
var CELL_SIZE = 204; // 2048 / 10 ~= 204
var GRID_OFFSET_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_OFFSET_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2;
var TOTAL_GAS_TANKS = 10;
// Game state variables
var grid = [];
var gridContainer = new Container();
var player;
var shark;
var shark2;
var gasTanks = [];
var collectedTanks = 0;
var gameActive = true;
var turnCount = 0;
var playerMoved = false;
var sharkHidden = false;
var shark2Hidden = false;
var sharkDisappearTurns = 0;
var shark2DisappearTurns = 0;
var sharkLastX = 0;
var sharkLastY = 0;
var shark2LastX = 0;
var shark2LastY = 0;
var hidingSpots = [];
var playerHiding = false;
var hideButtonActive = false;
var currentLevel = 1; // Start at level 1
// UI elements
var statusText = new Text2('Find the gas tanks!', {
size: 50,
fill: 0xFFFFFF
});
var scoreText = new Text2('Gas Tanks: 0/' + TOTAL_GAS_TANKS, {
size: 50,
fill: 0xFFFFFF
});
var warningText = new Text2('', {
size: 60,
fill: 0xFF0000
});
// Initialize grid
function initGrid() {
var gridBackground = LK.getAsset('gridOutline', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: CELL_SIZE * GRID_SIZE,
height: CELL_SIZE * GRID_SIZE,
alpha: 0.2
});
game.addChild(gridBackground);
game.addChild(gridContainer);
for (var y = 0; y < GRID_SIZE; y++) {
grid[y] = [];
for (var x = 0; x < GRID_SIZE; x++) {
var cell = new GridCell();
cell.x = GRID_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2;
cell.y = GRID_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2;
cell.gridX = x;
cell.gridY = y;
gridContainer.addChild(cell);
grid[y][x] = cell;
// Cell clicks will be handled by game.down
cell.down = function (x, y, obj) {
// Let the game handle this via global click detection
};
}
}
}
// Initialize player
function initPlayer() {
player = new Player();
player.gridX = 0;
player.gridY = 0;
player.x = GRID_OFFSET_X + player.gridX * CELL_SIZE + CELL_SIZE / 2;
player.y = GRID_OFFSET_Y + player.gridY * CELL_SIZE + CELL_SIZE / 2;
// Add click handler for player
player.down = function (x, y, obj) {
// Just a visual indication that player was clicked
tween(player, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(player, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
};
game.addChild(player);
}
// Initialize shark
function initShark() {
shark = new Shark();
shark.gridX = 9;
shark.gridY = 9;
shark.x = GRID_OFFSET_X + shark.gridX * CELL_SIZE + CELL_SIZE / 2;
shark.y = GRID_OFFSET_Y + shark.gridY * CELL_SIZE + CELL_SIZE / 2;
game.addChild(shark);
// Add second shark for level 3
if (currentLevel === 3) {
shark2 = new Shark2();
shark2.gridX = 0;
shark2.gridY = 9;
shark2.x = GRID_OFFSET_X + shark2.gridX * CELL_SIZE + CELL_SIZE / 2;
shark2.y = GRID_OFFSET_Y + shark2.gridY * CELL_SIZE + CELL_SIZE / 2;
game.addChild(shark2);
}
}
// Initialize gas tanks
function initGasTanks() {
// Create a list of all possible positions
var positions = [];
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE; x++) {
// Avoid player and shark starting positions
if (x === 0 && y === 0 || x === 9 && y === 9) {
continue;
}
positions.push({
x: x,
y: y
});
}
}
// Shuffle the positions
for (var i = positions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = positions[i];
positions[i] = positions[j];
positions[j] = temp;
}
// Place gas tanks
for (var i = 0; i < TOTAL_GAS_TANKS; i++) {
var pos = positions[i];
var gasTank = new GasTank();
gasTank.setPosition(pos.x, pos.y);
gasTanks.push(gasTank);
game.addChild(gasTank);
}
}
// Initialize UI
function initUI() {
statusText.anchor.set(0.5, 0);
statusText.y = 50;
statusText.x = 2048 / 2;
LK.gui.top.addChild(statusText);
scoreText.anchor.set(0, 0);
scoreText.y = 50;
scoreText.x = 50;
LK.gui.topRight.addChild(scoreText);
warningText.anchor.set(0.5, 1);
warningText.y = -50;
LK.gui.bottom.addChild(warningText);
// Hide button removed
}
// Handle cell clicks for player movement
function handleCellClick(x, y) {
if (!gameActive || playerMoved) return;
// Check if the clicked cell is adjacent to the player
var dx = Math.abs(x - player.gridX);
var dy = Math.abs(y - player.gridY);
if (dx === 1 && dy === 0 || dx === 0 && dy === 1) {
movePlayer(x, y);
playerMoved = true;
// Schedule shark movement after player moves
LK.setTimeout(function () {
if (gameActive) {
moveShark();
checkCollisions();
playerMoved = false;
}
}, 500);
}
}
// Move player to new position
function movePlayer(x, y) {
player.moveTo(x, y);
// Check if player collected a gas tank
for (var i = 0; i < gasTanks.length; i++) {
var tank = gasTanks[i];
if (!tank.collected && tank.gridX === x && tank.gridY === y) {
if (tank.collect()) {
collectedTanks++;
updateScore();
if (collectedTanks >= TOTAL_GAS_TANKS) {
gameWon();
}
}
}
}
turnCount++;
}
// Move shark towards player
function moveShark() {
// Handle shark disappearance every 7 turns
if (turnCount % 7 === 0 && turnCount > 0 && !sharkHidden) {
sharkHidden = true;
sharkDisappearTurns = currentLevel === 1 ? 3 : 2; // Level 1: 3 turns, Level 2/3: 2 turns
sharkLastX = shark.gridX;
sharkLastY = shark.gridY;
shark.alpha = 0;
statusText.setText("The shark disappeared!");
warningText.setText("");
return;
}
// Handle shark hidden state
if (sharkHidden) {
sharkDisappearTurns--;
if (sharkDisappearTurns <= 0) {
// Shark reappears
sharkHidden = false;
shark.alpha = 1;
shark.moveTo(sharkLastX, sharkLastY);
statusText.setText("The shark reappeared!");
LK.effects.flashScreen(0xFF0000, 300);
// Update warning based on distance
updateWarning();
return;
}
statusText.setText("Shark reappears in " + sharkDisappearTurns + " turns");
return;
}
// Handle second shark in level 3
if (currentLevel === 3 && shark2) {
// Handle shark2 disappearance every 5 turns (different pattern than first shark)
if (turnCount % 5 === 0 && turnCount > 0 && !shark2Hidden) {
shark2Hidden = true;
shark2DisappearTurns = 1; // Always 1 turn for second shark
shark2LastX = shark2.gridX;
shark2LastY = shark2.gridY;
shark2.alpha = 0;
// Don't overwrite main shark messages
if (!sharkHidden) {
statusText.setText("The blue shark disappeared!");
}
}
// Handle shark2 hidden state
if (shark2Hidden) {
shark2DisappearTurns--;
if (shark2DisappearTurns <= 0) {
// Shark2 reappears
shark2Hidden = false;
shark2.alpha = 1;
shark2.moveTo(shark2LastX, shark2LastY);
if (!sharkHidden) {
statusText.setText("The blue shark reappeared!");
LK.effects.flashScreen(0x0000FF, 300);
}
}
}
// Move shark2 if it's visible
if (!shark2Hidden) {
if (playerHiding) {
// Random movement for shark2 when player is hiding
var directions = [{
x: 1,
y: 0
}, {
x: -1,
y: 0
}, {
x: 0,
y: 1
}, {
x: 0,
y: -1
}];
var randomDir = directions[Math.floor(Math.random() * directions.length)];
var newX = shark2.gridX + randomDir.x;
var newY = shark2.gridY + randomDir.y;
// Make sure we don't go out of bounds
newX = Math.max(0, Math.min(GRID_SIZE - 1, newX));
newY = Math.max(0, Math.min(GRID_SIZE - 1, newY));
shark2.moveTo(newX, newY);
} else {
// Shark2 uses a different strategy - move diagonally when possible
var dx = player.gridX - shark2.gridX;
var dy = player.gridY - shark2.gridY;
var newX = shark2.gridX;
var newY = shark2.gridY;
// Try to move diagonally when possible
if (dx !== 0 && dy !== 0) {
newX = shark2.gridX + (dx > 0 ? 1 : -1);
newY = shark2.gridY + (dy > 0 ? 1 : -1);
} else if (dx !== 0) {
newX = shark2.gridX + (dx > 0 ? 1 : -1);
} else if (dy !== 0) {
newY = shark2.gridY + (dy > 0 ? 1 : -1);
}
// Make sure we don't go out of bounds
newX = Math.max(0, Math.min(GRID_SIZE - 1, newX));
newY = Math.max(0, Math.min(GRID_SIZE - 1, newY));
shark2.moveTo(newX, newY);
}
}
}
// If player is hiding, move randomly
if (playerHiding) {
// Random movement
var directions = [{
x: 1,
y: 0
}, {
x: -1,
y: 0
}, {
x: 0,
y: 1
}, {
x: 0,
y: -1
}];
var randomDir = directions[Math.floor(Math.random() * directions.length)];
var newX = shark.gridX + randomDir.x;
var newY = shark.gridY + randomDir.y;
// Make sure we don't go out of bounds
newX = Math.max(0, Math.min(GRID_SIZE - 1, newX));
newY = Math.max(0, Math.min(GRID_SIZE - 1, newY));
shark.moveTo(newX, newY);
updateWarning();
return;
}
// Normal shark movement
// Simple pathfinding - move toward player
var dx = player.gridX - shark.gridX;
var dy = player.gridY - shark.gridY;
var newX = shark.gridX;
var newY = shark.gridY;
// First try to move horizontally or vertically
if (Math.abs(dx) > Math.abs(dy)) {
newX = shark.gridX + (dx > 0 ? 1 : -1);
} else {
newY = shark.gridY + (dy > 0 ? 1 : -1);
}
// Make sure we don't go out of bounds
newX = Math.max(0, Math.min(GRID_SIZE - 1, newX));
newY = Math.max(0, Math.min(GRID_SIZE - 1, newY));
shark.moveTo(newX, newY);
// Update warning based on distance
updateWarning();
}
// Update warning message based on distance to shark
function updateWarning() {
// Don't show warnings if both sharks are hidden in level 3
if (sharkHidden && (currentLevel < 3 || shark2Hidden)) {
warningText.setText("");
return;
}
var distance = Math.abs(player.gridX - shark.gridX) + Math.abs(player.gridY - shark.gridY);
// For level 3, check distance to second shark if it exists and is visible
var distance2 = Infinity;
if (currentLevel === 3 && shark2 && !shark2Hidden) {
distance2 = Math.abs(player.gridX - shark2.gridX) + Math.abs(player.gridY - shark2.gridY);
// Use the shorter distance for warning
distance = Math.min(distance, distance2);
// If the closer shark is the blue one, change the warning message
if (distance2 < distance) {
if (distance <= 1) {
warningText.setText("BLUE SHARK RIGHT NEXT TO YOU!");
if (warningText.style) warningText.style.fill = "#0000FF";
LK.getSound('warning').play();
LK.effects.flashScreen(0x0000FF, 300);
return;
}
}
}
if (distance <= 1) {
warningText.setText("IT'S RIGHT NEXT TO YOU!");
if (warningText.style) warningText.style.fill = "#FF0000";
LK.getSound('warning').play();
LK.effects.flashScreen(0xFF0000, 300);
} else if (distance <= 3) {
warningText.setText("You can hear it breathing...");
if (warningText.style) warningText.style.fill = "#FF3300";
LK.getSound('warning').play();
} else if (distance <= 5) {
warningText.setText("It's getting closer...");
if (warningText.style) warningText.style.fill = "#FF6600";
} else if (distance <= 8) {
warningText.setText("Something is hunting you");
if (warningText.style) warningText.style.fill = "#FFCC00";
} else {
warningText.setText("");
}
}
// Check if shark caught player
function checkCollisions() {
if (!sharkHidden && !playerHiding && shark.gridX === player.gridX && shark.gridY === player.gridY) {
gameOver();
return;
}
// Check if shark2 caught player in level 3
if (currentLevel === 3 && shark2 && !shark2Hidden && !playerHiding && shark2.gridX === player.gridX && shark2.gridY === player.gridY) {
statusText.setText("THE BLUE SHARK GOT YOU!");
gameOver();
}
}
// Update score display
function updateScore() {
scoreText.setText("Gas Tanks: " + collectedTanks + "/" + TOTAL_GAS_TANKS);
}
// Game over
function gameOver() {
gameActive = false;
statusText.setText("THE SHARK GOT YOU!");
if (statusText.style) statusText.style.fill = "#FF0000";
LK.effects.flashScreen(0xFF0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
// Game won
function gameWon() {
if (currentLevel === 1) {
// Advance to next level instead of showing win
currentLevel = 2;
statusText.setText("LEVEL COMPLETE! Starting Level 2...");
if (statusText.style) statusText.style.fill = "#00FF00";
LK.effects.flashScreen(0x00FF00, 1000);
LK.setTimeout(function () {
resetForLevel2();
}, 1500);
} else if (currentLevel === 2) {
// Advance to level 3
currentLevel = 3;
statusText.setText("LEVEL COMPLETE! Starting Level 3...");
if (statusText.style) statusText.style.fill = "#00FF00";
LK.effects.flashScreen(0x00FF00, 1000);
LK.setTimeout(function () {
resetForLevel3();
}, 1500);
} else {
// Final level complete
gameActive = false;
statusText.setText("YOU ESCAPED!");
if (statusText.style) statusText.style.fill = "#00FF00";
LK.effects.flashScreen(0x00FF00, 1000);
LK.setTimeout(function () {
LK.showYouWin();
}, 1500);
}
}
// Initialize hiding spots
function initHidingSpots() {
// Create random hiding spots (3-5 spots)
var numSpots = 3 + Math.floor(Math.random() * 3);
var positions = [];
// Create a list of all possible positions
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE; x++) {
// Avoid player and shark starting positions
if (x === 0 && y === 0 || x === 9 && y === 9) {
continue;
}
positions.push({
x: x,
y: y
});
}
}
// Shuffle the positions
for (var i = positions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = positions[i];
positions[i] = positions[j];
positions[j] = temp;
}
// Place hiding spots
for (var i = 0; i < numSpots; i++) {
var pos = positions[i];
var hidingSpot = new HidingSpot();
hidingSpot.gridX = pos.x;
hidingSpot.gridY = pos.y;
hidingSpot.x = GRID_OFFSET_X + pos.x * CELL_SIZE + CELL_SIZE / 2;
hidingSpot.y = GRID_OFFSET_Y + pos.y * CELL_SIZE + CELL_SIZE / 2;
hidingSpots.push(hidingSpot);
gridContainer.addChild(hidingSpot);
}
}
// Highlight valid moves
function highlightValidMoves() {
// Reset all highlights
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE; x++) {
grid[y][x].resetHighlight();
}
}
// Highlight hiding spots
for (var i = 0; i < hidingSpots.length; i++) {
var spot = hidingSpots[i];
spot.resetHighlight();
// If player is on a hiding spot, highlight it
if (player.gridX === spot.gridX && player.gridY === spot.gridY) {
spot.highlight();
}
}
// Don't highlight moves when hiding
if (playerHiding) {
return;
}
// Highlight valid moves
var directions = [{
x: 1,
y: 0
}, {
x: -1,
y: 0
}, {
x: 0,
y: 1
}, {
x: 0,
y: -1
}];
for (var i = 0; i < directions.length; i++) {
var newX = player.gridX + directions[i].x;
var newY = player.gridY + directions[i].y;
if (newX >= 0 && newX < GRID_SIZE && newY >= 0 && newY < GRID_SIZE) {
grid[newY][newX].highlight(0.5);
}
}
}
// Initialize game
function initGame() {
initGrid();
initPlayer();
initShark();
initGasTanks();
initHidingSpots();
initUI();
updateScore();
highlightValidMoves();
LK.playMusic('bgmusic');
}
// Start the game
initGame();
// Reset game state for level 2
function resetForLevel2() {
// Clear existing game elements
for (var i = 0; i < gasTanks.length; i++) {
if (gasTanks[i].parent) {
gasTanks[i].parent.removeChild(gasTanks[i]);
}
}
for (var i = 0; i < hidingSpots.length; i++) {
if (hidingSpots[i].parent) {
hidingSpots[i].parent.removeChild(hidingSpots[i]);
}
}
// Reset variables
gasTanks = [];
collectedTanks = 0;
turnCount = 0;
playerMoved = false;
sharkHidden = false;
sharkDisappearTurns = 0;
hidingSpots = [];
playerHiding = false;
// Reset player and shark positions
player.moveTo(0, 0);
shark.moveTo(9, 9);
shark.alpha = 1;
// Initialize level 2 elements
initGasTanks();
initHidingSpots();
// Update UI
statusText.setText("LEVEL 2: The shark only disappears for 2 turns now!");
if (statusText.style) statusText.style.fill = "#FFFFFF";
updateScore();
highlightValidMoves();
// Re-enable gameplay
gameActive = true;
}
// Reset game state for level 3
function resetForLevel3() {
// Clear existing game elements
for (var i = 0; i < gasTanks.length; i++) {
if (gasTanks[i].parent) {
gasTanks[i].parent.removeChild(gasTanks[i]);
}
}
for (var i = 0; i < hidingSpots.length; i++) {
if (hidingSpots[i].parent) {
hidingSpots[i].parent.removeChild(hidingSpots[i]);
}
}
// Reset variables
gasTanks = [];
collectedTanks = 0;
turnCount = 0;
playerMoved = false;
sharkHidden = false;
shark2Hidden = false;
sharkDisappearTurns = 0;
shark2DisappearTurns = 0;
hidingSpots = [];
playerHiding = false;
// Reset player and shark positions
player.moveTo(0, 0);
shark.moveTo(9, 9);
shark.alpha = 1;
// Initialize level 3 elements
initGasTanks();
initHidingSpots();
initShark(); // This will create the second shark
// Update UI
statusText.setText("LEVEL 3: Now there are TWO sharks hunting you!");
if (statusText.style) statusText.style.fill = "#FFFFFF";
updateScore();
highlightValidMoves();
// Re-enable gameplay
gameActive = true;
}
// Game update loop
game.update = function () {
// Highlight valid moves when player is able to move
if (gameActive && !playerMoved) {
highlightValidMoves();
}
};
// Game event handlers
game.down = function (x, y, obj) {
if (!gameActive || playerMoved || playerHiding) return;
// Convert click coordinates to grid coordinates
var gridX = Math.floor((x - GRID_OFFSET_X) / CELL_SIZE);
var gridY = Math.floor((y - GRID_OFFSET_Y) / CELL_SIZE);
// Check if click is within grid boundaries
if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) {
// Check if the clicked cell is adjacent to the player
var dx = Math.abs(gridX - player.gridX);
var dy = Math.abs(gridY - player.gridY);
if (dx === 1 && dy === 0 || dx === 0 && dy === 1) {
// Highlight the clicked cell briefly
grid[gridY][gridX].highlight(0.7);
// Move player to the clicked cell
movePlayer(gridX, gridY);
playerMoved = true;
// Schedule shark movement after player moves
LK.setTimeout(function () {
if (gameActive) {
moveShark();
checkCollisions();
playerMoved = false;
highlightValidMoves();
}
}, 500);
}
}
};
game.move = function (x, y, obj) {
// For debugging purposes
// console.log("Mouse position: " + x + ", " + y);
};
game.up = function (x, y, obj) {
// No additional handling needed
};