Classic Computer Magazine Archive ANTIC VOL. 3, NO. 2 / JUNE 1984

Use Basic to Animate

An easier way to program your own games

By Fred Pinho

This article, the first in a two-part series, shows you how to control Player/Missile graphics from BASIC. The accompanying BASIC program is a four-player, tank-battle game. It requires a minimum of 32K ram. XL owners should modify the program as specified below. For an introduction to Player/Missile graphics, see "Player/Missile Tutorial" by Chris Chabris (Antic, p.14, September 1983). Part Two will appear next month.

This tutorial was inspired by a plea from a desperate reader Despite having read numerous magazine articles about Player/Missile (P/M) graphics, he hasn't been able to fulfill his desire: to write a tank-warfare game that uses four tanks on the screen. More importantly, he needs to learn a simple method, via BASIC, to move players and fire missiles horizontally.

Alas, it's not that simple. BASIC knows little or nothing of the P/M system, so it's not easy to control P/M graphics with BASIC. The programmer must keep track of all important registers, and must write a program to move players around on the screen. The horizontal movement of a player can be accomplished with relative ease by means of a single POKE, but vertical motion is much more complex.

You must relocate data bytes in memory to move a player vertically. And to make things even more confusing, if you move data upwards in memory, your player moves downward on the screen. As a result of these factors, vertical motion from BASIC is almost always excruciatingly slow.

You can achieve rapid player motion with machine language. However, most BASIC programmers aren't familiar enough with machine language to accomplish this.

Now for the good news. There is a way to do a passable job of achieving vertical player motion through BASIC, if you use some specialized tricks. But because of the speed problem, you'll have to keep your game fairly simple.

The accompanying program is a simple, four-player tank game. Each player is controlled by a separate joystick (one each in Ports 1 to 4). You can fire vertically and horizontally. To prevent random firing, each tank is limited to 30 shells. The first tank to hit its opponents 10 times wins. Only the score is displayed; you have to keep track of how many shots you've fired. There's a "reload" time of two to three seconds between each shot, during which you must maneuver for safety You can only fire while moving, and you cannot move or fire diagonally.

For XL Owners Only

Since Atari XL machines have only two joystick ports, you cannot play Tank Battle as a four-player game. As a result, you must disable two of the tanks. The simplest way to do this is to delete lines 1170 and 1180. If you follow the program logic, this may seem to be illogical, since it eliminates the instructions for Players 1 and 2, not Players 2 and 3. (The Antic staff tried eliminating the instructions for Players 2 and 3, but when we did so the remaining tanks wouldn't fire.)

Modifying the Game

You can add features such as diagonal movement/firing and the ability to keep track of the number of shots fired without too much trouble. However, each feature you add will slow down the game. You can then move tanks and missiles in greater increments to compensate for the lack of speed, but their motion will appear "jerky" and problems with collision detection will be introduced. The choice is up to you, the programmer.

The game isn't as smooth as it would be if it were coded in machine language. However, within BASIC's limits, it's fast enough to result in a playable game.

P/M System Paramaters

To help you set up housekeeping for the P/M system, I've listed all of the important registers and their functions in Table 1. Note that some of the registers have two different meanings, depending on whether you're reading (with a PEEK) or writing (with a POKE) to them. For instance, you can POKE player 0's horizontal position into location 53248. But you can't check its position by PEEKing 53248. When PEEKed, that register functions as a collision register for player 0 missiles. Table 1 indicates whether a register is read only, write only, or both.

Programmung the P/M System

This section describes, in order, the registers that you must use to set up a Player/Missile system.

Vertical Player Resolution

See Table 1, Item 15. A player can be drawn in either of two resolutions. Single-line resolution provides high resolution, equivalent to that of Graphics 8, but uses more memory (2K). Double-line resolution, which is equivalent to that of Graphics 7, uses only IK.

Storage of PM data

See Table 1, Item 14. Examine Figure 1, which shows the organization of memory for P/M data. Note that a block of memory that is safe from other activities must be reserved. My program places data below the display list, as shown in Figure 1. If you store your data here, be careful not to let the BASIC program move into the P/M data area. In Figure 1, note that each player has its own memory space, but that the missiles are lumped together in a common area. Each player is eight-bits wide, but the missiles are only two-bits wide. Thus, each byte contains data for all four missiles. To put a missile on the screen, POKE these numbers into the missile data area:

                    HALF-WIDTH         FULL-WIDTH
MISSILE#             MISSILE             MISSILE
0                    1 or 2               3
1                    4 or 8               12
2                   16 or 32              48
3                   64 or 128             192
Data for one missile is independent of that for other missiles. You can, for instance, POKE a three into one byte for missile 0 and 12 into another byte for missile 1. Since the bytes are different, each missile appears at a different vertical location on the screen. Each missile also has its own horizontal-position register, so you have complete control over its movement.

Table 2 shows you where to store P/M data for each graphics mode, while taking certain restrictions into account. The first of these is the actual amount of memory required (2K for single-line resolution, 1K for double-line resolution). The second is that the block of memory must start on a 2K boundary for single-line resolution, and on a 1K boundary for double-line resolution. This means that the address of the start of P/M memory must be exactly divisible by 1024 (1K boundary) or 2048 (2K boundary). If you don't place P/M data on the proper boundary, the system won't work correctly.

TABLE 1


                                   PLAYER/MISSILE REGISTERS

LOCATION(S)                 FUNCTION                              COMMENTS                 POKE and PEEK
--------------   -----------------------------------    -----------------------------      -------------
1) 53248-53251   Horizontal-position registers for      POKE values of 0 to 255. Only       POKE only
                 players 0 to 3                         values of about 48-208 are visible
                                                        on the screen.

