Using The VIC Game Paddles
In addition to being able to use the Atari joystick (as described in my article in the Fall, 1981 issue of Home and Educational COMPUTING!), the Commodore VIC can use the Atari game paddles. This article provides a tutorial on how these paddles work with the VIC by giving a detailed discussion of a Pong game. This version of Pong can have two human players against one another, or one player against the VIC which has nine skill levels. A game paddle version of the classic game Breakout with three skill levels is also presented. After studying these two programs the reader should be a game paddle "expert" and be capable of easily incorporating game paddles into his own programs.
How Game Paddles Work
For those readers who are unfamiliar with the Atari game paddles, a brief description is in order. These game paddles are included when you buy an Atari home video computer system (the game machine), or may be purchased separately as a peripheral device for the Atari personal computer. The price for a pair of paddles varies between $15 and $20. There are two separate paddle units which attach to a single connector that plugs directly into the VIC game port. Each paddle unit consists of a red "fire" button and a knob that may be turned freely in either direction. The knob is attached to a potentiometer which varies a voltage fed into the VIC's game port. After converting this voltage to a digital value, the VIC is able to know the exact position to which the knob has been turned.
To see how the VIC can read the paddles, plug your paddles into the game port and enter the following short program:
10 DD = 37154:P1=37151:P2 = 37152 20 PX = 36872:PY = 36873 30 POKE DD,127:P = PEEK(P2) AND 128 40 FR = -(P = 0):POKE DD,255 50 P = PEEK(P1):FL = -((PAND16) = O) 60 VL = PEEK(PX): VR = PEEK(PY) 70 PRINT "CLEAR"FL;VL;FR;VR 200 GOTO30
When you RUN this program you should see four numbers in the first row of the screen. The first two numbers correspond to the left paddle and the last two values to the right paddle. FL and FR will be either one or zero depending upon whether the left or right "fire" button is pushed or not. VL and VR will correspond to the knob settings for the left and right paddles respectively. Both VL and VR will vary between 255 and zero as the knobs are turned clockwise from their leftmost position to their rightmost position. You will notice that the knobs are more sensitive than their wide arc would imply, i.e. there is a large band of arc at either extreme of the knob's movement where the values stay at 255 or zero. The actual arc where the values change linearly from zero to 255 is only about one-quarter of a full turn. Although this is a little more sensitive than you might wish, you will find that this will still be enough arc to produce some exciting games.
The reason why this short program actually works is beyond both the scope of this article and the interest level of most readers. I will leave it to Commodore to explain more fully when they issue their documentation on the game paddles. Suffice it to say, it does work!
Controlling Screen Motion
To see how the game paddles can be used to control motion on the VIC's screen, add the following lines of code to the above program:
2 POKE 36879, 27:PRINT"CLEAR":C = 4 4 S = 256*PEEK(648):A = 30720:LL = S 6 IF PEEK(648)=16 THEN A = 33792 70 X = 21-INT(VL*21/255): Y = 22-INT(VR*22/255) 80 NL = S + X + 22*Y:CL = NL + A 90 IF FR OR FL THEN C = C+1 100 IF C = 8 THEN C = 2 110 IF NL = LL THEN 30 120 POKE LL,32:POKE LL + A, 1 130 POKE NL,81:POKE CL,C 140 LL = NL
You will notice that line 70 above replaces line 70 in the previous program. All of the other lines are new additions.
When you run this program, you will find that the game paddles will move a ball graphic character around the screen at a very rapid pace. Specifically, the left paddle will move the ball from left to right horizontally, and the right paddle will cause vertical movement from top to bottom. Pushing either one of the fire buttons will change the ball's color.
Let's look at this short program in more detail. It not only demonstrates how the game paddles can control motion (and will make following the logic of Pong and Breakout easier) but also contains several useful techniques that will help improve any "action" game you may write. Line 2 sets the border color to cyan and the background color to white, and clears the screen. The variable "C" contains the color of the ball and is initialized to purple.
Lines 4 and 6 will be a useful addition to any program that POKEs characters to the screen. As you may have read or even experienced, when memory modules (8K or more) are plugged into the VIC, the location of the screen memory and the color matrix move. When you run a program which assumes the screen is in its "normal" position of 7680 and the screen has actually moved (to 4096), the results are frequently a disaster. Line 4 and 6 determine the correct locations for the screen and the color matrix — regardless of the amount of memory that has been added to the VIC. In line 4, the variable "S" will be the starting location of the screen and will be either 7680 or 4096. The variable "A" is the value that must be added to a particular screen location to get its corresponding color matrix location. For example, if we POKE location S with 81 (a ball character), and we POKE location S + A with 4, we would get a purple ball in the "home" corner of the screen. For a "normal" 3.5K VIC, "A" is 30720, i.e., the start of the color matrix is 7680 + 30720 or 38400. If the screen moves to 4096, the color matrix will move to 37888 and the value of "A" changes to 33792 — this is the condition given in line 6.
The logic of the Pong program actually starts on line 280 which defines a group of variables that will be used repeatedly later. R is the number of rows. C is the number of columns. NA$(1 and 2) contain the two players names. SP$(1 and 2) contain strings with the cursor control characters needed to position the cursor where each player's name is printed. SC(1 and 2) contain the scores for the two players. In lines 290 and 300 more useful variables are defined. E and F are values used in the calculation of the paddle location. By making these calculations once at the start of the program, and just referencing their variable names later, the speed of the game is increased. The other variables in these lines are either identical to those used in the previous example or their purpose will be obvious when you see how they are used. Line 300 determines the starting locations for the screen, S, and color matrix, S + A.
Line 320 defines three very useful functions. FNA will return the current screen location corresponding to row Y and column X. This will normally be the ball's location. FNB will return the color matrix location corresponding to FNA. FNR(Z) will return a random integer between 0 and Z. Lines 330 to 470 ask the player(s) to specify the options for the play of the game. The variable N is the number of players. If N = 1 then the VIC will play the part of the player on the right side of the screen. The variable D is the skill level for the VIC. A value of 1 will play a very poor game. A value of 9 will never miss a shot.
Lines 480 to 520 begin the game by zeroing both scores, randomly deciding who serves first, clearing the screen, drawing the border in row 1, and printing the names and scores in row 0. Line 530 tests the variable SV (which will either be 1 for the left player's serve or 2 for the right player's serve) and branches accordingly.
Lines 540 to 580 handle the left player's serve. Specifically, line 550 reads the status of the left fire button and allows the left paddle and the right paddles to move by the GOSUB's to 120 and 190 respectively. Line 560 jumps back to 550 unless the fire button has been pushed and the serve has been made. Line 570 randomly causes the serve to go upward (DY = -1) or downward (DY = + 1). Line 580 puts the ball in front of the current position of the left paddle, sets its forward direction toward the right (DX = + 1), sounds a "hit", and branches to line 670 which is the actual play loop.
Lines 590 to 650 are the right player's serve routines. Line 600 tests N for the number of players. If N = 1 and the VIC is playing the right side, line 610 waits a random amount of time and then serves. Lines 620 to 650 handle a human player on the right side almost identically to the way that lines 550 to 580 handle the left side player.
Line 670 is the start of the play loop and moves the ball one position in its current direction, via the GOSUB70. Line 690 allows the left paddle to move. Line 700 tests whether it is possible that the ball is about to hit a paddle because it is either in column 2 or column 19, i.e., one column from the paddles. If the answer is no, the ball is allowed to move one more position. This "extra" move in the playing loop makes the game considerably faster — to see how much faster try the game with line 700 deleted.
Line 710 to 790 handle the right player's paddle move. Lines 730 to 760 are for the VIC playing the right paddle. Based on whether a random integer from zero to 9 is greater than the skill level, the VIC will move. If the VIC moves, it moves so its paddle is even vertically with the current position of the ball. Obviously, if the skill level is 9, then the VIC will always move and will never miss the ball. Line 780 makes the paddle move for a human player on the right side.
Line 790 again tests whether the ball is possibly going to hit a paddle because it is in a column next to a paddle. If the answer is no, then the program branches back to the start of the play loop at line 670. If the answer is yes, the ball is either just about to hit the paddle or to miss it. Lines 810 and 820 determine the values for ZZ, the index for the player who will win the point if there is a mix, and ZC, the screen PEEK/POKE character for the paddle. Line 830 slows any "fast" ball down to normal speed.
Lines 840 and 850 test if the ball would hit the paddle if it moved one more position. The variable Q in line 840 is the screen location of the position next (in the same row) to the ball's current position. If the screen character at location Q is equal to ZC, the appropriate paddle character, the ball is about to hit the middle of the paddle and the program branches to 960. Line 850 performs the same type of test, but for a possible "corner" hit.
If the ball failed both of these tests, it is just about to miss the paddle. In this case lines 870 to 940 move the ball off the field, sound a "miss," update the score, determine the next server (the loser), and branch back to serve again or asks about a new game if that was the winning point.
If the ball is hit by the paddle, line 960 will change its direction, sound a "hit," and move it one position on its flight path. Line 970 will randomly make it a "fast" ball by doubling the ball's X movement, DX. This not only doubles the speed, but also changes the angle of flight. These "fast" balls make the game much more exciting.
After having gone through the previous example, the subroutines used in Pong should be very straightforward. The subroutine at line 70, checks if the ball is about to hit a wall and, if the answer is yes, it causes the ball to bounce. Then this subroutine erases the current ball location and draws it at its new location. The subroutines at 120 and 190 move the left and right paddles respectively. They first check to see if the paddle has moved since the last reading. If the answer is no, they RETURN. If yes, these subroutines erase the last paddle, and draw a paddle at the new location. The subroutine at 260 sounds a "hit" and the subroutine at 270 a "miss."
The version of Breakout here also uses the game paddles. You will find it much faster and more exciting than versions which use a joystick or the keyboard and can only move the paddle a column at a time. It has three skill levels and the highest will challenge even the most seasoned arcade malingerers.
The overall program flow and even the variable names are almost identical to Pong. The program is well commented and self-documenting.