Programming Techniques 04: Using Basic

By Dominic Ford

Originally published in EUG #39

In EUG #38, I described how screen memory is laid out, and how this knowledge can be of use to the programmer. The problem is that this is all of little use in BASIC - your program would crawl along if it tried to display graphics by directly accessing screen memory from BASIC. The only technique which is of use if you don't know machine code is that of using *LOAD and *SAVE to reload a previous screen memory display.

This doesn't mean, however, that it is impossible for BASIC programmers to make use of screen memory techniques. The only part of your program which has to be in machine code is the part which accesses screen memory - the rest can be in BASIC. Let's say, for example, that you are writing a game which requires a sprite to move across the screen. The part pf the program that physically plots the sprite into screen memory must be in machine code to be able to achieve reasonable speed. But the part of the program which manipulates the sprite, keeps track of your score, checks if you're walking into an enemy sprite, etc. can all be done in BASIC.

This means that if BASIC programmers could have a module of machine code which does the screen memory access for them, and which they can call every time they want to display a sprite on the screen, they too could make use of this powerful technique. That is exactly what I'm providing in this issue of EUG - a small machine code module which BASIC programmers can use to plot multi-coloured sprites onto the screen. There are even a couple of sample demonstrations to show how the module can be put to use.

Obviously such a system does have some limitations - where machine code programmers can devise a specialist module for the particular needs of their program, this module does force the user into following certain rules in their program. The main limitations are:

  • Your program must operate in MODE 2 when the module is being used to produce the graphics.
  • Your sprites must consist of blocks of 8x8 pixels (one character), although larger sprites can be used simply by tiling several one character sprites together, side by side.
  • Your program must not make use of memory locations above &2C00. This does put quite a severe size limit on your program on an ADFS system. If you receive "No Room" error messages when you try to use your program, you've hit that limit!
  • You must not use conventional VDU23 style user-defined characters in your program, because this module uses the same workspace as these.

Before you can use the module, you must design some sprites for it to display. This is done using the program "U.MLTIUDG" which can be loaded from the Utilities Menu. If you don't want to get artistic at this stage of trying out the module, there are a couple of files of sample sprites included with this editor: "B+B" are those used by the bat and ball demo and "U.WALKSPR" are those used by the "walking demonstration". For the moment I will assume that you are using these sample sprite files - more details on how to create your own sprite files using the editor program will be given later.

To use the sprites in your program, you must use the program "U.UDGMOD" on this issue of EUG as a starting point. This program consists of a couple of lines at the beginning that set up your computer to use the module, by entering Mode 2, and assembling the machine code module into memory. Then there is the assembly language of the module itself which comes after the body of your program. Your program should be inserted between the line:

      REM Put your program code here!
and the line:
      END
Apart from adding your program code, there is one other alteration which you need to make, and that is to insert the filename of sprite file I mentioned earlier into line 1020. You should replace the string <Filename> in quotes at the end of line 1020 with the relevant filename. For the moment use "B+B" - this will enable you to use the sprites used in the Bat and Ball demonstration.

Whenever you want to display a sprite in your program, you need to set a number of variables and then call the module. These variables must be set with integer values in the ranges given:

?char ... The number of the sprite you want to draw (0-31)
?xc ... The x position of the sprite in characters (0-19) Use just like TAB(?xc,?yc)
?yc ... The y position of the sprite in characters (0-31)
?xoff ... The offset of the x position from the left edge of the character position given, in pixels (0-3). This enables you to smoothly move your sprite from one character to another.
?yoff ... The offset of the y position from the top edge of the character position given (0-7).

Having set these four variables, execute CALLdisplay to display your sprite.

As an example, we can try this now. Load up a copy of "U.UDGMOD" and replace the filename in line 1020 with "B+B" as described earlier. Now enter the following line:

       30 ?char=2:?xc=1:?yc=1:?xoff=2:?yoff=4:CALLdisplay
Run the program, and a block will appear at the top left of the screen. The top left of the block is in character square (1,1) and with offsets of half a character both horizontally and vertically.

The SetPaint(col) function