2) 53252-53255   Horizontal-position registers for      same.                               POKE only
                 missiles 0 to 3

3) 53256-53259   Size registers for players 0 to 3      See Note 1                          POKE only

4) 53260         Size registers for players 0 to 3      See Note 2                          POKE only

5) 53248-53251   Collision registers between            See Note 3                          PEEK only
                 missiles and playfield graphics.
                 Missiles 0 to 3

6) 53252-53255   Collision registers between            See Note 4                          PEEK only
                 players and playfield graphics.
                 Players 0 to 3

7) 53256-53259   Collision registers between            See Note 5                          PEEK only
                 missiles and players. Missiles 0 to 3

8) 53260-53263   Colision registers between players.    See Note 6                          PEEK only
                 Players 0 to 3

9) 53278         Used to clear all collision registers  POKE any number but zero to         POKE only
                                                        clear register. See Note 7

10) 53261-53264  Graphics-data registers for            Used by the computer to disply      POKE only
                 players 0 to 3                         P/M data, Not normally used by
                                                        programmers.

11) 53265        Graphics-data register for all         Same                                POKE only
                 missiles

12) 704-707      Color registers for players 0 to 3     Missile has same color as its       Both
                 and associated missile                 player. Must POKE color value into
                                                        register. See Note 8.

13) 623          Priority register                      See Note 9                          Both

14) 54279        PMBASE. Page number of start of                                            Both
                 Player/Missile memory area

15) 559          DMA control. Specifies type of         See Note 10                         Both
                 P/M resolution and whether the
                 screen is turned on or off.

16) 53277        Graphics control. Enables the          POKE zero to dissable P/M system.   POKE only
                 Player/Missile system                  POKE 3 to enable P/M.


Notes
1. Player-Size Register

Value to POKE      Size
      0,2          Normal Width
      1            Double Width
      3            Quadruple Width
The default (normal) register value is zero. Only the width, not the height, is affected.

2.Missile-Size Register

        Value to POKE for Size
Missile  Normal    Double    Quadruple
   0       0          1          3
   1       0          4         12
   2       0         16         48
   3       0         64        192
Each missile's width can be controlled independently with this register.

3. Missile/Playfield Collision Registers

A planyfield object is anything drawn on the screen with PLOT and DRAWTO commands. Characters that are PRINTed to the screen are also playfield objects. The playfield's number corresponds to the COLOR command used before graphics plotting. If a collision between a missile and a playfield object occurs on screen, PEEKing these registers tells you which playfield was hit.

Value in      Playfield        COLOR Command
Register         Hit        Corresponding to Playfield
   1              0                 1
   2              1                 2
   4              2                 3
   8              3          None. Used to print in
                               Graphics 1 and 2
4. Player/Playfield Collision Register

These registers are affected when a player collides with a playfield. This table is identical to the one in Note 3.

5. Missile/Player Collision Registers

These registers are affected when a player collides with a missile.

    Value in      Player
    Register       Hit
       1            0
       2            1
       4            2
       8            3
6. Player/Playfield Collision Registers

These registers are affected by collisions between players. This table is identical to that in Note 5.

7. Collision-Clear Register

POKE this register with any value from zero to 255 to clear all of the collision registers. It's important that your program clear these registers frequently. If this isn't done, multiple collisions may result in unanticipated values that confuse your program. It's best to clear these registers just before each player or missile movement.

8. Player/Missile Color Registers

Set each player's color by POKEing the proper register with the result of this formula: COLOR = LUMINANCE + 16 * HUE

9. Priority Register

This selects the screen objects that are to be displayed "in front" of other objects. Background color always has the lowest priority.

POKE Priority Order

1 Players 0, 1, 2, 3, Playfields 0, 1, 2, 3

2 Players 0, 1, Playfields 0, 1, 2, 3, Players 2, 3

4 Playfields 0, 1, 2, 3, Players 0, 1, 2, 3

8 Playfields 0, 1, Players 0, 1, 2, 3, Playfields 2, 3

If you increase the value of the contents of the Priority Register by 32, you can combine players (0 with 1, and 2 with 3) to form multicolored players'.

10. Direct-Memory-Access (DMA) Control Registers

This register controls the screen and Player/Missile display as follows:

                     Add to Final
Option              Value for POKE     Comments

Narrow Playfield            1           Choose
Standard Playfield          2            only
Wide Playfield              3             one
Enable-Missile DMA          4
Enable-Player DMA           8
Double-Line Player
  Resolution                0      Default value
Single-Line Player
  Resolution               16
Regular-Graphics DMA       32
The default (normal) value for this register is 34 (regular graphics, standard playfield, P/M not enabled). POKE 559,0 to turn off the screen and speed processing time by up to 30 percent (for fast initialization).

Table 2

  Locating P/M Data Beneath the Display List

Graphics    Locate PMBASE at indicated Offset
 Mode          (in pages) below RAMTOP

               Double-line    Single-line
               Resolution     Resolution
  0                 8             16
  1                 8             16
  2                 8             16
  3                 8             16
  4                 8             16
  5                12             16
  6                16             24
  7                24             32
  8-11             36             40
PMBASE is the location in memory of the start of P/M data. Store the page number (address/256) of PMBASE in location 54279. RAMTOP, in location 106, holds the number of pages of RAM in the machine. Let's pick Graphics 5. We code the following:

PM = PEEK(106)-16:POKE 54279, PM

So far, we've covered some of the registers listed in table 1. I'll describe the remaining registers, and provide a detailed program description next month.

Listing: PMTANKS.BAS Download

Fred Pinho is a biochemical research engineer and a self-taught programmer who is interested in BASIC and assembly language. The Atari 800 is his first computer.