CS248 – Computer Graphics
Autumn quarter 1999
Stanford University

Assignment #4 : 3D Video Game

Kyle Kuznetz (kuznetz@stanford.edu)
Nicolas Scapel (
Frédéric Mazzella (


  • A. How to get it
  • B. How to play the game
  • C. Extra Features
  • D. Sources

A. How to get it

Download the user friendly Pac 2K installation program at the following URL :
thanks !

B. How to play the game

Our program is a 3D tribute to Pacman, probably the world most famous Video Game. In short : eat the pellets, avoid the ghosts or use the red Super-Pellets to eat them... If you eat all the pellets, then you go to the next level. You can choose between the camera position, from the classic 2D view to a fully immersive "you are Pacman" standpoint...

If you play in COOL mode, then you will have the ability to jump, be invisible, and shoot the ghosts with a freezing gun... but if you want to remember the old days, you can play in OLD SCHOOL mode !

The levels are simply described in ASCII format in the Levels directory, making it very simple to modify them or create new ones. We have implemented 4 different levels. If you ever finish them, then you come back to the first one but the ghosts will be much more aggressive...

You can access the game menu at any time by pressing the ESC key. From there, you can :

  • Start a New Game
  • View the Introduction sequence
  • View the Highscores
  • Change the game options
  • Quit the game

1. Basic Controls

  • Move Pacman with the arrow keys
  • F2 sets the Classic view
  • F3 sets the 3D View
  • F4 sets the Doom View
  • In Doom View use ALT-LEFT and ALT-RIGHT to do a lateral move

2. Special Controls

If you are in COOL gameplay mode :

  • Use Z to shoot a ghost with a freezing bullet. You can have additionnal ammunitions with a Blue torus pellet.
  • The Green torus pellet makes you invisible for a while...
  • Use the SPACE BAR to jump

3. Options

You can navigate through the options in the Game Menu using the arrow keys, ENTER to change a value, and ESC to return to the game. Some options also have a shortcut, indicated as [F] for the F key:

  • Game view [F2 F3 F4] : Classic | 3D View | Doom View
  • Game play : Old school | Cool
  • Difficulty : Easy | Normal | Hard
  • Level of Detail [L] : Low | High
  • Reflection [R] : On | Off
  • Draw floor [D] : On | Off
  • Fog [F] : On | Off
  • Shading [S] : On | Off
  • Set Defaults

C. Extra Features

  • On-screen control panel : We have used two methods to display informations on screen. The Score, Remaining lives, and Ammunition items are drawn as 3D objects in the scene, and can be viewed in the CLASSIC view (orthogonal projection). The Highscores panel is also an orthogonal projection of 3D objects. For the Game Menu we have used font.c code from the redbook, with some minor modifications, e.g. changed some bitmaps in order to represent "2" and "3"... We pause the game, set glutIdleFunc(NULL), copy the entire screen, 800x600, multiply each pixels r, g, and b values by 0.5 in order to darken the background scenery, and then wrote the menu text to the foreground using screen coordinates...
  • View frustum culling : We can take advantage of the maze construction method for our view frustum algorithm : all the objects are drawn within a maze unit cell, so we can use a same cubic bounding box for all the objects in the scene. Actually, we can come with a more straightforward algorithm : given the camera parameters, we just have to compute a binary mask over the maze, and the value of one cell tells us if the object is to be drawn. This is how we implemented view frustum culling. The binary mask is computed using viewing angle calculations. This feature is really boosting the game in Doom View, where 75% of the scene is out of the camera frustum.
  • Level of detail control : We want to compute a parameter 0 < alpha < 1 which will correspond to the object level of detail. We first compute the distance d from the object to the camera. alpha is then computed as a non-linear function of d ( alpha = cos(k * d) ), leading to a less perceptible loss of quality. Since all the objects are drawn within a maze unit cell, it makes sense to have only one parameter per object. Within each object drawing function, we specify the precision range, for example instead of calling
    glutSolidSphere (.25, 10, 10), we will call
    glutSolidSphere(.25, getResolution(3, 10), getResolution(3,10))
    If level of detail is enabled, the getResolution function will interpolate between the min and max values using the value of alpha, else it will return the max value. This feature is greatly improving performance in the 3D Views without fog, when the whole maze is to be displayed.
  • Reflection - Multipass rendering : In order to get reflection to work we used the dinoreflection example as a base (the code was obtained from the opengl examples website). Basically, we took our scene, flipped it upside down into the negative 1 plane on the z-axis, and used a blend function on our floor in order to see through it. We also used the stencil buffer so that when reflecting our surface, if the user happens to look underneath the floor, s/he won't see the "fake" upside scene which creates the reflection. So, we draw our floor first using the stencil buffer, so that when drawing our reflected scene, the pixels which get drawn are the pixels that are turned on in the stencil buffer (or the pixels which are at the same location as part of the floor). If the reflected scene wants to draw a pixel in a spot where the stencil buffer is not turned on, then we don't draw that part of the scene...
  • Sound : The game includes intro music and sound effects wich rely on the PlaySound() function. We have found Pacman's original sound effects on the web [see sources], and we synchronize sounds with the game events. We also use sound timing for the intro sequence : the titles appearing on the screen are synchronised with the music, using real time management functions.

Screenshot from the original Pacman

  • AI : We wanted to integrate in our game the original AI behavior of the ghosts (those that were in the original Pacman game). Without AI, the game was not interesting to play, since a random behavior is too simple to play. Each ghost has its own personality: Shadow is the red ghost and it chases Pacman all the time, using a straight forward tracking algorithm. Speedy is the pink ghost. It is very fast but moves in a random manner. Bashful is the blue ghost: it is shy at the beginning and escapes from pacman all the time, but if Pacman approaches him to much, then it is not shy anymore and begins to chase him (Pacman is then chased by two ghosts at the same time...). Pokey is the orange ghost and is slow and moves in a random manner. When Pacman eats a special pellet that allows him to eat the ghost, all the ghosts become blue, move twice as slow as before and change their direction. After that try to escape Pacman, still going twice as slow as before. When Pacman eats a ghost, the eyes of the ghost come back home...
  • Fire - Procedural Modeling : We assigned "hot" values to random indices in the bottom row of an array, once these values were assigned, we moved up the array, and for each pixel, assigned an average of surrounding pixels...

D. External sources

  • Sounds were obtained from http://www.classicgaming.com/pac-man/ , from the movie Beetlegeuse, and the THX logo...
  • Menu text obtained from opengl sample code, font.c, with some minor modifications to write a "2" and a "3"...
  • Fred's texture code uses Nate Miller's tga import function :
    Copyright (C) 1999
    For non-commercial use only.

    File : tga.c
    Date : 05/05/1999
    Author : Nate Miller
    Contact :

Monday, December 6, 1999