Budding game creators rejoice! Michael Gledhill's got just the thing to spruce up your playing power.
As an ex-BASIC programmer, I envied machine coders on one main asset: sprites. Try as I might, I just couldn't match the speed of my sprites with theirs, BASIC routines just weren't fast enough!
On learning machine code, I started work on a new sprite making system. Welcome to the Spritemaker.
The clearest way to demonstrate it's power is with an example. The listing below will compile, then display a sprite of a face in PENs 1 and 2 on a PEN 0 background, in mode 1. See if you can work out what the face will look like by looking at the DATA.
10 DATA 00111111100
20 DATA 01111111110
30 DATA 11221112211
40 DATA 11221112211
50 DATA 11111111111
60 DATA 11221112211
70 DATA 11122222111
80 DATA 01111111110
90 DATA 00111111100
100 MODE 1
120 |COMPLETE, 10,90
130 LOCATE 13,10
140 |SPRITE, 1
No addresses are needed, and absolutely no machine coding knowledge.
You don't even need to say how big the sprite is! Let's take a closer look at that program.
First, there's the sprite data, lines 10 to 90. You'll notice that the DATA in lines 10,20,80 and 90 have zeros at the start and end of them. This is important. All of the DATA lines for a particular sprite must be the same length. Of course, if you wanted to compile another sprite with a different width, it's fine, as long as all of that sprite's data lines are also the SAME length. Asprite can be any width or height up to 255 pixels (which wouldn't fit on a BASIC line anyway).
Line 110 has one purpose, to retrieve as much memory as possible. When you run a program, any sprites previously compiled will still linger in memory, so |CLEAR should be used to get rid of them.
Line 120 compiles the sprite. You cannot display a sprite until it's BASIC data has been converted into machine code data. As you can see, the COMPILE command is very simple to use - you just tell the command the first and last line of BASIC DATA which you've used to represent the sprite data.
Once the sprite data has been compiled, the sprite is given a number. Now, we have just |CLEARed any lingering sprites from memory, so this is the first sprite, sprite number 1.
Finally, line 140 displays the sprite. The "1" tells the |SPRITE command to display sprite number 1, and this is displayed at the cursor position, hence the LOCATE command in line 130. Incidentally, once you have |COMPILEd a sprite, it can be displayed using |SPRITE as many times as you like without needing to recompile it (unless, of course, you use the |CLEAR command).
I've always believed that the best way to learn a new topic is to learn by experiment, so go ahead. Change line 100 to compile the sprite in a different MODE. Try filling the screen with the face. Try changing the 10 in line 120 to a 20, or the 90 to 70. Try compiling a sprite in one mode and displaying it in a different mode. Is it displayed normally? Now, we'll go on to meet some new commands and get the low-down on the ones we've already met. The Spritemaker consists of seven bar commands (RSXs): |COMPILE, |SPRITE, |SPRITEP, |JAM, |IMPORT, |CLEAR, |STORE. Let's take a look at each of these separately.
|COMPILE, first line of data, last line of data
You've already seen the speed and power of this command in the example above. You can have up to 128 compiled sprites in memory at once, although normally you'll run out of memory before you can compile that many!
Note: When your sprites are converted into machine code, the sprite data which is produced is dependent on the MODE you are in when the sprite is compiled. So if you compile a four coloured sprite in MODE 1 and display it in MODE 0, it will look corrupted. You'll need to obey a few rules when using |COMPILE:
- All lines for a sprite MUST be the same length. In the listing above, lines 10,20,80 and 90 are 'padded'with 0s. Remember that spaces at the end of a BASIC DATA line will alter that DATA line's length, even though it will look the same length as the others.
- All lines between the specified 'first data line' and 'last data line' must consist of just BASIC DATA
- Try adding 35 REM Hello to the program above, then run it.
Although the parameters you put on the end of the |COMPILE command (the 10 and 50 in |COMPILE, 10,50) represent line numbers, BASIC does not and cannot be told this, so if you renumber your program using RE-NUM, the |COMPILE parameters will not be changed.
- You can use any of the 16 pens available in MODE 0 by using the numbers 0 to 9 for pens 0 to 9 and the uppercase letters A to F for pens 10 to 15.
No sprite data is written into memory until your DATA lines have been checked, and the sprite will only be compiled if there's enough space for it.
|SPRITE, sprite number
This command will display a compiled sprite on the screen at the cursor position, which as you know, you alter using BASIC'' LOCATE command. This is where the sprite number comes in.
Don't worry about 'wrap-around'; for example, displaying a 60 pixel wide sprite at the righthand column of the screen where there's only room to display 8 pixels, as the sprite is automatically cut off at the bottom and righthand edges.
|SPRITEP, sprite number
This command will do the same as |SPRITE, but will not display pixels that are in pen 0. This gets rid of the annoying rectangular border around the sprites, so that, in theory, games like Head over Heels can be written in BASIC.
|JAM, jam code
This tells the |SPRITE command how to display a sprite - on top of or merged with the background (|SPRITE only).
Jam codes: 0 for JAM, 1 for XOR, 2 for AND, 3 for OR.
There is also an extra feature in that you can ask sprites to be printed BEHIND what's already on the screen (|SPRITEP only).
Jam codes: 4 for display ON TOP, 5 for display BEHIND
This will retrieve as much of the workspace as possible, by erasing all sprites and BASIC variables.
You are strongly advised to put |CLEAR at the start of any programs that |COMPILES sprites as existing sprites are not erased when you rerun a program.
|STORE, sprite number
Once again, an example will clarify the function of this command. Add the following lines to the program above.
100' Make sure you run this in MODE 1
125 'Sprite number 2 will store the sprite data
135 ' Sprite number 2 will store the background
140 ' which gets overwritten when sprite 1 is displayed
150 WHILE INKEY$=""
180 LOCATE X,Y
210 FOR a=1 TO 30:NEXT
One popular method of using sprites in games is to allow a sprite to appear to pass over scenery, so that when the sprite is removed, the part of the scenery it was printed on gets redisplayed. This is done in three simple steps:
- Store" what's on the screen at the sprite position intitially
- Print the sprite at the sprite position
- Restore what was at the sprite position initially
This should help to explain why the sprite is compiled twice in this program and what |STORE is used for.
The area in memory devoted to sprite number 1 actually stores the sprite data, whilst the memory used to store sprite number 2 stores the area of screen where a sprite is about to appear.
As our sprite is 11 pixels by 9 pixels, this is the number of pixels that the |STORE command will copy from the screen into memory. These 99 pixels are stored just like a |COMPILEd sprite, so can be redisplayed using the |SPRITE command.
This command was suggested by David Gibbon of County Durham. He suggested that BASIC programmers could get machine code sprite data from loading in screens saved from art packages. Who was I to argue ? To use |IMPORT, you need to draw your sprite in the TOP-LEFTHAND corner of the screen, save it normally, return to BASIC, then use a program like the following:
10 INPUT"Filename ",a$
20 INPUT"Mode ",b
30 MODE b
40 LOAD "!"+a$,&C000
The command calculates the size by looking for the bottom righthand corner of the sprite, so if you had just one pixel in the bottom righthand corner of the screen, then the command will assume the WHOLE SCREEN is the sprite (and probably result in an error due to the sprite's enormous size!).
From there, the sprite is read in, and to all extents, it's treated like a |COMPILEd sprite.
Make sure that the rest of the screen which you draw the sprite on is set to pen 0.
To save your valuable memory, the Spritemaker errors appear as simply "Error no. X". Note that a BASIC program will not stop when the Spritemaker error is printed, so you'll need to press ESCape when you see one!
The error codes are as follows:
Error no.0 - You've left off a variable (|COMPILE,30)
Error no.1 - "First data line" doesn't exist
Error no.2 - "Last data line" doesn't exist
Error no.3 - One of the data lines too long/short
Error no.4 - A non-DATA line found Error no.5 - Not enough workspace for sprite
Error no.6 - All 128 sprites in use Error no.7 - Sprite has been overwritten
Error no.8 - The screen is clear ! (|IMPORT)
Typing in the Spritemaker program
When you run the program, assuming all DATA lines are correct, the BASIC program and a binary version will be saved. To load back the Spritemaker code and set up the RSXs you need only type:
MEMORY &7FFF:LOAD"SM.BIN",&9000:CALL &9000
If anyone writes a cracking program with the Spritemaker send it into ACU, remembering to conform to a few rules, to keep the members of the ACU staff sane (or as close as is surgically possible).
- Make sure that your program starts off with the lines below to ensure the Spritemaker is loaded once and only once and that SM.BIN is either on the same disc or following the main program file on tape.
10 IF PEEK(&9000) -&AF THEN GOTO 30
20 MEMORY &7FFF:LOAD"SM.BIN",&9000:CALL &9000
30 REM Rest of program.
- If you're going to send in a sprite-based program, try not to have masses of BASIC DATA for sprites, be considerate to the readers who will have to sit and type them all in.
That's basically all you need to know. BASIC programmers, try to save your programs a little more often, as Amstrad BASIC doesn't really like taking second place to a set of RSXs.
Spritemaker v2.4 may also see the light eventually, so if you have any ideas for extra RSXs, send them in. I am always open for suggestions, death
threats, blind dates, or just a plain old chat at the following address: Michael Gledhill 21 Newtake Road Whitchurch Tavistock Devon PL199BX
Enclose a SAE if you're expecting anything resembling a reply.
A Spritemaking Demo
This example program will demonstrate the power of the jam codes 4 and 5 by making a sprite move in front of, and behind two identical shapes.
BASIC programmers notice that the CALL &BD19, as briefly described in the CPC manual can be used to prevent sprite movement from being jerky.
10 MODE 1-.BORDER 0:INK 1,26 20 INK 0,0:INK 2,6:INK 3,11
60 DATA 000001111100000
70 DATA 001111010111100
80 DATA 011110010011110
90 DATA 111111111111111
100 DATA 113311111113311
110 DATA 111333333333111
120 DATA 111130000003111
130 DATA 011113022031110
140 DATA 001111322031100
150 DATA 000011133030000
160 DATA 000000011330000
170 FOR n=0 TO 100 STEP 2
180 PLOT 222,250:DRAW 172+n,150,3
190 PLOT 364,250:DRAW 314+n,150
200 NEXT n
210 FOR n=0 TO 20 STEP 2
220 PLOT 212+n,150:DRAWR 0,20,0
230 PLOT 354+n,150:DRAWR 0,20
240 NEXT n
250 LOCATE 11,17:PRINT "INFRONT"
260 LOCATE 21,17:PRINT"BEHIND"
270 FOR n=1 TO 40
280 LOCATE n,13
290 IF n300 |STORE,2:|SPRITEP,1
310 FOR p=0 TO 3:CALL &BD19:NEXT p
330 NEXT n
340 IF INKEY$="" THEN 270
For the machine coders
The Spritemaker is, quite frankly, the most unrelocatable thing I've ever done, mainly so that as much speed can be squeezed out as possible.
Don't try and relocate it, it won't work!
Obviously one of the main assets in a program like this is to be able to use BASIC to design sprites and the Spritemaker to compile this BASIC data into machine code data which can be used to your own programs.
To incorporate sprite data, you'll need to know where to find a sprite's data, and how many bytes it uses.
The sprites are stored as blocks consecutively downwards from &8EFF, each block directly below the next.
Each block is stored in the following format:
Byte 0: Width of sprite Byte 1: Height of sprite
Byte 2: &12
Bytes 3 - ???? Sprite data
The &12 is there for the |SPRITE and |SPRITEP commands, so they can check whether the sprite has been corrupted - if &12 isn't at byte 2 then the sprite is corrupted - display Error no.7.
The program uses a table of addresses (from &8F0 to &8FFF) to store the locations of the blocks, allowing sprites to be referred to as a simple number, rather than an address. So the address of the block storing sprite 1 is stored at &8F00/ 1, the block for sprite 2 at &8F02/3 and so on.
From there saving sprites should be a doddle. You know where the sprites are stored, how they're stored, and can work out their size by multiplying the sprite's width by it's height.
The following BASIC program might help you if you're lost. Enter the sprite number and the rest is doneforyou. Note then &909C stores the number of sprites complied (0-128).
10 INPUT "Sprite number";a
30 IF a>0 AND a<=b THEN 50
40 PRINT "Sprite doesn't exist.":END
60 spaddr=PEEK(tbl)+256*PEEK (tbl+1)
70 PRINT "Sprite stored at";
80 PRINT HEX$(spaddr)
90 wid=PEEK(spaddr) 'WID -Width
100 hgt=PEEK(spaddr+l) 'HGT= Height
110 siz=wid*hgt 'SIZ - Sprite size
130 if chk=&12 THEN 150
140 PRINT"SPRITE CORRUPTED.":END
150 PRINT"SAVE":CHR$(34);" FILENAME";
160 PRINT CHR$(34);",B,&";
170 PRINT HEX$(spaddr+3)","siz
Once sprites are compiled, there is no reason why BASIC doesn't just overwrite the whole lot of them. To prevent this you need to set MEMORY to just below the location of the sprite data lowest in memory. This can be achieved using the following three lines, which make use of |COMPILE's optional third parameter, which returns the address which the sprite is compiled to into an integer variable.
|COMPILE, 10, 50, @A% MEMORY %a-1
This is especially important before loading or saving to tape or disc as this uses a 2K buffer.
|★ AMSTRAD CPC ★ DOWNLOAD ★|
|★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...|
|QUE DIT LA LOI FRANÇAISE:|
L'alinéa 8 de l'article L122-5 du Code de la propriété intellectuelle explique que « Lorsque l'œuvre a été divulguée, l'auteur ne peut interdire la reproduction d'une œuvre et sa représentation effectuées à des fins de conservation ou destinées à préserver les conditions de sa consultation à des fins de recherche ou détudes privées par des particuliers, dans les locaux de l'établissement et sur des terminaux dédiés par des bibliothèques accessibles au public, par des musées ou par des services d'archives, sous réserve que ceux-ci ne recherchent aucun avantage économique ou commercial ». Pas de problème donc pour nous!
CPCrulez[Content Management System] v8.7-desktop/cache
Page créée en 120 millisecondes et consultée 968 fois
L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.