/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ghost = Container.expand(function (color, startX, startY) {
var self = Container.call(this);
var graphics = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = color;
self.gridX = startX;
self.gridY = startY;
self.direction = 0;
self.speed = 2;
self.vulnerable = false;
self.vulnerableTimer = 0;
self.moveTimer = 0;
self.x = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.y = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.update = function () {
self.moveTimer++;
if (self.vulnerable) {
self.vulnerableTimer--;
graphics.tint = self.vulnerableTimer % 60 < 30 ? 0x0000FF : 0xFFFFFF;
if (self.vulnerableTimer <= 0) {
self.vulnerable = false;
graphics.tint = color;
}
}
if (self.moveTimer % (self.vulnerable ? 6 : 4) === 0) {
// Simple AI: choose random valid direction
var validDirections = [];
var directions = [{
dx: 1,
dy: 0
},
// right
{
dx: 0,
dy: 1
},
// down
{
dx: -1,
dy: 0
},
// left
{
dx: 0,
dy: -1
} // up
];
for (var i = 0; i < directions.length; i++) {
var newX = self.gridX + directions[i].dx;
var newY = self.gridY + directions[i].dy;
if (newX >= 0 && newX < MAZE_WIDTH && newY >= 0 && newY < MAZE_HEIGHT) {
if (maze[newY][newX] !== 1) {
validDirections.push(i);
}
}
}
if (validDirections.length > 0) {
self.direction = validDirections[Math.floor(Math.random() * validDirections.length)];
var dir = directions[self.direction];
self.gridX += dir.dx;
self.gridY += dir.dy;
// Handle tunnel wrapping
if (self.gridX < 0) self.gridX = MAZE_WIDTH - 1;
if (self.gridX >= MAZE_WIDTH) self.gridX = 0;
self.x = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.y = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
}
}
};
return self;
});
var PacMan = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('pacman', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = 0; // 0=right, 1=down, 2=left, 3=up
self.nextDirection = 0;
self.speed = 3;
self.gridX = 1;
self.gridY = 1;
self.animationTimer = 0;
self.targetX = 1 * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.targetY = 1 * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.moveProgress = 1.0;
self.isMoving = false;
self.update = function () {
self.animationTimer++;
// Simple mouth animation by scaling
if (self.animationTimer % 20 < 10) {
graphics.scaleX = 0.9;
} else {
graphics.scaleX = 1.0;
}
// Update rotation based on direction
graphics.rotation = self.direction * Math.PI / 2;
// Handle smooth movement
if (self.isMoving) {
self.moveProgress += 0.15; // Movement speed
if (self.moveProgress >= 1.0) {
self.moveProgress = 1.0;
self.isMoving = false;
self.x = self.targetX;
self.y = self.targetY;
} else {
// Interpolate position
var startX = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
var startY = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.x = startX + (self.targetX - startX) * self.moveProgress;
self.y = startY + (self.targetY - startY) * self.moveProgress;
}
}
// Start new movement if not currently moving
if (!self.isMoving) {
var newGridX = self.gridX;
var newGridY = self.gridY;
// Calculate next position
if (self.direction === 0) newGridX++; // right
else if (self.direction === 1) newGridY++; // down
else if (self.direction === 2) newGridX--; // left
else if (self.direction === 3) newGridY--; // up
// Check if next position is valid
if (newGridX >= 0 && newGridX < MAZE_WIDTH && newGridY >= 0 && newGridY < MAZE_HEIGHT) {
if (maze[newGridY][newGridX] !== 1) {
// Handle tunnel wrapping
if (newGridX < 0) newGridX = MAZE_WIDTH - 1;
if (newGridX >= MAZE_WIDTH) newGridX = 0;
// Start smooth movement
self.gridX = newGridX;
self.gridY = newGridY;
self.targetX = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.targetY = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.moveProgress = 0.0;
self.isMoving = true;
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var MAZE_WIDTH = 19;
var MAZE_HEIGHT = 21;
var CELL_SIZE = 40;
var MAZE_OFFSET_X = (2048 - MAZE_WIDTH * CELL_SIZE) / 2;
var MAZE_OFFSET_Y = 200;
// Simple maze layout (1 = wall, 0 = empty, 2 = dot, 3 = power pellet)
var maze = [[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, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 3, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1], [1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 1], [1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 2, 1, 0, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1, 0, 2, 2, 2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 2, 1, 0, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1], [1, 3, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 3, 1], [1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1], [1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1], [1, 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]];
var walls = [];
var dots = [];
var powerPellets = [];
var ghosts = [];
var pacman;
var score = 0;
var lives = 3;
var level = 1;
var powerMode = false;
var powerModeTimer = 0;
var ghostScore = 200;
var totalDots = 0;
var dotsEaten = 0;
// Create maze elements
for (var y = 0; y < MAZE_HEIGHT; y++) {
for (var x = 0; x < MAZE_WIDTH; x++) {
var cellX = x * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
var cellY = y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
if (maze[y][x] === 1) {
var wall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: cellX,
y: cellY
}));
walls.push(wall);
} else if (maze[y][x] === 2) {
var dot = game.addChild(LK.getAsset('dot', {
anchorX: 0.5,
anchorY: 0.5,
x: cellX,
y: cellY
}));
dots.push({
obj: dot,
x: x,
y: y,
eaten: false
});
totalDots++;
} else if (maze[y][x] === 3) {
var pellet = game.addChild(LK.getAsset('powerPellet', {
anchorX: 0.5,
anchorY: 0.5,
x: cellX,
y: cellY
}));
powerPellets.push({
obj: pellet,
x: x,
y: y,
eaten: false
});
}
}
}
// Create Pac-Man
pacman = game.addChild(new PacMan());
pacman.x = pacman.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
pacman.y = pacman.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
// Create ghosts
var ghostColors = [0xFF0000, 0xFFB8FF, 0x00FFFF, 0xFFB852];
var ghostPositions = [[9, 8], [9, 9], [8, 9], [10, 9]];
for (var i = 0; i < 4; i++) {
var ghost = game.addChild(new Ghost(ghostColors[i], ghostPositions[i][0], ghostPositions[i][1]));
ghosts.push(ghost);
}
// UI elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFF00
});
scoreText.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreText);
scoreText.x = 120;
scoreText.y = 20;
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFFFF00
});
livesText.anchor.set(1, 0);
LK.gui.topRight.addChild(livesText);
livesText.x = -20;
livesText.y = 20;
var levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFF00
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
levelText.y = 20;
// Touch controls
var lastTouchX = 0;
var lastTouchY = 0;
game.down = function (x, y, obj) {
lastTouchX = x;
lastTouchY = y;
};
game.up = function (x, y, obj) {
var deltaX = x - lastTouchX;
var deltaY = y - lastTouchY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
pacman.nextDirection = deltaX > 0 ? 0 : 2; // right or left
} else {
// Vertical swipe
pacman.nextDirection = deltaY > 0 ? 1 : 3; // down or up
}
// Try to change direction immediately if not moving or can turn
var newGridX = pacman.gridX;
var newGridY = pacman.gridY;
if (pacman.nextDirection === 0) newGridX++; // right
else if (pacman.nextDirection === 1) newGridY++; // down
else if (pacman.nextDirection === 2) newGridX--; // left
else if (pacman.nextDirection === 3) newGridY--; // up
if (newGridX >= 0 && newGridX < MAZE_WIDTH && newGridY >= 0 && newGridY < MAZE_HEIGHT) {
if (maze[newGridY][newGridX] !== 1) {
pacman.direction = pacman.nextDirection;
// If currently moving, interrupt and start new movement
if (pacman.isMoving) {
pacman.gridX = Math.round((pacman.x - MAZE_OFFSET_X - CELL_SIZE / 2) / CELL_SIZE);
pacman.gridY = Math.round((pacman.y - MAZE_OFFSET_Y - CELL_SIZE / 2) / CELL_SIZE);
pacman.isMoving = false;
}
}
}
};
game.update = function () {
if (powerMode) {
powerModeTimer--;
if (powerModeTimer <= 0) {
powerMode = false;
for (var i = 0; i < ghosts.length; i++) {
ghosts[i].vulnerable = false;
}
ghostScore = 200;
}
}
// Check dot collection
for (var i = 0; i < dots.length; i++) {
var dot = dots[i];
if (!dot.eaten && dot.x === pacman.gridX && dot.y === pacman.gridY) {
dot.eaten = true;
dot.obj.visible = false;
score += 10;
dotsEaten++;
LK.setScore(score);
scoreText.setText('Score: ' + score);
LK.getSound('chomp').play();
}
}
// Check power pellet collection
for (var i = 0; i < powerPellets.length; i++) {
var pellet = powerPellets[i];
if (!pellet.eaten && pellet.x === pacman.gridX && pellet.y === pacman.gridY) {
pellet.eaten = true;
pellet.obj.visible = false;
score += 50;
LK.setScore(score);
scoreText.setText('Score: ' + score);
powerMode = true;
powerModeTimer = 300; // 5 seconds at 60fps
ghostScore = 200;
for (var j = 0; j < ghosts.length; j++) {
ghosts[j].vulnerable = true;
ghosts[j].vulnerableTimer = powerModeTimer;
}
LK.getSound('powerUp').play();
}
}
// Check ghost collision
for (var i = 0; i < ghosts.length; i++) {
var ghost = ghosts[i];
if (ghost.gridX === pacman.gridX && ghost.gridY === pacman.gridY) {
if (ghost.vulnerable) {
// Eat ghost
score += ghostScore;
ghostScore *= 2;
LK.setScore(score);
scoreText.setText('Score: ' + score);
ghost.vulnerable = false;
ghost.gridX = ghostPositions[i][0];
ghost.gridY = ghostPositions[i][1];
ghost.x = ghost.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
ghost.y = ghost.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
LK.getSound('eatGhost').play();
} else {
// Lose life
lives--;
livesText.setText('Lives: ' + lives);
if (lives <= 0) {
LK.showGameOver();
} else {
// Reset positions
pacman.gridX = 1;
pacman.gridY = 1;
pacman.x = pacman.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
pacman.y = pacman.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
for (var j = 0; j < ghosts.length; j++) {
ghosts[j].gridX = ghostPositions[j][0];
ghosts[j].gridY = ghostPositions[j][1];
ghosts[j].x = ghosts[j].gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
ghosts[j].y = ghosts[j].gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
ghosts[j].vulnerable = false;
}
powerMode = false;
powerModeTimer = 0;
}
}
}
}
// Check level completion
if (dotsEaten >= totalDots) {
level++;
dotsEaten = 0;
levelText.setText('Level: ' + level);
// Reset dots and pellets
for (var i = 0; i < dots.length; i++) {
dots[i].eaten = false;
dots[i].obj.visible = true;
}
for (var i = 0; i < powerPellets.length; i++) {
powerPellets[i].eaten = false;
powerPellets[i].obj.visible = true;
}
// Increase ghost speed
for (var i = 0; i < ghosts.length; i++) {
ghosts[i].speed = Math.min(ghosts[i].speed + 0.5, 5);
}
// Reset positions
pacman.gridX = 1;
pacman.gridY = 1;
pacman.x = pacman.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
pacman.y = pacman.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
for (var i = 0; i < ghosts.length; i++) {
ghosts[i].gridX = ghostPositions[i][0];
ghosts[i].gridY = ghostPositions[i][1];
ghosts[i].x = ghosts[i].gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
ghosts[i].y = ghosts[i].gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
ghosts[i].vulnerable = false;
}
powerMode = false;
powerModeTimer = 0;
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ghost = Container.expand(function (color, startX, startY) {
var self = Container.call(this);
var graphics = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = color;
self.gridX = startX;
self.gridY = startY;
self.direction = 0;
self.speed = 2;
self.vulnerable = false;
self.vulnerableTimer = 0;
self.moveTimer = 0;
self.x = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.y = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.update = function () {
self.moveTimer++;
if (self.vulnerable) {
self.vulnerableTimer--;
graphics.tint = self.vulnerableTimer % 60 < 30 ? 0x0000FF : 0xFFFFFF;
if (self.vulnerableTimer <= 0) {
self.vulnerable = false;
graphics.tint = color;
}
}
if (self.moveTimer % (self.vulnerable ? 6 : 4) === 0) {
// Simple AI: choose random valid direction
var validDirections = [];
var directions = [{
dx: 1,
dy: 0
},
// right
{
dx: 0,
dy: 1
},
// down
{
dx: -1,
dy: 0
},
// left
{
dx: 0,
dy: -1
} // up
];
for (var i = 0; i < directions.length; i++) {
var newX = self.gridX + directions[i].dx;
var newY = self.gridY + directions[i].dy;
if (newX >= 0 && newX < MAZE_WIDTH && newY >= 0 && newY < MAZE_HEIGHT) {
if (maze[newY][newX] !== 1) {
validDirections.push(i);
}
}
}
if (validDirections.length > 0) {
self.direction = validDirections[Math.floor(Math.random() * validDirections.length)];
var dir = directions[self.direction];
self.gridX += dir.dx;
self.gridY += dir.dy;
// Handle tunnel wrapping
if (self.gridX < 0) self.gridX = MAZE_WIDTH - 1;
if (self.gridX >= MAZE_WIDTH) self.gridX = 0;
self.x = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.y = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
}
}
};
return self;
});
var PacMan = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('pacman', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = 0; // 0=right, 1=down, 2=left, 3=up
self.nextDirection = 0;
self.speed = 3;
self.gridX = 1;
self.gridY = 1;
self.animationTimer = 0;
self.targetX = 1 * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.targetY = 1 * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.moveProgress = 1.0;
self.isMoving = false;
self.update = function () {
self.animationTimer++;
// Simple mouth animation by scaling
if (self.animationTimer % 20 < 10) {
graphics.scaleX = 0.9;
} else {
graphics.scaleX = 1.0;
}
// Update rotation based on direction
graphics.rotation = self.direction * Math.PI / 2;
// Handle smooth movement
if (self.isMoving) {
self.moveProgress += 0.15; // Movement speed
if (self.moveProgress >= 1.0) {
self.moveProgress = 1.0;
self.isMoving = false;
self.x = self.targetX;
self.y = self.targetY;
} else {
// Interpolate position
var startX = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
var startY = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.x = startX + (self.targetX - startX) * self.moveProgress;
self.y = startY + (self.targetY - startY) * self.moveProgress;
}
}
// Start new movement if not currently moving
if (!self.isMoving) {
var newGridX = self.gridX;
var newGridY = self.gridY;
// Calculate next position
if (self.direction === 0) newGridX++; // right
else if (self.direction === 1) newGridY++; // down
else if (self.direction === 2) newGridX--; // left
else if (self.direction === 3) newGridY--; // up
// Check if next position is valid
if (newGridX >= 0 && newGridX < MAZE_WIDTH && newGridY >= 0 && newGridY < MAZE_HEIGHT) {
if (maze[newGridY][newGridX] !== 1) {
// Handle tunnel wrapping
if (newGridX < 0) newGridX = MAZE_WIDTH - 1;
if (newGridX >= MAZE_WIDTH) newGridX = 0;
// Start smooth movement
self.gridX = newGridX;
self.gridY = newGridY;
self.targetX = self.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
self.targetY = self.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
self.moveProgress = 0.0;
self.isMoving = true;
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var MAZE_WIDTH = 19;
var MAZE_HEIGHT = 21;
var CELL_SIZE = 40;
var MAZE_OFFSET_X = (2048 - MAZE_WIDTH * CELL_SIZE) / 2;
var MAZE_OFFSET_Y = 200;
// Simple maze layout (1 = wall, 0 = empty, 2 = dot, 3 = power pellet)
var maze = [[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, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 3, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1], [1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 1], [1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 2, 1, 0, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1, 0, 2, 2, 2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 2, 1, 0, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1], [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1], [1, 3, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 3, 1], [1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1], [1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 1], [1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1], [1, 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]];
var walls = [];
var dots = [];
var powerPellets = [];
var ghosts = [];
var pacman;
var score = 0;
var lives = 3;
var level = 1;
var powerMode = false;
var powerModeTimer = 0;
var ghostScore = 200;
var totalDots = 0;
var dotsEaten = 0;
// Create maze elements
for (var y = 0; y < MAZE_HEIGHT; y++) {
for (var x = 0; x < MAZE_WIDTH; x++) {
var cellX = x * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
var cellY = y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
if (maze[y][x] === 1) {
var wall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: cellX,
y: cellY
}));
walls.push(wall);
} else if (maze[y][x] === 2) {
var dot = game.addChild(LK.getAsset('dot', {
anchorX: 0.5,
anchorY: 0.5,
x: cellX,
y: cellY
}));
dots.push({
obj: dot,
x: x,
y: y,
eaten: false
});
totalDots++;
} else if (maze[y][x] === 3) {
var pellet = game.addChild(LK.getAsset('powerPellet', {
anchorX: 0.5,
anchorY: 0.5,
x: cellX,
y: cellY
}));
powerPellets.push({
obj: pellet,
x: x,
y: y,
eaten: false
});
}
}
}
// Create Pac-Man
pacman = game.addChild(new PacMan());
pacman.x = pacman.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
pacman.y = pacman.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
// Create ghosts
var ghostColors = [0xFF0000, 0xFFB8FF, 0x00FFFF, 0xFFB852];
var ghostPositions = [[9, 8], [9, 9], [8, 9], [10, 9]];
for (var i = 0; i < 4; i++) {
var ghost = game.addChild(new Ghost(ghostColors[i], ghostPositions[i][0], ghostPositions[i][1]));
ghosts.push(ghost);
}
// UI elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFF00
});
scoreText.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreText);
scoreText.x = 120;
scoreText.y = 20;
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFFFF00
});
livesText.anchor.set(1, 0);
LK.gui.topRight.addChild(livesText);
livesText.x = -20;
livesText.y = 20;
var levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFF00
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
levelText.y = 20;
// Touch controls
var lastTouchX = 0;
var lastTouchY = 0;
game.down = function (x, y, obj) {
lastTouchX = x;
lastTouchY = y;
};
game.up = function (x, y, obj) {
var deltaX = x - lastTouchX;
var deltaY = y - lastTouchY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
pacman.nextDirection = deltaX > 0 ? 0 : 2; // right or left
} else {
// Vertical swipe
pacman.nextDirection = deltaY > 0 ? 1 : 3; // down or up
}
// Try to change direction immediately if not moving or can turn
var newGridX = pacman.gridX;
var newGridY = pacman.gridY;
if (pacman.nextDirection === 0) newGridX++; // right
else if (pacman.nextDirection === 1) newGridY++; // down
else if (pacman.nextDirection === 2) newGridX--; // left
else if (pacman.nextDirection === 3) newGridY--; // up
if (newGridX >= 0 && newGridX < MAZE_WIDTH && newGridY >= 0 && newGridY < MAZE_HEIGHT) {
if (maze[newGridY][newGridX] !== 1) {
pacman.direction = pacman.nextDirection;
// If currently moving, interrupt and start new movement
if (pacman.isMoving) {
pacman.gridX = Math.round((pacman.x - MAZE_OFFSET_X - CELL_SIZE / 2) / CELL_SIZE);
pacman.gridY = Math.round((pacman.y - MAZE_OFFSET_Y - CELL_SIZE / 2) / CELL_SIZE);
pacman.isMoving = false;
}
}
}
};
game.update = function () {
if (powerMode) {
powerModeTimer--;
if (powerModeTimer <= 0) {
powerMode = false;
for (var i = 0; i < ghosts.length; i++) {
ghosts[i].vulnerable = false;
}
ghostScore = 200;
}
}
// Check dot collection
for (var i = 0; i < dots.length; i++) {
var dot = dots[i];
if (!dot.eaten && dot.x === pacman.gridX && dot.y === pacman.gridY) {
dot.eaten = true;
dot.obj.visible = false;
score += 10;
dotsEaten++;
LK.setScore(score);
scoreText.setText('Score: ' + score);
LK.getSound('chomp').play();
}
}
// Check power pellet collection
for (var i = 0; i < powerPellets.length; i++) {
var pellet = powerPellets[i];
if (!pellet.eaten && pellet.x === pacman.gridX && pellet.y === pacman.gridY) {
pellet.eaten = true;
pellet.obj.visible = false;
score += 50;
LK.setScore(score);
scoreText.setText('Score: ' + score);
powerMode = true;
powerModeTimer = 300; // 5 seconds at 60fps
ghostScore = 200;
for (var j = 0; j < ghosts.length; j++) {
ghosts[j].vulnerable = true;
ghosts[j].vulnerableTimer = powerModeTimer;
}
LK.getSound('powerUp').play();
}
}
// Check ghost collision
for (var i = 0; i < ghosts.length; i++) {
var ghost = ghosts[i];
if (ghost.gridX === pacman.gridX && ghost.gridY === pacman.gridY) {
if (ghost.vulnerable) {
// Eat ghost
score += ghostScore;
ghostScore *= 2;
LK.setScore(score);
scoreText.setText('Score: ' + score);
ghost.vulnerable = false;
ghost.gridX = ghostPositions[i][0];
ghost.gridY = ghostPositions[i][1];
ghost.x = ghost.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
ghost.y = ghost.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
LK.getSound('eatGhost').play();
} else {
// Lose life
lives--;
livesText.setText('Lives: ' + lives);
if (lives <= 0) {
LK.showGameOver();
} else {
// Reset positions
pacman.gridX = 1;
pacman.gridY = 1;
pacman.x = pacman.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
pacman.y = pacman.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
for (var j = 0; j < ghosts.length; j++) {
ghosts[j].gridX = ghostPositions[j][0];
ghosts[j].gridY = ghostPositions[j][1];
ghosts[j].x = ghosts[j].gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
ghosts[j].y = ghosts[j].gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
ghosts[j].vulnerable = false;
}
powerMode = false;
powerModeTimer = 0;
}
}
}
}
// Check level completion
if (dotsEaten >= totalDots) {
level++;
dotsEaten = 0;
levelText.setText('Level: ' + level);
// Reset dots and pellets
for (var i = 0; i < dots.length; i++) {
dots[i].eaten = false;
dots[i].obj.visible = true;
}
for (var i = 0; i < powerPellets.length; i++) {
powerPellets[i].eaten = false;
powerPellets[i].obj.visible = true;
}
// Increase ghost speed
for (var i = 0; i < ghosts.length; i++) {
ghosts[i].speed = Math.min(ghosts[i].speed + 0.5, 5);
}
// Reset positions
pacman.gridX = 1;
pacman.gridY = 1;
pacman.x = pacman.gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
pacman.y = pacman.gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
for (var i = 0; i < ghosts.length; i++) {
ghosts[i].gridX = ghostPositions[i][0];
ghosts[i].gridY = ghostPositions[i][1];
ghosts[i].x = ghosts[i].gridX * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_X;
ghosts[i].y = ghosts[i].gridY * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
ghosts[i].vulnerable = false;
}
powerMode = false;
powerModeTimer = 0;
}
};
A pac man ghost. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
PAC man. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A star . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat