Who said you can't write a good Invaders program in Mode7?
TOM BLACKBURN has done it!
AT last, an authentic game of Invaders to run on both the Model
A and B micros. In good arcade style, there are five colourful
and ever advancing rows of Aliens, 10 per row, mercilessly bombing
you.
You get 1,000 points for each full wave you destroy, but you've
only got three lives, and each new wave starts lower and comes
faster.
The mothership appears randomly, taunting you with her song,
but if you can hit her, she's worth up to 300 points.
With a choice of either joysticks or keyboard, the game should
provide hours of enjoyment, and a chance to admire the wonders
of BBC Basic and Teletext Mode 7.
The program is written almost entirely in "straight"
Basic, with the exception of the bomb routines, which for the
sake of speed, use the BBC "?" peeks and pokes.
Before discussing the details of the program, let's consider
Mode 7. The program runs in less than 10,000 bytes and that includes
the graphics.
Although the shapes are limited and chunky, they are very likeable,
much in the same vein as the Ceefax and Oracle screens on TV.
In simple terms, to the Basic interpreter the shapes are no
more than concatenated (joined together) characters, printed in
the same way as the normal Ascii set — ABC, etc.
The difference is achieved by use of the control codes - see
Figure I.
|
Decimal
|
Hex |
producing
|
|
145
|
&91 |
red
|
|
146
|
&92
|
green
|
|
147
|
&93
|
yellow
|
|
148
|
&94
|
blue
|
|
149
|
&95
|
magenta |
|
150
|
&96
|
cyan |
| 151 |
&97
|
white |
Figure I
The code must be printed before the required shape - but on the
same line -using the CHR$( ) instruction, or alternatively, using
the VDU instruction. For example:
PRINTCHR$(&91)
VDU145
will both provide for red graphics on the rest of the line.
Each line of print requires its own control code - try Program
I:
10MODE7:FOR A=2 TO 24 STEP 2
20PRINT TAB(0,A)CHR*(&91)
30NEXT
40FOR A=1 TO 24
50PRINTTAB(A,A)"x{xt"
60NEXT
Program I
As you can see, the first loop places the control code in alternate
lines, resulting in a mothership (borrowed from the game) on one
line and gobbledygook on the next.
What about gobbledygook? Can we use it selectively? The answer
is yes, and is explained in Table I.
Table I
In the User Guide (page 155) the "six cell" graphics
characters are explained as Ascii values. I use the table, which
provides both a quick look-up method and an easier line to enter.
The User Guide would have you calculate and enter:
PRINT CHR$(&91); CHR$(248); CHR$(251); CHR$(247); CHR$(244)
or:
VDU 145,248,251,247,244
to print a mothership, but by the table method:
PRINTCHR$(&91)"x{wt"
is all that is required.
The table is used by printing a graphic control code (&91-&97)
followed by the character which represents the required cell,
in quotes.
Alternatively, if you have OS 1.2, you can use the CTRL plus
FUNCTION keys procedure.
By depressing CTRL+F1, for example, red graphics characters
can be entered directly, enabling you to develop your Mode 7 graphics
in real time.
Note that all six cells filled requires its own PRINT or VDU
statement - PRINTCHR$(255) or VDU255 - copied into
a function key as defined below.
For fun, set function key FO as below, and by using the CTRL
key to move the cursor position:
CTRL+H = 1 space left
CTRL+I = 1 space right
CTRL+J = 1 line down (40 spaces)
CTRL+K = 1 line up (40 spaces)
and the keyboard with the caps lock off, you can create simple
pictures and line drawings.
The F0 setting gives red graphics on all lines except line 0.
Use CTRL+H, CTRL+F1 for line 0. You can change colours by using
CTRL plus FUNCTION keys as you wish, but you must not overwrite
character 0 of each line, nor any of your colour change characters.
I doubt if Mode 7 will turn you into a computer Picasso, but
it's all in the best possible taste!
Function key F0
*KEY0 CLS:F.A=0 TO 23: VDU145,10,8:N.: F.A=0 TO 23: VDU11:N.¦M
Incidentally, to fill all six cells, you can enter direct VDU
255.
This will simply print a block. You then set the block into
a normal function key - *KEY 1 - then copy the block and press
Return.
Now function key 1 will display the block whenever pressed.
You must remember that the alphabet is lower case to print graphics.
The upper case alphabet is printed as normal in the selected colour.
Finally, in preparation for the real McCoy, try Program II.
It is a demonstration of how to animate your characters. The program
displays the mothership, as she quietly drifts to rest at the
bottom of your screen.
Her movement is controlled by the FOR-NEXT loop, but is made
clear and realistic by printing the space characters before moving
the ship and by using the REPEAT-UNTIL, to slow it down.
If you really want to see the BBC Basic moving, delete line
50.
10 MODE7:VDU 23;8202;0;0;0;
20 FOR A=2 TO 18
30 B=B+RND(2)
40 PRINT TAB(B,A)CHR$(&91)'x{wt"
50 TIME=0:REPEAT UNTIL TIME=100
60 IF A=17 END ELSE PRINT TAB(B,A)""
70 NEXT
Program II
Although it looks lengthy, the Basic is fairly well structured
with a few REMs and space lines.
For clarity, wherever possible the lines have been kept short
and you should find that you will soon have the program keyed
in and working.
Or, for those who prefer to let the machine do the work, you
could send for the Micro User cassette and obtain a completely
keyed and debugged version (see Page 137).
For the sake of speed, the program uses the % variables A to
Z (yes, all of them), which in some instances saves up to 50 per
cent of the time it takes an ordinary variable. A list of their
uses is supplied.
The program is entered from RUN, and uses lines 10 to 180 to
set up the working environment:
Lines 10-40 define the ENVELOPES.
Line 50 uses the ON ERROR routine to return the keyboard
to normal and print the error number and line (ERR ERL). refer
line.
Line 60 *TV 255 drops the display 1 line — improves the
display on most TVs.
Line 70 sets mode and switches off the cursor.
Line 80-90 set up all the arrays and displays the titles.
Line 100 sets up the "Hall of Fame".
Lines 110-150 sets the values of the variables - note that
the % variables must be set to zero even from run, as their values
are not set by MOS (Machine Operating System). Return to line
80 from "Another Game" prompt ensures that the values
are correctly maintained. Lines
160-170 set the top lines of print (lives left, scores).
Line 180 set time and branch to the main loop.
The Main Loop - line 2000
To be absolutely correct, the main loop does not begin until
line 2090, the intermediate lines being used from start and from
each cleared screen to set up the battle scenario.
I let the machine do the donkey work in lines 1530 to 1930,
using FOR NEXT loops to create the rows of aliens and bases.
As you can see, the string variables A$ to E$ are preset with
the necessary gobbledygook in preparation for the magic control
codes.
All processing is by PROCEDURE, apart from the main REPEAT UNTIL
loop itself, which performs the routines and marches the invading
hordes across your screen.
Before beginning the loop, the invaders are printed by lines
2000 to 2050 which display the aliens without the timing delays
within the loop.
Note that for efficiency and thus to increase speed the more
aliens you shoot, only non-space filled rows of aliens are printed
and this is achieved by A% to E% counting your kills.
The REPEAT UNTIL variables, T% to W%, are set up during PROC-DIRECT,
and must take account of the columns shot out. This is achieved
by use of the variables GL%, SGL%, MM% and NN%. The result is
the rather complex looking formula at line 2330.
Now a description of the procedures:
PROCDIRECT. Sets up the REPEAT UNTIL variables T% to W%.
The TT% array helps to ensure that only living aliens are displayed.
The values of T%, V% and W% are modified during the main loop
to take account of fully destroyed columns.
Incidentally, the *3 in the formula is the two-character alien
plus its space character. Also the values of 20 and 21 are used
to restrict space line prints to a minimum.
PROCLINE1 to PROCLINE 5. Actual print of the aliens.
They are held in the string arrays A$ to E$ and are concatenated
into AP$ to EP$ by the FOR NEXT loops which use MM% and NN% for
the left and right hand columns.
This ensures that the well used technique of shooting out the
end columns is catered for.
Note again that for the sake of efficiency the concatenation
is only carried out if any aliens in that row have been shot -
AA% to EE% are the indicators.
PROCMOVE. Normal laser movement, achieved by either ADVAL
if K% is set from PROCTITLE or the negative INKEY. The negative
INKEY is the most efficient and responsive method of key detection
and is highly suited to games programming.
Note that F% is checked for bullets in motion (F%>0) before
shoot detection, allowing for the COPY key or shoot button to
remain depressed without slowing down the game.
Also the laser has a space character each side, providing smooth
movement in one PRINTTAB instruction.
PROCSHOOT. First in a series of nested procedures, PROCSHOOT
sets your laser bolt into action. Once fired, the laser is disabled
by F% until you hit something or go out of range (line 0 on the
screen). F% is the column position of the laser and thus the bullet.
PROCHIT. Moves the bullet up one line. Performs PROCBOMB
in fairness to the aliens.
PROCHITA. Checks for a hit. Uses FNHIT to look at the
correct screen position - not TUBE compatible. Four checks are
involved:
1 - Hit your own base. Screen location value of either 255,
50, 120, 116, or 97.
2 - Hit a bomb. Screen location value 124.
3 - Hit the mothership - line value of 1 and screen location
value < > 0 or 32 (space). In this case Perform PROCMHIT.
4 - Last < > 0 or 32 - hit an alien. Needless to say,
perform PROC-SCORE.
PROCMHIT. Hit the mothership. Plays a fanfare and gives
a random score. Perhaps you might add a delay at this point to
show more clearly the score value.
PROCSCORE. No guesses, looks after your score. Actually,
it does a fair bit more. Logically, perhaps the most complex routine.
By using DIV and MOD it looks after the rows and columns of
aliens - A$ to E$, A% to E% for the rows; B4% (1 to 10) for the
columns.
It also checks a count of the aliens shot and gives you your
"Cleared Screen" award. A little fanfare (perhaps the
Close Encounters theme) would go nicely here. I'll leave it to
you.
PROCMSHIP. Moves the mothership by time delay. The more
purist of you might wish to make her appearance even more random.
As it is, she appears sometime after 10 seconds since she last
got shot or disappeared - but from which side?
PROCBOMBS. This routine and its subsequent performs will
kill you, well it does drop the aliens bombs!
By setting L% to the start position of the highest row of aliens
at the beginning (L% = HIMEM + (2+Z%) * 40) we have the base location
for bomb dropping.
HIMEM is the first screen location in this mode.
Z% is the start height depending on screens cleared.
(2+Z%) * 40 gives the address of the first column of the highest
line of aliens.
By using this method, we can direct and lower the bombs using
the minimum of time-consuming arithmetic :
1. Random choice of one or two bombers.
2. Check A$ to E$ position to make sure an alien exists.
3. Add the correct screen location values; 80 characters for
each line of aliens plus the following line of spaces.
4. Poke - or to be precise ?B2%(J%) = 97 — which means print
a bomb below the chosen alien. Note that PROCLOWER uses the formula
described in PROCBOMBS to check for a hit and blank out bomb and
lower bomb one line.
PROCBOMBED removes a life and, if necessary, ends the
game.
PROCTITLE is the first routine performed, prints the introduction
and checks for joysticks. Note the interesting use of RIGHT$ to
display the title.
PROCFAME of course, sets up your rank by FOR NEXT loops.
Overall, the flow of the program is governed by the way the
main procedures are performed.
This potentially allows much scope for experiment — changing
the frequency of the performs will change the responses and movement
of the various characters.
For the adventurous, the laser bullets routines could be changed
to use PEEKs and POKEs or even assembler routines - the assembler
equivalent of ? is only a STA to a specified address.
I've described the program in detail in a hope that it may be
helpful by providing an insight into games programming.
The Mode 7 graphics prove to be more than useful and the techniques
used in Invaders could equally well be used in Galaxian, Centipede
- even Gorf type games.
In the meantime, I wish you luck. Get keying, and enjoy yourself.
Variables Used
A% = Count of aliens shot - top line
B% = Count of aliens shot - second line
C% = Count of aliens shot - third line
D% = Count of aliens shot - fourth line
E% = Count of aliens shot - fifth line
F% = Position of base for bullets (column)
G% = Position of bullets (row)
H% = Height of aliens 1% = General loop count
J% = General loop - specifically used in random routines and small
loops
K% = Joysticks
L% = Screen position in map terms
M% = General loop
N% = Position in base - movement routines
O% = FNHIT calculation - column
P% = FNHIT calculation - row
Q% = Mothership movement (direction +1-1)
R% = Used to define which alien characters are printed
S% = Mothership markers
T%, U%, V%, W% = Main loop counts - defines direction of aliens
- TT% array helps.
X% = Result of FNHIT (=FNHIT) - checks for bullet hits
Y% = High score
Z% = Lower position of aliens after clearing screen
MM% = Start of alien string count - increases the prints per line
as the columns are cleared (left hand side)
NN% = End of alien string count - used as
MM% from right hand side
LI% = Used as go to variables in SCORE - defines which alien was
hit
AA% to EE% = Indicators for changes to alien lines
A$ to E$ = Alien lines
AP$ to EP$ = Concatenated alien lines
B4% (1 to 10)= Alien column counts
F3 = Result of row calculation - which alien was hit?
GL%, SGL%= Additional variables used to continue the leftward
movement of the aliens if complete columns have been destroyed.