11: HARDWARE SPRITES One of the biggest attractions of the Commodore Amiga is its ability to produce high quality games which rivial those found on genuine arcade machines. This can be amply demonstrated by terrific programs such as Battle Squadron and Eliminator. Now, for the first time, all these amazing features are at your fingertips! AMOS Basic provides you with complete control over the Amiga's hardware and software sprites. These sprites can be effortlessly manoeuvred with the built-in AMAL animation language, so you don't have to be a machine code wizard in order to create your own stunning arcade games. Hardware sprites are searate images which can be automatically overlayed on the Amiga's screen. The classic example of a hardware sprite is the mouse pointer. This is completely independent of the screen, and works equally well in all the Amiga's graphics modes. Since sprites don't interfere with the screen background, they are perfect for the moving objects required by an arcade game. Not only are they blindingly fast, but they also take up very little memory. So when you're writing an arcade game, hardware sprites should always be at the top of your list. Each sprite is 16 pixews wise and up to 255 pixels high. The Amiga's hardware supports a maximum of eight three-colour sprites or four fifteen-colour sprites. Colour number zero is transparent - that's the reason for the odd colour ranges. At first glance, these features don't seem particulary impressive. But there are a couple of useful tricks which can increase both the numbers and sizes of these sprites beyond recognition. One solution is to take each hardware sprite and split it into a number of horizontal segments. These segments can be independently positioned, allowing you to apparently display dozens of sprites on the screen at once. Similarly, the width restriction can be exceeded by building an object out of several individual sprites. Using this technique it's easy to generate objects up to 128 pixels wide. Until recently the only way to exploit these techniques was to delve into the mysterious wolrd of 68000 assembler language. So you'll be delighted to discover that AMOS Basic manages the entire process automatically! Once you've designed your sprites with the AMOS sprite editor, you can effortlessly manipulate them with just a single Basic instruction. The sprite commands =================== Remember to have a sprite bank loaded into memory when trying out the various commands in this chapter. We advise you use the file SPRITES.ABK from the AMOS data disc. SPRITE (display a hardware sprite on the screen) SPRITE n,x,y,i The SPRITE command displays a hardware sprite on the screen at coordinates x,y using image number i. n is the identification number of the sprite and can range from 0 to 63. Each sprite can be associated with a separate image from the sprite bank, so the same image can be used for several sprites. x and y hold the position of the sprite using special hardware 146 coordinates. All measurements are taken from the *hot spot* of your images. This serves as a sort of 'handle' on the sprite and is used as a reference point for the coordinates. Normally the hot spot is set to the top left hand corner of an image. However it can be changed within your program using the HOT SPOT command. Hardware coordinates are independent of the screen mode and effectively start from (-129,-45) on the default screen. AMOS provides you with several built-in functions for conversions between hardware coordinates and the easier to use screen coordinates. See the X HARD, Y HARD, X SCREEN and Y SCREEN functions for more details. i is the number of a particular image stored in the sprite bank. This bank can be created using the AMOS sprite editor, and is automatically saved along with your Basic program. It can also be loaded directly with the LOAD instruction. In addition you can use the GET SPRITE command to grab an image straight off the current screen. Any of these parameters x,y and i may be optionally omitted, but the appropriate commas must be included. For example: Load "AMOS_DATA:Sprites/Octopus.abk" Sprite 8,200,100,1 Sprite 8,,150,1 Sprite 8,300,, For a demonstration of sprites in action, load EXAMPLE 11.1 from the MANUAL folder on the AMOS data disc. Computed sprites ================ Although the Amiga only provides you with eight actual sprites, it's possible to use them to display up to 64 different objects on the screen at once. These objects are known as -computed sprites- and are managed antirely by AMOS Basic. Computed sprites can be assigned by calling the SPRITE command with a number greater than 7. For example, Load "AMOS_DATA:Sprites/Octopus.abk" Sprite 8,200,100,1 The size of a computed sprite is taken directly from the image data, and can vary between 16 and 128 pixels wide, and from 1 to 255 pixels high. Before you can make full use of these sprites you need to understand some of the principles behind them. Each hardware sprite consists of a thin narrow strip 16 pixels wide and 256 pixels deep. Depending on the number of colours, you can have either eight or four of these strips on the screen at a time. It should be obvious that most of the area inside these sprites is 147 effectively wasted. That's because few programs need sprites which are taller than about 40 or 64 pixels. However there is a simple trick which enables us to borrow this space to generate dozens of extra objects on the screen. Look at the picture AMOS1.PIC (included in this manual file packet) which contains the letters A,M,O and S. < picture AMOS1.PIC > This sprite can be split into four horizontal segments each enclosing a single letter. The Amiga's hardware allows each section to be freely positioned anywhere on the current line, making a total of four computed sprites. Here's a diagram which illustrates this process. < picture AMOS2.PIC > 148 As you can see, a computed sprite is really just a small part of a hardware sprite displayed at a different horizontal screen position. Notice the line between each object. This is an unavoidable side effect of the repositioning process, and is generated by the Amiga's hardware. Due to the way computed sprites are produced, there are a couple of restrictions to their use. Firstly, you can't have more than 8 computed sprites on a single line. In practice the system is complicated by the need to produce sprites which are larger than the 16 pixel maximum. AMOS generates these objects by automatically positioning several computed sprites side by side. This can be seen from the diagram below: < picture AMOS3.PIC > The maximum of eight hardware sprites therefore imposes a strict limit to the number of such objects you can display on a horizontal line. The total width of the objects must not exceed: 16*8=128 pixels for three-colour sprites 149 16*4=64 pixels for fifteen-colour sprites If you attempt to ignore limitation, you won't get an error message, but your computer sprite will not be displayed on the screen. So it's vital to ensure that the above restriction is never broken. This can be achieved using the following procedure: Add together the widths of all your computed sprites, multiplying the dimensios of any fifteen-colour sprites by two. If the total is greater than 128, you'll need to space your sprites on the screen so that their combined width lies below this value. Take particular care if you are animating your sprites with AMAL as certain combinations will only come to light after you've experimented with the sequence for some time. These problems will be manifested by the random disappearance of one or more sprites on the screen. If the worst comes to the worst, you'll need to substitute some of your larger sprites with Blitter Objects. This will increase the overall size of your program significantly, but it should have a negligible effect on the final quality of your game. These restrictions are not confined to AMOS Basic of course. They apply equally well to all games on the Amiga, even if they're written entirely in machine code! So there's nothing stopping you from producing your own Xenon II clone using exactly the same tehcniques. Note that, normally, hardware sprite number zero is allocated to the mouse cursor. You can release this sprite with a simple call to the HIDE command. See EXAMPLE 11.2. Creating an individual hardware sprite ====================================== The only real problem with computed sprites is that you never know precisely which hardware sprite is going to be used in a particular object. Normally the hardware sprites used in an object will change whenever the object is moved. Occasionally this can be inconvenient, especially when you are animating objects such as missiles which need to remain visible in a wide range of possible sprite combinations. In these circumstances it's useful to be able to allocate a hardware sprite directly. Individual hardware sprites can be assigned using the SPRITE instruction with an identification number between 0 and 7. Example: Sprite 1,100,100,2 This loads a hardware sprite number 1 with image number 2. N now corresponds to the number of a single hardware sprite, and can range between 0 and 7. If your image is larger than sixteen pixels wide, AMOS will automatically grab the required sprites in consecutive order starting from the sprite you have chosen. For example: Sprite 2,200,100,1 Supposing image number 1 contained a 32-bit image with three colours. This command would allocate hardware spries 2 and 3 to the image. Nothing would happen if you were now to attempt to display hardware sprite 3 with a command like SPRITE 3,150,100,1 because this sprite has already been used. You would only have access to sprites 0,1,4,5,6 and 7, and the maximum numbers and sizes of your computed sprites would be reduced accordingly. Each 15-colour sprite is implemented using a pair of two three-colour 150 sprites. However, it's not possible to combinea ny two sprites in this way. Only the combinations 0/1,2/3,4/5,6/7 are allowed. One side effect of this, is that you should always assign your hardware sprites using even sprite numbers. Otherwise, AMOS will start your sprite from the next group of two, effectively wasting the first sprite. Also note that if you try to create a large fifteen-colour sprite with this system, you could easily use up all the available sprites in a single object. WARNING! If you are writing a screen scrolling game, you may encounter problems using sprites in conjunction with the SCREEN OFFSET and SCREEN DISPLAY commands. These generate a DMA clash between the sprite system and the screen bit-maps, and can occasionally lead to unwanted screen effects. This problem is only relevant if you are using hardware sprites 6/7. When the screen is shifted to the left with SCREEN OFFSET, the amount of time for your sprite updates is reduced, as the screen DMA has priority over the sprite system. Unfortunately, there isn't enough processing time to draw sprites 6/7, and they will therefore be corrupted on your display. To clear up this problem, create sprites 6/7 as individual hardware sprites and position them off the screen using negative coordinates. This will stop AMOS Basic from using them in your computed sprites. Providing sprites 6/7 are never displayed on the screen during your scrolling operations, all will be well. The sprite palette ================== The colours required by a hardware sprite are stored in the colour registers 16 to 31. Providing your current screen mode doesn't make use of these registers, the sprite colours will be completely separate from your screen colours. Interestingly enough, this is also the case for the 4096-colour Ham mode. So there's nothing stopping you from producing some mind-blowing Ham games with this system! However you will encounter real problems when using 32 or 64 colour screen in conjunction with three colour sprites. This is because the colours used by these sprites are grouped together in the following way: Hardware sprites Colour registers ---------------- ---------------- 0 / 1 17 / 18 / 19 2 / 3 21 / 22 / 23 4 / 5 25 / 26 / 27 6 / 7 29 / 30 / 31 Colour registers 16,20,24 and 28 are treated as transparent. The difficulty arises due to the way AMOS generates computed sprites. The hardware sprites used to produce these objects vary during the course of a game, so it's vital to ensure that the three colours used by each individual sprite are set to exactly the same values, otherwise the colours of your computed sprites will change unpredictably. Here's a small AMOS procedure which will perform the entire process for you 151 automatically. Procedure INIT_SPRITES Get Sprite Palette For S=0 To 3 For C=0 To 2 Colour S*4+C+17,Colour(C) Next C Next S Endproc The above restriction does not, of course, apply to fifteen-colour sprites. If you want to make the most of the Extra Half Bright or 32-colour modes, you may find it easier to avoid using four-colour sprites altogether. GET SPRITE PALETTE (grab sprite colours into screen) GET SPRITE PALETTE [mask] This loads the entire colour palette used for your sprite images into the current screen. The optional "mask" allows you to load just a selection of the colours from the sprite palette. Each of the 32 colours is represented by a single bit in the mask, numbered from right to left. The rightmost bit represents the status of colour zero, the next vit colour 1, and so on. To load a colour simply set the appropriate bit to 1. If, for instance, you wanted to copy just the first four colours, you would set the bit pattern to: Get Sprite Palette %0000000000001111 Identically, since bobs use the same sprite bank as sprites, this command can also be used to load the colours of a bob. Controlling sprites =================== SET SPRITE BUFFER (set height of the hardware sprites) SET SPRITE BUFFER n This sets the work area in which AMOS creates the images of the hardware sprits. Acceptable values for n range from 16 to 256. TO set the correct value for n, simply examine the sprites in the sprite editor and work out which is the largest sprite length wise. ANy sprite that is larger than "n" will simply be truncated at the appropriate cut off point. SET SPRITE BUFFER is supplied for your use so that you can claim back any redundant memory our game or application simply doesn't use. The amount of memory consumed by the sprite buffer can be calculated using the formula: Memory = N*4*8*3 = N*96 So the minimum buffer size is 1536 bytes and the maximum is 24k. Note: This command erases all current sprite assignments and resets the mouse cursor to its original state. SPRITE OFF (remove one or more 152 sprites from the screen) SPRITE OFF [n] The SPRITE OFF command removes one or more sprites from the screen. All current sprite movements are aborted. In order to restart them, you'll need to completely reinitialize your movement pattern. SPRITE OFF Removes all the sprites from display SPRITE OFF n Only deactivates sprite number n Note that your sprites are automatically deactivated whenever you call up the AMOS Basic editor. They will be automatically returned to their original positions the next time you enter direct mode. SPRITE UPDATE (control sprite movements) SPRITE UPDATE [ON/OFF] The SPRITE UPDATE command provides you with total control of the movements of your sprites. Normally, whenever you move a sprite, its position is updated automatically during the next vertical blank period (see WAIT VBL). But if you are moving a lot of sprites using the SPRITE command, the updates will occur before all the sprites have been moved. This may result in a noticeable jump in yur movement patterns. In these circumstances, you can turn off the automatic updating system with the SPRITE UPDATE OFF command. Once your sprites have been succesfully moved, you can then slide them smoothly into place with a call to SPRITE UPDATE. This will reposition any sprites which have moved since your last update. =X SPRITE (get x coordinate of a sprite) x=X SPRITE(n) Returns the current x coordinate of sprite n, measured the hardware system. This command allows you to quickly check whether a sprite has passed of the edge of the Amiga's screen. =Y SPRITE (get y coordinate of a sprite) 153 y=Y SPRITE(n) Y SPRITE returns a sprite's vertical position. As usual, n refers to the number of the sprite and can range from 0 to 63. Remember, all sprite positions are measured in hardware coordinates. See EXAMPLE 11.3 GET SPRITE (load a section of the screen into the sprite bank) GET SPRITE [s,] i,x1,y1 TO x2,y2 This instruction enables you to grab images directly off the screen and turn them into sprites. The coordinates x1,y1 and x2,y2 define a rectangular area to be captured into the sprite bank. Normally all images are taken from the current screen. However it's also possible to grab the image from a specific screen using the optional screen number "s". Note: There are no limitations to the region that may be grabbed in this way. Providing your coordinates lie inside the existing screen borders, everything will be fine. i denotes the number of the new image. If there is no existing sprite with this number, a new image will be created automatically. AMOS wlil also take the trouble of reserving the sprite bank if it hasn't been previously defined. See EXAMPLE 11.4 There's also an equivalent GET BOB instruction which is identical to GET SPRITE in every respect. Since the sprite bank is shared by both bobs and sprites, the images are in exactly the same format. So it's perfectly acceptable to use both instructions in conjunction with either bobs or sprites. Try changing the sprite instruction in the previous example to something like: Bob 1,0,0,1 Conversion functions ==================== =X SCREEN (convert hardware coordinates =Y SCREEN into screen coordinates) x=X SCREEN([n,] xcoord) y=Y SCREEN([n,] ycoord) Transforms a hardware coordinate into a screen cordinate relative to the current screen. If the hardware coordinates lie outside the screen then both functions will return relative offsets from the screens boundaries. Type the following from direct mode: Print X Screen(130) The result will be -2. This is because the x screen coordinate 0 is equal to hardware coordinate 128 and thus the conversion of 130 to a screen coordinate results in a position two pixels to the left of the screen. If the optional screen number is included then the coordinates will be returned relative to screen # n. =X HARD (convert screen coordinates 154 =Y HARD into hardware coordinates) X=X HARD ([n,] xcoord) These functions convert a screen coordinate into a hardware coordinate. There are four separate conversion functions, the above syntaz converts xcoord from a coordinate relative to the current screen to a hardware coordinate. Y=Y HARD ([n,] ycoord) Transforms a Y coordinate relative to the current screen into hardware coordinate. As before, n specififes a screen number for use with the functions. All coordinates will now be returned relative to this screen. =I SPRITE (return current image of a sprite) Image=I SPRITE(n) This function returns the current image number being used by sprite n. A value of zero will be reported if the sprite is not displayed.