Students add Pacman with arrow key movement, wall collision, pellet eating, and a mouth animation using arc().
// ════════════════════════════════════════════════════════════
// DAY 2 — Moving Pacman
// Adds: Pacman sprite, arrow key movement, wall collision,
// pellet eating, score, mouth animation
// ════════════════════════════════════════════════════════════
const TILE_SIZE = 20;
const COLS = 21;
const ROWS = 21;
const PATH = 0, WALL = 1, PELLET = 2, POWER = 3;
let maze = [
[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,1,2,2,2,2,2,2,2,2,2,1],
[1,2,1,1,2,1,1,1,1,2,1,2,1,1,1,1,2,1,1,2,1],
[1,3,1,1,2,1,1,1,1,2,1,2,1,1,1,1,2,1,1,3,1],
[1,2,1,1,2,2,2,1,1,2,2,2,1,1,2,2,2,1,1,2,1],
[1,2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,2,1],
[1,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,1],
[1,1,1,1,2,1,1,1,0,0,1,0,0,1,1,1,2,1,1,1,1],
[1,1,1,1,2,1,0,0,0,0,1,0,0,0,0,1,2,1,1,1,1],
[1,1,1,1,2,1,0,1,1,0,0,0,1,1,0,1,2,1,1,1,1],
[1,2,2,2,2,0,0,1,0,0,0,0,0,1,0,0,2,2,2,2,1],
[1,1,1,1,2,1,0,1,1,1,1,1,1,1,0,1,2,1,1,1,1],
[1,1,1,1,2,1,0,0,0,0,1,0,0,0,0,1,2,1,1,1,1],
[1,1,1,1,2,1,1,1,0,0,1,0,0,1,1,1,2,1,1,1,1],
[1,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,1],
[1,2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,2,1],
[1,2,1,1,2,2,2,1,1,2,2,2,1,1,2,2,2,1,1,2,1],
[1,3,1,1,2,1,1,1,1,2,1,2,1,1,1,1,2,1,1,3,1],
[1,2,1,1,2,1,1,1,1,2,1,2,1,1,1,1,2,1,1,2,1],
[1,2,2,2,2,2,2,2,2,2,1,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],
];
// NEW: Pacman state
let pacRow = 16, pacCol = 10;
let pacDir = 0; // 0=right, 90=down, 180=left, 270=up
let mouthAngle = 0;
let mouthOpen = true;
let score = 0;
function setup() {
createCanvas(COLS * TILE_SIZE, ROWS * TILE_SIZE);
frameRate(60);
noSmooth();
}
function draw() {
background(0);
drawMaze();
animateMouth(); // NEW
drawPacman(); // NEW
drawScore(); // NEW
}
function drawMaze() {
for (let row = 0; row < ROWS; row++) {
for (let col = 0; col < COLS; col++) {
let cell = maze[row][col];
let x = col * TILE_SIZE, y = row * TILE_SIZE;
if (cell === WALL) {
fill(0, 0, 180); noStroke(); rect(x, y, TILE_SIZE, TILE_SIZE);
} else if (cell === PELLET) {
fill(0); rect(x, y, TILE_SIZE, TILE_SIZE);
fill(255, 255, 200); noStroke();
circle(x + TILE_SIZE/2, y + TILE_SIZE/2, 4);
} else if (cell === POWER) {
fill(0); rect(x, y, TILE_SIZE, TILE_SIZE);
fill(255, 180, 0); noStroke();
circle(x + TILE_SIZE/2, y + TILE_SIZE/2, 12);
} else {
fill(0); rect(x, y, TILE_SIZE, TILE_SIZE);
}
}
}
}
// NEW: oscillates mouth between 0 and 40 degrees
function animateMouth() {
if (mouthOpen) { mouthAngle += 4; if (mouthAngle >= 40) mouthOpen = false; }
else { mouthAngle -= 4; if (mouthAngle <= 0) mouthOpen = true; }
}
// NEW: draws Pacman as a pie/wedge using arc()
function drawPacman() {
let x = pacCol * TILE_SIZE + TILE_SIZE / 2;
let y = pacRow * TILE_SIZE + TILE_SIZE / 2;
fill(255, 220, 0); noStroke();
arc(x, y, TILE_SIZE - 2, TILE_SIZE - 2,
radians(pacDir + mouthAngle),
radians(pacDir + 360 - mouthAngle),
PIE
);
}
function drawScore() {
fill(255); noStroke(); textSize(12); textAlign(LEFT, TOP);
text('SCORE: ' + score, 6, 4);
}
// NEW: move on arrow key press, check wall, eat pellet
function keyPressed() {
let nextRow = pacRow, nextCol = pacCol;
if (keyCode === UP_ARROW) { nextRow -= 1; pacDir = 270; }
if (keyCode === DOWN_ARROW) { nextRow += 1; pacDir = 90; }
if (keyCode === LEFT_ARROW) { nextCol -= 1; pacDir = 180; }
if (keyCode === RIGHT_ARROW) { nextCol += 1; pacDir = 0; }
if (maze[nextRow][nextCol] !== WALL) {
pacRow = nextRow; pacCol = nextCol;
if (maze[pacRow][pacCol] === PELLET) {
maze[pacRow][pacCol] = PATH; score += 10;
} else if (maze[pacRow][pacCol] === POWER) {
maze[pacRow][pacCol] = PATH; score += 50;
}
}
}