You may remember that a couple of issues back I mentioned how the GCOL command in BASIC can be used to set how graphics are drawn onto the screen. For example, the pixels could be set to the colours defined in your sprites regardless of their previous state. They could also have the light from the pixels mixed with the light from your sprite. This would mean, for example, that if a green sprite were plotted onto a blue background, the result would be cyan. This effect can also be achieved using this graphics module, using the SetPaint procedure:

PROCSetPaint(x)
Where: x = Parameter giving the type of painting you want to do.

0:Your sprite will replace any previous colours on the screen.
1:Your sprite will be used as a filter put over the light already on the screen.
2:Your sprite will be mixed with the light already on the screen.
3:EOR (described later)

The default setting is 0. The other paint modes obviously have applications if you want to be able to see several sprites on top of each other by mixing the light from them, or if you only want to see a sprite when it is in a certain area of the screen. But the EOR mode also has another very important use:

Suppose you want to create a moving sprite. Say, for example, the ball in the Bat & Ball demonstration. If you just draw the sprite over and over again slowly moving across the screen you will get a trail of all of the old displays of the sprite behind your latest display. This is because these are not being removed before the new image is being drawn. Let's say our sprite has moved left from square 10 to square 9.

Initially you would have drawn the sprite in square 10. Then when the sprite moves into square 9, you would draw it again in its new position in square 9. The result is that your sprites is now visible in both squares 9 and 10 - you need to remove the image from square 10.

You could do this by allocating one of your program's 32 sprites as a black square. But what happens if your sprite is in front of a complex backdrop? If you start putting black blocks in front of that, you'll get in a mess. The problem is illustrated by the "Walking" Demonstration which is available from the Utilities Menu.

The answer to this problem is to use the "EOR" paint style. This is very useful, as it is a reversible way of displaying a sprite. Simply display your sprite for a second time in exactly the same location and it will disappear. This can easily be demonstrated using the following steps:

  1. Load up a fresh copy of "U.UDGMOD"
  2. Change the filename in 1020 to "B+B"
  3. Add the following lines:
  4.     30 PROCSetPaint(3)
        40 ?char=0:?xoff=0:?yoff=0:?xc=2:?yc=2:CALLdisplay
        50 REPEAT UNTIL INKEY(-99)
        60 CALLdisplay
    
Run this program, and a ball will appear at the top-left of the screen. Press SPACE and it will disappear. The program works as follows:

 30...Sets EOR paint style
40...Displays sprite no. 0 using the EOR style at co-ordinates (2,2)
50...Wait for SPACE
60...Display same sprite again using EOR at (2,2)

You can see more of how to use the User-Defined Characters module by studying the examples available on the Utilities Menu. All have REM statements to tell you what is happening, except the Bat & Ball Demo, which is longer and has a program description available in separate documents.

Now that you know how to use sprites created by the Editor in your programs, you will probably want to create your own sets of sprites. Firstly you must load up the Editor program from the Utilities Menu or by typing CH."U.MLTIUDG"

Using the Editor program

The keys used to control the editor are shown below the sprite design box. Initially, the editor contains a file of 32 blank sprites, each of which are 8x8 pixels. You can design your sprites by moving a cursor around the sprite design box with the following keys:

Z - Left   X - Right   * - Up   / - Down

You can set the colour of a pixel in your sprite using the following keys:

A - Black
B - Red
C - Green
D - Yellow
E - Blue
F - Purple
G - Cyan
H - White

To move from one sprite definition to another, use the keys +/-. If you want to jump to a sprite whose number is a long way from the sprite you are currently editing, it would be very time consuming to use the +/- keys and watch the editor go through every sprite until you reach the one you want. The keys 0-9 are used to jump quickly from one sprite to another. These keys are set up as follows:

0 -Jump to sprite 0.
1 -Jump to sprite 3.
2 -Jump to sprite 6.
3 -Jump to sprite 9.
4 -Jump to sprite 12.
5 -Jump to sprite 15.
6 -Jump to sprite 18.
7 -Jump to sprite 21.
8 -Jump to sprite 24.
9 -Jump to sprite 27.

When you have finished designing your sprites, you need to save them to a sprite file. This is done by pressing S and typing the filename you want to save under. Should you want to continue editing a previously saved set of sprites at a later date, you can do so by pressing L and entering the filename of the sprite file you want to load.

Dominic Ford, EUG #39