Classic Computer Magazine Archive COMPUTE! ISSUE 17 / OCTOBER 1981 / PAGE 98

Extending Player Missile Graphics

Eric Stoltman
San Antonio, TX

One of the best features of the Atari is Player Missile Graphics. Since it has been introduced, many people have started using it in their programs, (some improving upon it, such as Larry Isaacs). This article and example program will explain how to create excellent animation, such as a walking figure or a rotating ship, with just one player.

One way to perform animation is to alternate players back and forth, but problems arise. What if the player is moved up? The other players also have to be moved up. This takes time. Another method is to alternately POKE data into the player, thus changing its shape. This can be done slowly in BASIC or quickly and easily in machine language. This program will compare both the BASIC and machine language method for changing the data of a player.

After a player is set up, additional data for other shapes must be stored in RAM. I prefer to use memory locations 256 to 511, since they are empty and are protected. This data can be manipulated by setting up pointers in an array. A subroutine can then easily retrieve this data and place it in the player's data area. This can be done in BASIC:

C = 0: A = PMBASE + 512 + Y TO PMBASE + 519 + Y:
  POKE A, PEEK(POINTER(FACING) + C) : C = C + 1: NEXT A
POINTER(FACING) = Array containing addresses of data.
EXAMPLE: POINTER(1) = 260, POINTER(2) = 268, etc.

Or in machine language:

A = USR(XXX, PMBASE + 512 + Y, POINTER(FACING))
XXX = Address of Machine Language subroutine.

The machine language method is not only easier, but also executes 11 times faster and provides smoother motion.

The machine language code is relocatable and can easily be modified by changing the 22nd data element so more or less data can be poked into the player's data area. For machine language programmers, I have included the machine language listing:

         *=    	   $0600
CHANGE   PLA
         PLA
         STA         $CC
         PLA
         STA         $CB
         PLA
         STA         $CF
         PLA
         STA         $CE
         LDY         #$00
LOOP     LDA         ($CE), Y
         STA         ($CB), Y
         INY
         CPY         #$08
         BNE         LOOP
         RTS
Line Numbers Explanation
110-130 Poke machine language subroutine for changing player into player.
140-170 Poke data for additional shapes into memory.
180-190 Set up pointers to data.
200-250 Set up player
270-330 If trigger is pressed change player by machine language.
340-400 If trigger is not pressed change player by BASIC.

In addition to providing animation, this subroutine can move a player up or down when the vertical value changes greatly. To do this, point to an empty area of RAM (thus erasing the player) and then change the vertical value and point to the desired data. An example would be if a player went off the top of the screen and, using the method mentioned above, quickly reappeared at the bottom.

I should point out that many false players, that is, data for alternate shapes, may be stored and rotated among the four players to provide excellent animation.

10 REM BY ERIC STOLTMAN
20 REM THE ‘I’ IN POINTER SHOULD BE A ‘1’ SINCE ‘POINT’ IS A RESERVED WORD
100 REM ** INITIALIZATION **
110 FOR A = 1536 TO 1560 : READ I = POKE A, I = NEXT A : REM POKE DATA FOR MACHINE
        LANGUAGE SUBROUTINE INTO MEMORY
120 REM ** MACHINE LANGUAGE DATA **
130 DATA 104, 104, 133, 204, 104, 133, 203, 104, 133, 207, 104, 133, 206, 160, 0, 177,
        206, 145, 203, 200, 192, 8, 208, 247, 96
140 REM ** ADDRESS OF PLAYER DATA **
150 FOR A = 260 TO 323 : READ I : POKE A, I : NEXT A : REM POKE DATA INTO PROTECTED RAM
155 REM ** PLAYER DATA **
160 DATA 28, 62, 62, 28, 73, 127, 73, 65, 7, 23, 39, 88, 154, 36, 8, 16, 240, 38, 47, 127,
        47, 38, 240, 0, 16, 8, 36, 154, 88, 39, 23, 7
170 DATA 65, 73, 127, 73, 28, 62, 62, 28, 8, 16, 36, 89, 26, 228, 232, 224, 15, 108, 244,
        254, 244, 100, 15, 0, 224, 232, 228, 26, 89, 36, 16, 8
180 REM ** POINTERS TO DATA **
190 DIM POINTED(8) : FOR A = 1 TO READ I : POINTER(A) = I : NEXT A : DATA 260, 268,
        276, 284, 292, 300, 308, 316
200 REM ** SETUP PLAYER **
210 GRAPHICS 0 : POKE 752, 1 : POKE 710, 0 : POKE 559, 46
220 A = PEEK(106) - 8 : POKE 54279, A : POKE 53277, 3 : PMBASE = 256 * A : POKE 53256, 1 :
        X = 124 : Y = 48230 FOR A = PMBASE + 512 TO PMBASE + 640 : POKE A, 0 : NEXT A
240 POKE 53248, 124 : POKE 704, 12 : FACING = 1
250 C = 0 : FOR A = PMBASE + 512 + Y TO PMBASE + 519 + Y : POKE A, PEEK(POINTER(FACING)+C) :
        C = C+1 : NEXT A
270 REM ** MACHINE LANGUAGE CHANGE **
275 IF STRIG(0) = 1 THEN 340
280 POSITION 5, 5 : ? "MACHINE LANGUAGE";
285 J = STICK(0)
290 IF J = 15 THEN 270
300 IF J = 11 THEN FACING = FACING-1 : IF FACING<1 THEN FACING = 8
310 IF J = 7 THEN FACING = FACING+1 : IF FACING>8 THEN FACING = 1
320 D = USR(1536, PMBASE + 512 + Y, POINTERS (FACING))
330 GOTO 270
340 REM ** BASIC CHANGE **
345 IF STRIG(0) = 0 THEN 270
350 POSITION 5,5 :? "BASIC     ";
355 J = STICK(0)
360 IF J = 15 THEN 270
370 IF J = 11 THEN FACING = FACING-1 : IF FACING<1 THEN FACING = 8
380 IF J = 7 THEN FACING = FACING+1 : IF FACING>8 THEN FACING = 1
390 C = 0 : FOR A = PMBASE + 512 + Y TO PMBASE + 519 + Y : POKE A, PEEK(POINTER FACING)+C) :
        C = C+1 : NEXT A
400 GOTO 340