/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Dot = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('dot', { anchorX: 0.5, anchorY: 0.5, width: 30, height: 30 }); self.collected = false; return self; }); var Ghost = Container.expand(function (color) { var self = Container.call(this); var mazeHeight = 27; var mazeWidth = 25; var graphics = self.attachAsset('ghost', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); // Tint ghost to proper color graphics.tint = color; self.gridX = 0; self.gridY = 0; self.targetX = 0; self.targetY = 0; self.moving = false; self.speed = 4; self.vulnerable = false; self.eaten = false; self.originalColor = color; self.moveTimer = 0; self.eyesOpen = true; self.blinkTimer = 0; self.spawnGridX = 0; self.spawnGridY = 0; self.respawnTimer = 0; self.respawning = false; self.startBlinking = function () { self.blinkTimer = Math.random() * 120 + 60; // Random blink interval between 1-3 seconds }; self.blink = function () { if (self.eyesOpen) { // Close eyes - scale down vertically to simulate closing tween(graphics, { scaleY: 0.7 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { // Open eyes after brief pause LK.setTimeout(function () { tween(graphics, { scaleY: 1.0 }, { duration: 100, easing: tween.easeIn, onFinish: function onFinish() { self.eyesOpen = true; self.startBlinking(); } }); }, 150); } }); self.eyesOpen = false; } }; // Start the blinking cycle self.startBlinking(); self.makeVulnerable = function () { self.vulnerable = true; // Stop any existing tweens on the graphics tween.stop(graphics); self.removeChild(graphics); graphics = self.attachAsset('ghost', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); // Make ghost blue when vulnerable graphics.tint = 0x0000FF; // Reset blinking cycle for new graphics self.eyesOpen = true; self.startBlinking(); }; self.makeNormal = function () { self.vulnerable = false; // Stop any existing tweens on the graphics tween.stop(graphics); self.removeChild(graphics); graphics = self.attachAsset('ghost', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); // Restore original ghost color graphics.tint = self.originalColor; // Reset blinking cycle for new graphics self.eyesOpen = true; self.startBlinking(); }; self.moveToGrid = function (gx, gy) { if (self.moving) return; // Handle tunnel teleportation if (gy === 13) { // Tunnel row if (gx < 0) { gx = mazeWidth - 1; // Teleport to right side } else if (gx >= mazeWidth) { gx = 0; // Teleport to left side } } // Check boundaries and wall collision if (gy >= 0 && gy < mazeHeight && gx >= 0 && gx < mazeWidth && maze[gy] && maze[gy][gx] !== 1) { self.moving = true; self.gridX = gx; self.gridY = gy; self.targetX = offsetX + gx * cellSize + cellSize / 2; self.targetY = offsetY + gy * cellSize + cellSize / 2; } }; self.update = function () { // Handle respawn timer if (self.respawning) { self.respawnTimer--; if (self.respawnTimer <= 0) { self.respawning = false; self.eaten = false; self.makeNormal(); } return; // Don't move while respawning } if (self.moving) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.speed) { self.x = self.targetX; self.y = self.targetY; self.moving = false; } else { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } // Handle blinking if (self.eyesOpen && self.blinkTimer > 0) { self.blinkTimer--; if (self.blinkTimer <= 0) { self.blink(); } } self.moveTimer++; if (!self.moving && self.moveTimer > 15) { self.moveTimer = 0; var directions = [{ x: self.gridX - 1, y: self.gridY }, { x: self.gridX + 1, y: self.gridY }, { x: self.gridX, y: self.gridY - 1 }, { x: self.gridX, y: self.gridY + 1 }]; var validDirections = []; for (var i = 0; i < directions.length; i++) { var dir = directions[i]; var checkX = dir.x; var checkY = dir.y; // Handle tunnel teleportation for pathfinding if (checkY === 13) { // Tunnel row if (checkX < 0) { checkX = mazeWidth - 1; // Would teleport to right side } else if (checkX >= mazeWidth) { checkX = 0; // Would teleport to left side } } // Only allow movement to non-wall cells if (checkY >= 0 && checkY < mazeHeight && checkX >= 0 && checkX < mazeWidth && maze[checkY] && maze[checkY][checkX] !== 1) { validDirections.push(dir); } } if (validDirections.length > 0) { var chosenDir; if (self.vulnerable && !self.eaten && powerMode && pacman) { // Flee from Pacman when vulnerable var bestDistance = -1; for (var i = 0; i < validDirections.length; i++) { var dir = validDirections[i]; var distanceToPacman = Math.abs(dir.x - pacman.gridX) + Math.abs(dir.y - pacman.gridY); if (distanceToPacman > bestDistance) { bestDistance = distanceToPacman; chosenDir = dir; } } } else if (pacman) { // Chase Pacman when not vulnerable var bestDistance = Infinity; for (var i = 0; i < validDirections.length; i++) { var dir = validDirections[i]; var distanceToPacman = Math.abs(dir.x - pacman.gridX) + Math.abs(dir.y - pacman.gridY); if (distanceToPacman < bestDistance) { bestDistance = distanceToPacman; chosenDir = dir; } } } else { // Fallback to random movement if pacman not available chosenDir = validDirections[Math.floor(Math.random() * validDirections.length)]; } if (chosenDir) { self.moveToGrid(chosenDir.x, chosenDir.y); } } } }; return self; }); var Pacman = Container.expand(function () { var self = Container.call(this); var mazeHeight = 27; var mazeWidth = 25; var graphics = self.attachAsset('pacman', { anchorX: 0.5, anchorY: 0.5 }); self.gridX = 9; self.gridY = 19; self.targetX = 0; self.targetY = 0; self.moving = false; self.speed = 8; self.moveToGrid = function (gx, gy) { if (self.moving) return; // Handle tunnel teleportation if (gy === 13) { // Tunnel row if (gx < 0) { gx = mazeWidth - 1; // Teleport to right side } else if (gx >= mazeWidth) { gx = 0; // Teleport to left side } } // Check boundaries and wall collision if (gy >= 0 && gy < mazeHeight && gx >= 0 && gx < mazeWidth && maze[gy] && maze[gy][gx] !== 1) { self.moving = true; self.gridX = gx; self.gridY = gy; self.targetX = offsetX + gx * cellSize + cellSize / 2; self.targetY = offsetY + gy * cellSize + cellSize / 2; } }; self.update = function () { if (self.moving) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.speed) { self.x = self.targetX; self.y = self.targetY; self.moving = false; } else { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } }; return self; }); var PowerPellet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('powerPellet', { anchorX: 0.5, anchorY: 0.5, width: 50, height: 50 }); self.collected = false; self.update = function () { graphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2; graphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ var maze = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 3, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 3, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1], [1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 1], [1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1], [0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0], [1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 1], [1, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 3, 1], [1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1], [1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]; var mazeWidth = maze[0].length; var mazeHeight = maze.length; var cellSize = 60; var offsetX = (2048 - mazeWidth * cellSize) / 2; var offsetY = (2732 - mazeHeight * cellSize) / 2; var walls = []; var dots = []; var powerPellets = []; var ghosts = []; var pacman = null; var powerMode = false; var powerModeTimer = 0; var totalDots = 0; var collectedDots = 0; var powerPelletRespawnTimer = 1800; // 30 seconds at 60 FPS var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); for (var y = 0; y < mazeHeight; y++) { for (var x = 0; x < mazeWidth; x++) { var cell = maze[y][x]; var worldX = offsetX + x * cellSize + cellSize / 2; var worldY = offsetY + y * cellSize + cellSize / 2; if (cell === 1) { var wall = game.addChild(LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: worldX, y: worldY })); walls.push(wall); } else if (cell === 2) { var dot = game.addChild(new Dot()); dot.x = worldX; dot.y = worldY; dot.gridX = x; dot.gridY = y; dots.push(dot); totalDots++; } else if (cell === 3) { var powerPellet = game.addChild(new PowerPellet()); powerPellet.x = worldX; powerPellet.y = worldY; powerPellet.gridX = x; powerPellet.gridY = y; powerPellets.push(powerPellet); } } } pacman = game.addChild(new Pacman()); pacman.gridX = 12; pacman.gridY = 25; pacman.x = offsetX + pacman.gridX * cellSize + cellSize / 2; pacman.y = offsetY + pacman.gridY * cellSize + cellSize / 2; pacman.targetX = pacman.x; pacman.targetY = pacman.y; var ghostColors = [0xFF0000, 0xFFB8FF, 0x00FFFF, 0xFFB852]; var ghostStartPositions = [{ x: 11, y: 13 }, { x: 12, y: 12 }, { x: 13, y: 13 }, { x: 12, y: 14 }]; for (var i = 0; i < 4; i++) { var ghost = game.addChild(new Ghost(ghostColors[i])); ghost.gridX = ghostStartPositions[i].x; ghost.gridY = ghostStartPositions[i].y; ghost.spawnGridX = ghostStartPositions[i].x; ghost.spawnGridY = ghostStartPositions[i].y; ghost.x = offsetX + ghost.gridX * cellSize + cellSize / 2; ghost.y = offsetY + ghost.gridY * cellSize + cellSize / 2; ghost.targetX = ghost.x; ghost.targetY = ghost.y; ghosts.push(ghost); } // Player control variables var swipeStartX = 0; var swipeStartY = 0; var swipeThreshold = 50; // Touch controls for player game.down = function (x, y, obj) { swipeStartX = x; swipeStartY = y; }; game.up = function (x, y, obj) { if (pacman.moving) return; var swipeEndX = x; var swipeEndY = y; var deltaX = swipeEndX - swipeStartX; var deltaY = swipeEndY - swipeStartY; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < swipeThreshold) return; var newGridX = pacman.gridX; var newGridY = pacman.gridY; if (Math.abs(deltaX) > Math.abs(deltaY)) { if (deltaX > 0) { newGridX++; } else { newGridX--; } } else { if (deltaY > 0) { newGridY++; } else { newGridY--; } } pacman.moveToGrid(newGridX, newGridY); }; game.update = function () { if (powerMode) { powerModeTimer--; if (powerModeTimer <= 0) { powerMode = false; // Reset Pacman speed to normal pacman.speed = 8; for (var i = 0; i < ghosts.length; i++) { if (!ghosts[i].eaten) { ghosts[i].makeNormal(); } } } } for (var i = dots.length - 1; i >= 0; i--) { var dot = dots[i]; if (!dot.collected && pacman.gridX === dot.gridX && pacman.gridY === dot.gridY) { dot.collected = true; dot.visible = false; collectedDots++; LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); LK.getSound('eatDot').play(); var collectedPowerPellets = 0; for (var j = 0; j < powerPellets.length; j++) { if (powerPellets[j].collected) collectedPowerPellets++; } if (collectedDots >= totalDots && collectedPowerPellets >= powerPellets.length) { LK.showYouWin(); } } } for (var i = powerPellets.length - 1; i >= 0; i--) { var pellet = powerPellets[i]; if (!pellet.collected && pacman.gridX === pellet.gridX && pacman.gridY === pellet.gridY) { pellet.collected = true; pellet.visible = false; powerMode = true; powerModeTimer = 600; // Triple Pacman's speed during power mode pacman.speed = 24; // 8 * 3 = 24 LK.setScore(LK.getScore() + 50); scoreTxt.setText(LK.getScore()); LK.getSound('powerUp').play(); for (var j = 0; j < ghosts.length; j++) { if (!ghosts[j].eaten) { ghosts[j].makeVulnerable(); } } } } for (var i = 0; i < ghosts.length; i++) { var ghost = ghosts[i]; if (pacman.gridX === ghost.gridX && pacman.gridY === ghost.gridY) { if (powerMode && ghost.vulnerable && !ghost.eaten) { ghost.eaten = true; ghost.respawning = true; ghost.respawnTimer = 600; // 10 seconds at 60 FPS ghost.gridX = ghost.spawnGridX; ghost.gridY = ghost.spawnGridY; ghost.x = offsetX + ghost.gridX * cellSize + cellSize / 2; ghost.y = offsetY + ghost.gridY * cellSize + cellSize / 2; ghost.targetX = ghost.x; ghost.targetY = ghost.y; ghost.moving = false; LK.setScore(LK.getScore() + 200); scoreTxt.setText(LK.getScore()); LK.getSound('eatGhost').play(); } else if (!ghost.vulnerable && !ghost.eaten) { LK.showGameOver(); } } } // Handle power pellet respawning every 30 seconds powerPelletRespawnTimer--; if (powerPelletRespawnTimer <= 0) { powerPelletRespawnTimer = 1800; // Reset to 30 seconds // Respawn all collected power pellets for (var i = 0; i < powerPellets.length; i++) { var pellet = powerPellets[i]; if (pellet.collected) { pellet.collected = false; pellet.visible = true; } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Dot = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('dot', {
anchorX: 0.5,
anchorY: 0.5,
width: 30,
height: 30
});
self.collected = false;
return self;
});
var Ghost = Container.expand(function (color) {
var self = Container.call(this);
var mazeHeight = 27;
var mazeWidth = 25;
var graphics = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 80
});
// Tint ghost to proper color
graphics.tint = color;
self.gridX = 0;
self.gridY = 0;
self.targetX = 0;
self.targetY = 0;
self.moving = false;
self.speed = 4;
self.vulnerable = false;
self.eaten = false;
self.originalColor = color;
self.moveTimer = 0;
self.eyesOpen = true;
self.blinkTimer = 0;
self.spawnGridX = 0;
self.spawnGridY = 0;
self.respawnTimer = 0;
self.respawning = false;
self.startBlinking = function () {
self.blinkTimer = Math.random() * 120 + 60; // Random blink interval between 1-3 seconds
};
self.blink = function () {
if (self.eyesOpen) {
// Close eyes - scale down vertically to simulate closing
tween(graphics, {
scaleY: 0.7
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Open eyes after brief pause
LK.setTimeout(function () {
tween(graphics, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn,
onFinish: function onFinish() {
self.eyesOpen = true;
self.startBlinking();
}
});
}, 150);
}
});
self.eyesOpen = false;
}
};
// Start the blinking cycle
self.startBlinking();
self.makeVulnerable = function () {
self.vulnerable = true;
// Stop any existing tweens on the graphics
tween.stop(graphics);
self.removeChild(graphics);
graphics = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 80
});
// Make ghost blue when vulnerable
graphics.tint = 0x0000FF;
// Reset blinking cycle for new graphics
self.eyesOpen = true;
self.startBlinking();
};
self.makeNormal = function () {
self.vulnerable = false;
// Stop any existing tweens on the graphics
tween.stop(graphics);
self.removeChild(graphics);
graphics = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 80
});
// Restore original ghost color
graphics.tint = self.originalColor;
// Reset blinking cycle for new graphics
self.eyesOpen = true;
self.startBlinking();
};
self.moveToGrid = function (gx, gy) {
if (self.moving) return;
// Handle tunnel teleportation
if (gy === 13) {
// Tunnel row
if (gx < 0) {
gx = mazeWidth - 1; // Teleport to right side
} else if (gx >= mazeWidth) {
gx = 0; // Teleport to left side
}
}
// Check boundaries and wall collision
if (gy >= 0 && gy < mazeHeight && gx >= 0 && gx < mazeWidth && maze[gy] && maze[gy][gx] !== 1) {
self.moving = true;
self.gridX = gx;
self.gridY = gy;
self.targetX = offsetX + gx * cellSize + cellSize / 2;
self.targetY = offsetY + gy * cellSize + cellSize / 2;
}
};
self.update = function () {
// Handle respawn timer
if (self.respawning) {
self.respawnTimer--;
if (self.respawnTimer <= 0) {
self.respawning = false;
self.eaten = false;
self.makeNormal();
}
return; // Don't move while respawning
}
if (self.moving) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.speed) {
self.x = self.targetX;
self.y = self.targetY;
self.moving = false;
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// Handle blinking
if (self.eyesOpen && self.blinkTimer > 0) {
self.blinkTimer--;
if (self.blinkTimer <= 0) {
self.blink();
}
}
self.moveTimer++;
if (!self.moving && self.moveTimer > 15) {
self.moveTimer = 0;
var directions = [{
x: self.gridX - 1,
y: self.gridY
}, {
x: self.gridX + 1,
y: self.gridY
}, {
x: self.gridX,
y: self.gridY - 1
}, {
x: self.gridX,
y: self.gridY + 1
}];
var validDirections = [];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
var checkX = dir.x;
var checkY = dir.y;
// Handle tunnel teleportation for pathfinding
if (checkY === 13) {
// Tunnel row
if (checkX < 0) {
checkX = mazeWidth - 1; // Would teleport to right side
} else if (checkX >= mazeWidth) {
checkX = 0; // Would teleport to left side
}
}
// Only allow movement to non-wall cells
if (checkY >= 0 && checkY < mazeHeight && checkX >= 0 && checkX < mazeWidth && maze[checkY] && maze[checkY][checkX] !== 1) {
validDirections.push(dir);
}
}
if (validDirections.length > 0) {
var chosenDir;
if (self.vulnerable && !self.eaten && powerMode && pacman) {
// Flee from Pacman when vulnerable
var bestDistance = -1;
for (var i = 0; i < validDirections.length; i++) {
var dir = validDirections[i];
var distanceToPacman = Math.abs(dir.x - pacman.gridX) + Math.abs(dir.y - pacman.gridY);
if (distanceToPacman > bestDistance) {
bestDistance = distanceToPacman;
chosenDir = dir;
}
}
} else if (pacman) {
// Chase Pacman when not vulnerable
var bestDistance = Infinity;
for (var i = 0; i < validDirections.length; i++) {
var dir = validDirections[i];
var distanceToPacman = Math.abs(dir.x - pacman.gridX) + Math.abs(dir.y - pacman.gridY);
if (distanceToPacman < bestDistance) {
bestDistance = distanceToPacman;
chosenDir = dir;
}
}
} else {
// Fallback to random movement if pacman not available
chosenDir = validDirections[Math.floor(Math.random() * validDirections.length)];
}
if (chosenDir) {
self.moveToGrid(chosenDir.x, chosenDir.y);
}
}
}
};
return self;
});
var Pacman = Container.expand(function () {
var self = Container.call(this);
var mazeHeight = 27;
var mazeWidth = 25;
var graphics = self.attachAsset('pacman', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 9;
self.gridY = 19;
self.targetX = 0;
self.targetY = 0;
self.moving = false;
self.speed = 8;
self.moveToGrid = function (gx, gy) {
if (self.moving) return;
// Handle tunnel teleportation
if (gy === 13) {
// Tunnel row
if (gx < 0) {
gx = mazeWidth - 1; // Teleport to right side
} else if (gx >= mazeWidth) {
gx = 0; // Teleport to left side
}
}
// Check boundaries and wall collision
if (gy >= 0 && gy < mazeHeight && gx >= 0 && gx < mazeWidth && maze[gy] && maze[gy][gx] !== 1) {
self.moving = true;
self.gridX = gx;
self.gridY = gy;
self.targetX = offsetX + gx * cellSize + cellSize / 2;
self.targetY = offsetY + gy * cellSize + cellSize / 2;
}
};
self.update = function () {
if (self.moving) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.speed) {
self.x = self.targetX;
self.y = self.targetY;
self.moving = false;
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
};
return self;
});
var PowerPellet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('powerPellet', {
anchorX: 0.5,
anchorY: 0.5,
width: 50,
height: 50
});
self.collected = false;
self.update = function () {
graphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
graphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var maze = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 3, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 3, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1], [1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 1], [1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1], [0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0], [1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 1], [1, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 3, 1], [1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1], [1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
var mazeWidth = maze[0].length;
var mazeHeight = maze.length;
var cellSize = 60;
var offsetX = (2048 - mazeWidth * cellSize) / 2;
var offsetY = (2732 - mazeHeight * cellSize) / 2;
var walls = [];
var dots = [];
var powerPellets = [];
var ghosts = [];
var pacman = null;
var powerMode = false;
var powerModeTimer = 0;
var totalDots = 0;
var collectedDots = 0;
var powerPelletRespawnTimer = 1800; // 30 seconds at 60 FPS
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
for (var y = 0; y < mazeHeight; y++) {
for (var x = 0; x < mazeWidth; x++) {
var cell = maze[y][x];
var worldX = offsetX + x * cellSize + cellSize / 2;
var worldY = offsetY + y * cellSize + cellSize / 2;
if (cell === 1) {
var wall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: worldX,
y: worldY
}));
walls.push(wall);
} else if (cell === 2) {
var dot = game.addChild(new Dot());
dot.x = worldX;
dot.y = worldY;
dot.gridX = x;
dot.gridY = y;
dots.push(dot);
totalDots++;
} else if (cell === 3) {
var powerPellet = game.addChild(new PowerPellet());
powerPellet.x = worldX;
powerPellet.y = worldY;
powerPellet.gridX = x;
powerPellet.gridY = y;
powerPellets.push(powerPellet);
}
}
}
pacman = game.addChild(new Pacman());
pacman.gridX = 12;
pacman.gridY = 25;
pacman.x = offsetX + pacman.gridX * cellSize + cellSize / 2;
pacman.y = offsetY + pacman.gridY * cellSize + cellSize / 2;
pacman.targetX = pacman.x;
pacman.targetY = pacman.y;
var ghostColors = [0xFF0000, 0xFFB8FF, 0x00FFFF, 0xFFB852];
var ghostStartPositions = [{
x: 11,
y: 13
}, {
x: 12,
y: 12
}, {
x: 13,
y: 13
}, {
x: 12,
y: 14
}];
for (var i = 0; i < 4; i++) {
var ghost = game.addChild(new Ghost(ghostColors[i]));
ghost.gridX = ghostStartPositions[i].x;
ghost.gridY = ghostStartPositions[i].y;
ghost.spawnGridX = ghostStartPositions[i].x;
ghost.spawnGridY = ghostStartPositions[i].y;
ghost.x = offsetX + ghost.gridX * cellSize + cellSize / 2;
ghost.y = offsetY + ghost.gridY * cellSize + cellSize / 2;
ghost.targetX = ghost.x;
ghost.targetY = ghost.y;
ghosts.push(ghost);
}
// Player control variables
var swipeStartX = 0;
var swipeStartY = 0;
var swipeThreshold = 50;
// Touch controls for player
game.down = function (x, y, obj) {
swipeStartX = x;
swipeStartY = y;
};
game.up = function (x, y, obj) {
if (pacman.moving) return;
var swipeEndX = x;
var swipeEndY = y;
var deltaX = swipeEndX - swipeStartX;
var deltaY = swipeEndY - swipeStartY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance < swipeThreshold) return;
var newGridX = pacman.gridX;
var newGridY = pacman.gridY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (deltaX > 0) {
newGridX++;
} else {
newGridX--;
}
} else {
if (deltaY > 0) {
newGridY++;
} else {
newGridY--;
}
}
pacman.moveToGrid(newGridX, newGridY);
};
game.update = function () {
if (powerMode) {
powerModeTimer--;
if (powerModeTimer <= 0) {
powerMode = false;
// Reset Pacman speed to normal
pacman.speed = 8;
for (var i = 0; i < ghosts.length; i++) {
if (!ghosts[i].eaten) {
ghosts[i].makeNormal();
}
}
}
}
for (var i = dots.length - 1; i >= 0; i--) {
var dot = dots[i];
if (!dot.collected && pacman.gridX === dot.gridX && pacman.gridY === dot.gridY) {
dot.collected = true;
dot.visible = false;
collectedDots++;
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
LK.getSound('eatDot').play();
var collectedPowerPellets = 0;
for (var j = 0; j < powerPellets.length; j++) {
if (powerPellets[j].collected) collectedPowerPellets++;
}
if (collectedDots >= totalDots && collectedPowerPellets >= powerPellets.length) {
LK.showYouWin();
}
}
}
for (var i = powerPellets.length - 1; i >= 0; i--) {
var pellet = powerPellets[i];
if (!pellet.collected && pacman.gridX === pellet.gridX && pacman.gridY === pellet.gridY) {
pellet.collected = true;
pellet.visible = false;
powerMode = true;
powerModeTimer = 600;
// Triple Pacman's speed during power mode
pacman.speed = 24; // 8 * 3 = 24
LK.setScore(LK.getScore() + 50);
scoreTxt.setText(LK.getScore());
LK.getSound('powerUp').play();
for (var j = 0; j < ghosts.length; j++) {
if (!ghosts[j].eaten) {
ghosts[j].makeVulnerable();
}
}
}
}
for (var i = 0; i < ghosts.length; i++) {
var ghost = ghosts[i];
if (pacman.gridX === ghost.gridX && pacman.gridY === ghost.gridY) {
if (powerMode && ghost.vulnerable && !ghost.eaten) {
ghost.eaten = true;
ghost.respawning = true;
ghost.respawnTimer = 600; // 10 seconds at 60 FPS
ghost.gridX = ghost.spawnGridX;
ghost.gridY = ghost.spawnGridY;
ghost.x = offsetX + ghost.gridX * cellSize + cellSize / 2;
ghost.y = offsetY + ghost.gridY * cellSize + cellSize / 2;
ghost.targetX = ghost.x;
ghost.targetY = ghost.y;
ghost.moving = false;
LK.setScore(LK.getScore() + 200);
scoreTxt.setText(LK.getScore());
LK.getSound('eatGhost').play();
} else if (!ghost.vulnerable && !ghost.eaten) {
LK.showGameOver();
}
}
}
// Handle power pellet respawning every 30 seconds
powerPelletRespawnTimer--;
if (powerPelletRespawnTimer <= 0) {
powerPelletRespawnTimer = 1800; // Reset to 30 seconds
// Respawn all collected power pellets
for (var i = 0; i < powerPellets.length; i++) {
var pellet = powerPellets[i];
if (pellet.collected) {
pellet.collected = false;
pellet.visible = true;
}
}
}
};
KİRAZ. In-Game asset. 2d. High contrast. No shadows
Yuvarlak bir pizzanın bir dilimini alınmış olacak ve boş kısım ağzı olacak şekilde sürekli açıp kapatsın ağzını . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Hayalet. Arkaplan yok. Şeffaf arkaplan. Boş arkaplan.