New: Source code (converted from the TASM C64 assembler to the Acme cross-assembler)
The summer of 2005, during my visit to Martin Wendt in Hamburg, we created a Pong game using a laser diode, two stepper motors, and a C64. More detailed information (including source code and schematics) will appear sooner or later.
One of the motors was positioned on the floor, for horizontal movement. The other was glued onto the first one, allowing vertical and horizontal movement of the laser diode connected to the upper motor. The user port of the C64 was connected to the steppers via a set of Darlington transistors, and the laser was powered by the cassette port (which in retrospect probably was a bad idea, as I suspect that induced voltages may have partially fried the laser, significantly reducing its strength).
This is the same principle as a vector monitor: you control the X-Y coordinates (well, spherical in this case, but close enough if the angles are small - which they have to be for acceptable speed of movement) and the intensity of the beam manually. Thus, the choice of Pong for this device is no coincidince, very few applications can make good use of a vector monitor. An 8x16 step area was used, with the paddles 3 steps long. This however looked better than it would on a 16x8 pixel display, since there were no large squares.
An annoying issue was the fact that you have to be very careful about the timing. If you turn off the laser too late, you'll see the vibrations in the laser magnified a few thousand times on the wall. You also want the motors to move as quickly as possible, but for physical reasons you need some delays. Getting these right in a 6502 assembly program can get a little tricky.
After writing some driver code (which handles timing, movement, and so on), it's easy to implement Pong. Joysticks are used for input, and the game itself is fairly ordinary.
A few words on final performance. The refresh rate needs to be at least 2-3 Hz to allow you to at least see the playing field in a dark room. This limits the maximum size of the field - 16x8 was a decent compromise between refresh rate and field size.