In this Chapter, you will learn how to turn moving objects into truly interactive game components, by giving them friendly or hostile personalities. These personalities depend on what happens when two or more objects collide, and all of the classic computer games demand continual monitoring for collision between moving objects. Collision detection must be instant, accurate and totally reliable, otherwise games will lack excitement and playability.
AMOS Professional provides a comprehensive range of functions that allow perfect monitoring for collisions between objects on screen: Bobs, Hardware Sprites, Computed Sprites or any combination of these different types. The detection routines are sensitive to the actual shape of your objects, so all results are incredibly accurate. There is not a single "classic" computer game that you cannot match in terms of speed and sensitivity when it comes to detecting collisions. Here is a synopsis of the options available.
AMOS Professional permits effortless checking for a collision between any group of screen objects, by means of four powerful functions. Each function uses the same principle, which takes a single source object and then searches for collisions between that object and one or more targets. If the test is successful and a collision is detected, a value of -1 is returned, meaning True. On the other hand, if there is no collision, a value of 0 is given, meaning False.
As a default, the collision functions will test all relevant active objects for collision with the single object that you are interested in, but if you want to restrict your test to a selection of active objects, each function can be qualified with an optional setting for the range of targets. This range is set by specifying the number of the first object in the range to the number of the last target object you are interested in.
BOB COL monitors for collisions between Bobs.
SPRITE COL monitors for collisions between Sprites.
SPRITEBOB COL checks a single Sprite for collisions with Bobs.
BOBSPRITE COL tests a single Bob for collisions with Sprites.
After a collision has been detected by one of those tests, you can make an immediate check for the other objects involved, using a collision function named COL, which is used like this:
collision=Col(number)
where the number relates to one of the objects being checked.
Most of these options are also available in the built-in AMAL animation system, to which Chapter 7.6 is devoted.
There are three general categories of collision which can occur in a computer game:
Before a detailed explanation of the collision functions, it is worth examining AMOS Professional in action with a ready-made program. This will demonstrate how collisions are handled.
Please load the following tutorial:
Load "AMOSPro Tutorial:Tutorials/Collision_Detection.AMOS"
Now run the program and select Example 1. This shows how a simple bat and ball are made to interact, and to simplify things, the bat has been fixed in position! The collision detection in this example relies on the following line:
If Bob Col(1) Then Boom
Notice how the explosion effect is triggered the instant that the bat overlaps the ball, even by the smallest margin. Example 2 really sets the ball rolling!
The same instruction can also be used to detect collisions between a single source and any number of target objects, with the BOB COL function checking all of the Bobs automatically in Example 3.
To refine the system, and check for collisions with a smaller range of objects, simply add the first and last numbers of that range to the BOBSPRITE COL command, in the demonstration program. For example, changing the relevant line as follows will test for one red and one green ball only:
If Bobsprite 001(1,2 To 4) Then Bell 10
Invisible "masks" are created around images for two main reasons. Firstly they ensure that the background colour (zero) is transparent, so a masked Bob will merge with the current screen display. The second reason for masking an image is to provide AMOS Professional with a mechanism for detecting collisions. The collision detection functions will only work if a mask has first been created around the required images.
Masks are automatically defined around an image when that image is assigned to a Blitter Object, in other words, when the BOB command is used. But it is important to remember that Sprites have no masks unless you specifically attach them. So if you intend to make use of collision detection, it is vital to ensure that all your objects are wearing their masks.
instruction: mask an image for collision detection
Make Mask
Make Mask number
This command creates a mask around every one of the images in the Object Bank, and may take
a little time, depending on the number of objects involved. If an optional number is given, then a mask is created for that specified image only.
function: detect for collision between Blitter Objects
c=Bob Col(number)
c=Bob Col(number, first To last)
The BOB COL function checks the screen for collisions between Blitter Objects. It is invaluable in the type of arcade games that rely on hitting or avoiding moving objects. To test for a collision with BOB COL, simply specify the number of the Bob you are interested in (in brackets) and a value of -1 (true) will be returned if a collision occurs. Otherwise zero (false) is generated.
Note that the AMOS Professional collision system uses "masks", and so it is sensitive to the physical shape of your objects. This means that when different objects have extremely varied appearances, the collision will only be detected when the objects happen to overlap on screen.
Normally, BOB COL will check for collisions between the specified Bob and any other Blitter Object, but you can also monitor the movements of a particular range of Bobs using this As optional parameters, after the specified Bob number, you may set the range of Bobs to be checked for collision from the first to the last in your Bob list.
BOB COL is very similar to the BC function used by the AMAL animation system. AMAL is detailed at the end of this section, in Chapter 7.6. For a rapid status test of an individual Bob, after a collision detection routine, the COL function can be used to determine precisely which pair of objects have collided amongst a whole range of similar objects. The COL function is explained later.
function: test for collision between Sprites
c=Sprite Col(number)
c=Sprite Col(number,start To finish)
SPRITE COL provides an easy method of checking to see if two or more Sprites have collided on screen. If the test is successful, SPRITE COL returns a value of -1 (true), and if not 0 (false) is returned instead. As you would expect, the brackets contain the number of any active Sprite on screen. This can be a standard Amiga hardware Sprite, or an AMOS Professional computed Sprite, but the image it displays must carry a mask. As a default, masks are created for Bobs only, so you must deliberately create a mask for each Sprite image at the start of your program, using MAKE MASK.
If you want to check for a selected group of Sprites, include the optional first to last parameters to set the range of the Sprite numbers you are interested in.
Note that any mixture of hardware Sprites and computed Sprites can be tested in the same SPRITE COL instruction. Also that the equivalent AMAL function is SC.
function: test for collision between one Sprite and range of Bobs
c=Spritebob Col(number)
c=Spritebob Col(number,start To finish)
As its name suggests, this function checks for a collision between the Sprite whose number you specify, and one or more Blitter Objects. If the Sprite collides with a Bob, a value of -1 (true) is returned, otherwise 0 (false) is given.
This function will test for collisions with all Bobs on screen, but the checking process can be restricted with the optional setting of the range of Bobs to be monitored, from the first Bob number to the last in the range. If you need to test for collisions between several Sprites and Bobs, the command should be enclosed in a loop, like this:
For FIRSTSPRITE=1 To LASTSPRITE
If Spritebob Col(FIRSTSPRITE,FIRSTBOB To LASTBOB) Then Boom
Next FIRSTSPRITE
Remember that all specified Sprites must be assigned to a masked image, before collision detection can work. You are also warned that this function will only work with low resolution screens, and attempts to use it in high resolution will lead to unpredictable results. This is because your Sprites and Bobs are likely to have different sized screen points.
function: test for collision between one Bob and range of Sprites
c=Bobsprite Col(number)
c=Bobsprite Col(number,first To last)
This function checks for a collision between the single Bob whose number you specify, and all active Sprites on screen. The result will be -1 (true) is a collision is detected, or 0 (false) if the object remains untouched. To narrow the range of Sprites to be monitored, simply include the first to the last number in that range. As with SPRITEBOB COL, this function should only be used in low resolution.
function: test status of an object after collision detection
status=Col(number)
One obvious problem with all of the previous detection functions is that they only report on whether an individual object has been hit. To discover information about any other objects involved in a collision, the COL function is used. This means that each object can be tested on its own, to see if it has collided with the source object.
Give the number of the object you wish to test, either a Bob or a Sprite, depending on the circumstances, and its status will be reported with a value of -1 (true) if it has collided, or 0 (false) if it remains untouched.
Supposing you are testing Bob 1 for a collision between Bobs 2,3 and 4. The initial test could look like this:
C=Bob Col(1,2 To 4)
Alter the collision has been detected, you can check on the other objects using the COL I unction, as follows:
For B=2 To 4
If Col(B) Then Print "You have hit Bob number ";B
Next B
A faster version of this function allows instant monitoring for the second object in the collision, like this:
object=Col(-1)
This returns the number of the object which has collided with your target, or a zero if no collision has happened. So the alternative version to the last example is:
object=Col(-1)
The AMAL equivalent of this function is C, and both are perfect for detecting collisions between individual "hostiles" and "friendlies". You simply check for a collision between each object with a BOB COL or SPRITE COL, then grab the number of the collision object with the COL function.
instruction: set hardware register for hardware Sprite collision detection
Set Hardcol bitmap1 ,bitmap2
This command is available to experienced Amiga programmers, and it permits Sprite collision detection using the computer's hardware. SET HARDCOL cannot be used with computed Sprites, so only Sprites zero to 7 may be monitored for collision.
The CLXCON register is set for hardware Sprite collision detection using two parameters. Bitmap1 is an enabler, that sets bits 12,13,14 and 15 of the CLXON register, and bitmap2 determines the comparison itself, setting bits zero to 5. Please refer to your hardware manual for a technical explanation of this register.
function: return collision status after a Set Hardcol instruction
c=Hardcol
Once the hardware register has been set with a SET HARDCOL command, the HARDCOL function can be used to read the system register CLXDAT, returning zero (False) if there is no collision, or -1 (True) if a collision is detected. The COL function can then be used to return the identification number of the colliding Sprite.
The last part of this Chapter explains how rapid checks can be made to see if an Object has entered a rectangular area of the screen. These screen "zones" can be used for collision detection in computer games, as well as for setting up buttons, control panels and dialogue boxes.
instruction: RESERVE memory for a detection zone
Reserve Zone
Reserve Zone number
The RESERVE ZONE instruction must be used to allocate enough memory for the exact number of zones required, before a SET ZONE command is given. There is no limit to the number that can be specified, apart from the amount of available memory.
To erase all current zone definitions and restore the allocated memory to the main program, simply give the RESERVE ZONE command without any number parameter.
instruction: set a screen zone for testing
Set Zone number,x1 ,y1 To x2,y2
After memory has been allocated with the RESERVE ZONE command, SET ZONE is used to define a rectangular area of the screen which can be tested by the various ZONE functions. The command is followed by the number of the new zone, followed by its coordinates from top left to bottom right-hand corner.
function: return the zone number under specified screen coordinates
number=Zone(x,y)
number=Zone(screen number,x,y)
The ZONE function is used to give the number of the screen zone at the specified screen coordinates x,y. These coordinates are normally relative to the current screen, but an optional screen number can be included before the coordinates.
After the ZONE function has been called, the number of the first zone at these coordinates will be returned, or a value of zero (False) will be given if no zone is detected.
This function can be used with the X BOB and Y BOB functions to detect whether or not a Bob has entered a specific screen zone, as follows:
N=Zone(X Bob(n),Y Bob(n))
function: return the zone number under the specified hardware coordinates
number=Hzone(x,y)
number=Hzone(screen number,x,y)
The HZONE function is identical to ZONE, except for the fact that the position on screen is measured in hardware coordinates. This means that this function can be used to detect the presence of a hardware Sprite in one of the screen zones, in this format:
N=Hzone(X Sprite(n),Y Sprite(n))
function: test if mouse pointer has entered a zone
number=Mouse Zone
This is a short reminder that the MOUSE ZONE function is used to check whether the mouse pointer has entered a zone, as outlined in Chapter 5.8.
instruction: erase screen zone
Reset Zone
Reset Zone number
This command is used to nullify a zone created by the SET ZONE instruction. On its own, RESET ZONE permanently de-activates all zone settings, but if it is qualified by a zone number, only that zone will be erased. The RESET ZONE instruction does not return the memory allocated by RESERVE ZONE to the main program.