PACMAN BATTLE

Three Screens showing the PacMan-Battle Website
CONTACT

OVERVIEW

PacMan Battle Thumbnail

The Problem
Traditional Pac-Man is a single-player game, limiting opportunities for competitive and cooperative gameplay.

The Goal
Expand Pac-Man into a two-player experience while maintaining the classic feel and mechanics.

My Role
I was responsible for game design and development, from ideation to prototyping and final implementation, as part of a team of four.

UNDERSTANDING THE USER

Competitive Audit

To ensure PacMan Battle provided an engaging and competitive multiplayer experience, we conducted a competitive audit, analyzing existing projects to understand what works and what doesn’t. Our goal was to convert the iconic game into a multiplayer format while staying true to its retro aesthetic and mechanics.

Limitations

We explored co-op variations, but due to technical constraints, we ultimately focused on a turn-based competition model. A real-time online multiplayer experience would require high data exchange frequency, which the university’s server could not handle. As a result, some of our competitive benchmarks didn’t fully align with our final approach.

Persona

Since extensive research already existed on Pac-Man’s target audience, we conducted a secondary analysis to understand our potential users better. Based on the findings, we developed an ad-hoc persona to capture our target group's needs and frustrations.

Persona Lukas displayed with his characteristics

Problem Statement

Lukas isretro game enthusiast who needs an engaging multiplayer experience of Pac-Man because it allows him to relive the nostalgia of the game while playing socially with friends.

REFINING THE DESIGN

Sketching

To explore different design concepts, we visualized the game layout through digital sketches. Early iterations helped us quickly refine design choices before transitioning into digital prototyping, ensuring the final approach remained true to the Pac-Man aesthetic.

Visual Elements

Colour Palett PacMan Battle
Font PacMan Battle
A screen showing the Homepage of PacMan Battle

Usability Study

Once our initial game layout was in place, we conducted usability testing to validate our design decisions and test the functionality of our code.

The usability test involved a live demonstration of the prototype to a group of 11 participants. They could play freely and explore the mechanics naturally. We observed this real-world user interactions and conducted interviews to identify areas for improvement.

Improvements

Tunnel Mechanic
Removed due to a bug where characters could escape the game area

Scoring System
Adjusted points to create a fairer competitive game

Local Score Storage
Information is spread across multiple sources

Interactive Quiz
We introduced a Pac-Man-themed quiz to maintain engagemen

Tunnel Mechanic
Removed due to a bug where characters could escape the game area

Scoring System
Adjusted points to create a fairer competitive game

Local Score Storage
Information is spread across multiple sources

Interactive Quiz
We introduced a Pac-Man-themed quiz to maintain engagemen

IMPLEMENTATION

Gameplay

Quiz

Board and Map Generation

The game board is built using a grid-based system, where each tile represents different objects in an array.

                        
    // Map Example    
    const map = [
        ['1', 'a', 'a', '2'],  // Walls = a / Corners = Numbers
        ['b', '.', '.', 'b'],  // Pellets = . / Vertical Walls = b
        ['b', 'p', 'p', 'b'],  // Power-ups = p
        ['4', 'a', 'a', '3']   // Walls = a / Corners = Numbers
    ];
                    
                        
    // Dynamic Generation
    function generateMap () {
        map.forEach((row, i) => { 
            row.forEach((symbol, j) => { 
                if (symbol === '.') {
                    pellets.push(new Pellet({ position: { x: j * 32, y: i * 32 }}));
                } else if (symbol === 'p') {
                    powerUps.push(new PowerUp({ position: { x: j * 32, y: i * 32 }}));
                } else {
                    boundaries.push(new Boundary({ position: { x: j * 32, y: i * 32 }}));
                }
            });
        });
    }
                    

Player and Movement Controls

Pac-Man's movement follows a collision-based system. To avoid conflicts with webpage functions, only W, A, S, D keys were assigned for player controls.

                        
    // Player Movement
    document.addEventListener("keydown", (event) => {
        switch (event.key) {
            case 'ArrowUp': player.velocity.y = -3; break;
            case 'ArrowDown': player.velocity.y = 3; break;
            case 'ArrowLeft': player.velocity.x = -3; break;
            case 'ArrowRight': player.velocity.x = 3; break;
        }
    });
                    
                        
    // Collision Detection
    boundaries.forEach((boundary) => {
        if (circleCollidesWithRectangle({ circle: player, rectangle: boundary })) {
            player.velocity.x = 0;
            player.velocity.y = 0;
        }
    });
                    

Ghost AI and Pathfinding

The ghosts navigate randomly while avoiding walls. At the same time, the AI adjusts movement based on available paths.

                        
    // Ghosts Movement
    const possibleDirections = ['up', 'down', 'left', 'right'];
    const randomDirection = possibleDirections[Math.floor(Math.random() * possibleDirections.length)];
    switch (randomDirection) {
        case 'up': ghost.velocity.y = -3; break;
        case 'down': ghost.velocity.y = 3; break;
        case 'left': ghost.velocity.x = -3; break;
        case 'right': ghost.velocity.x = 3; break;
    }
                    
                        
    // Ghosts Change Behavior
    ghosts.forEach(ghost => {
        ghost.scared = true;
        setTimeout(() => ghost.scared = false, 5000);
    });
                    

Multiplayer Turn System

                        
    // Round Timer
    var timeLeft = 20;
    var timerId = setInterval(() => {
        timeLeft--;
        if (timeLeft === 0) {
            clearTimeout(timerId);
            switchTurn();
        }
    }, 1000);
                    
                        
    // Switch Turn
    function switchTurn() {
        currentPlayer = currentPlayer === 1 ? 2 : 1;
        resetPlayerPosition();
    }
                    

Scoring System and Power-Ups

                        
    // Power-Up Collision Effect
    if (circleCollidesWithRectangle({ circle: player, rectangle: pellet })) {
        pellets.splice(i, 1); // Remove pellet
        score += 10; // Increase score
    } 
                    
                        
    // Power to Eat Ghosts
    if (circleCollidesWithRectangle({ circle: player, rectangle: powerUp })) {
        powerUps.splice(i, 1);
        ghosts.forEach(ghost => ghost.scared = true);
    }
                    
© 2025 Anthony Zoss. All rights reserved.