← Back to Blog Apr 23, 2026 · 11:00 AM · 7 min read

Pac-Man Power Pellet Mode: Ghosts Turn Blue and Become Edible

In Part 3 we gave ghosts unique chase personalities. Now we add the most iconic Pac-Man mechanic — power pellets that turn the tables. When Pac-Man eats a power pellet, all ghosts turn blue, reverse direction, and become edible for bonus points.

How Power Mode Works

Step 1: Add Frightened State Variables

Track whether power mode is active, how long it lasts, and a combo counter for escalating ghost eat bonuses.

let frightened = false;
let frightenedTimer = 0;
const FRIGHTENED_DURATION = 8000; // 8 seconds
const FLASH_START = 6000; // start flashing at 6s
let ghostEatCombo = 0;
const GHOST_SCORES = [200, 400, 800, 1600];

Step 2: Trigger Frightened Mode

When Pac-Man eats a power pellet, activate frightened mode and reverse all ghost directions.

function activatePowerMode() {
  frightened = true;
  frightenedTimer = Date.now();
  ghostEatCombo = 0;

  // Reverse all ghost directions
  ghosts.forEach(g => {
    if (!g.eaten) {
      g.dir = (g.dir + 2) % 4;
    }
  });
}

// In movePacman(), when eating a power pellet:
if (tile === 3) {
  score += SCORE_PELLET;
  dotsLeft--;
  map[ny][nx] = 0;
  activatePowerMode();
}

Step 3: Frightened Ghost Movement

Frightened ghosts move randomly instead of chasing. They also move slower — we skip every other frame for them.

let frameCount = 0;

function moveGhost(ghost) {
  if (ghost.eaten) {
    moveToGhostHouse(ghost);
    return;
  }

  // Frightened ghosts move slower (skip frames)
  if (frightened && frameCount % 2 !== 0) return;

  if (frightened) {
    moveGhostRandom(ghost);
  } else {
    updateGhostTarget(ghost);
    moveGhostToTarget(ghost);
  }
}

function moveGhostRandom(ghost) {
  const dirs = [{x:1,y:0},{x:0,y:1},{x:-1,y:0},{x:0,y:-1}];
  const reverse = (ghost.dir + 2) % 4;
  const valid = [];

  for (let d = 0; d < 4; d++) {
    if (d === reverse) continue;
    const nx = ghost.x + dirs[d].x;
    const ny = ghost.y + dirs[d].y;
    if (map[ny] && map[ny][nx] !== 1) valid.push(d);
  }

  if (valid.length === 0) valid.push(reverse);
  const pick = valid[Math.floor(Math.random() * valid.length)];
  ghost.x += dirs[pick].x;
  ghost.y += dirs[pick].y;
  ghost.dir = pick;
}

Step 4: Eating Frightened Ghosts

When Pac-Man collides with a frightened ghost, award bonus points and send the ghost back to the ghost house.

function checkGhostCollision() {
  for (const ghost of ghosts) {
    if (ghost.eaten) continue;
    if (ghost.x !== pacman.x || ghost.y !== pacman.y) continue;

    if (frightened) {
      // Eat the ghost
      const bonus = GHOST_SCORES[
        Math.min(ghostEatCombo, GHOST_SCORES.length - 1)
      ];
      score += bonus;
      ghostEatCombo++;
      ghost.eaten = true;

      // Show score popup
      addScorePopup(ghost.x, ghost.y, bonus);
    } else {
      onPacmanCaught();
      return;
    }
  }
}
Tip: The escalating bonus (200 → 400 → 800 → 1600) rewards players who chain ghost eats in a single power mode. This is a core scoring strategy in competitive Pac-Man.

Step 5: Ghost House Return

Eaten ghosts travel back to the ghost house at double speed, then respawn with their normal color.

const GHOST_HOUSE = { x: 9, y: 8 };

function moveToGhostHouse(ghost) {
  const dx = GHOST_HOUSE.x - ghost.x;
  const dy = GHOST_HOUSE.y - ghost.y;

  // Move 2 tiles per frame (fast return)
  if (Math.abs(dx) > Math.abs(dy)) {
    ghost.x += Math.sign(dx);
  } else {
    ghost.y += Math.sign(dy);
  }

  // Arrived at ghost house
  if (ghost.x === GHOST_HOUSE.x &&
      ghost.y === GHOST_HOUSE.y) {
    ghost.eaten = false;
  }
}

Step 6: Draw Frightened Ghosts

Frightened ghosts are blue. Near the end of the timer, they flash between blue and white to warn the player.

function drawGhost(ghost) {
  if (ghost.eaten) {
    drawGhostEyes(ghost); // eyes only
    return;
  }

  const cx = ghost.x * TILE_SIZE + TILE_SIZE / 2;
  const cy = ghost.y * TILE_SIZE + TILE_SIZE / 2;
  const r = TILE_SIZE / 2 - 2;

  if (frightened) {
    const elapsed = Date.now() - frightenedTimer;
    // Flash white/blue in last 2 seconds
    if (elapsed > FLASH_START) {
      const flash = Math.floor(elapsed / 200) % 2;
      ctx.fillStyle = flash ? '#fff' : '#2121DE';
    } else {
      ctx.fillStyle = '#2121DE';
    }
  } else {
    ctx.fillStyle = ghost.color;
  }

  // Draw body (same shape as before)
  ctx.beginPath();
  ctx.arc(cx, cy - 2, r, Math.PI, 0);
  ctx.lineTo(cx + r, cy + r);
  for (let i = 0; i < 3; i++) {
    const w = (r * 2) / 3;
    const bx = cx + r - w * i;
    ctx.quadraticCurveTo(bx - w/4, cy + r - 4,
                         bx - w/2, cy + r);
  }
  ctx.fill();

  // Frightened face (wavy mouth)
  if (frightened) {
    ctx.fillStyle = '#fff';
    ctx.beginPath();
    ctx.arc(cx - 3, cy - 3, 2, 0, Math.PI * 2);
    ctx.arc(cx + 3, cy - 3, 2, 0, Math.PI * 2);
    ctx.fill();
  } else {
    drawGhostEyes(ghost);
  }
}

Step 7: Update the Timer

Check the frightened timer each frame. When it expires, return all ghosts to normal chase mode.

function updateFrightened() {
  if (!frightened) return;

  const elapsed = Date.now() - frightenedTimer;
  if (elapsed > FRIGHTENED_DURATION) {
    frightened = false;
    ghostEatCombo = 0;
  }
}

// Add to gameLoop:
// updateFrightened();

What's Next?

Power pellet mode adds a huge layer of strategy. Players now have to decide when to eat pellets for maximum ghost combos. In the next parts:

Continue to Part 5: Multiple Levels where we add level progression with increasing difficulty.

More Articles

📈
Tutorial Pac-Man Levels: Speed Up Ghosts Each Level Tutorial · Apr 23, 2026 · 12:00 PM
🔊
Tutorial Pac-Man Sound Effects: Waka-Waka and Beyond Tutorial · Apr 23, 2026 · 01:00 PM
👻
Tutorial Pac-Man Ghost Chase AI: Make Ghosts Hunt the Player Tutorial · Apr 23, 2026 · 10:00 AM
← Back to Blog