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