Classic Computer Magazine Archive COMPUTE! ISSUE 86 / JULY 1987 / PAGE 74

Zookeeper For The Amiga

Michael Barron

Data for object images is stored in individual files—which can quickly lead to an unmanageable directory. This utility provides a solution—programs not only initialize faster, but they are also easier to handle.

The object commands in Microsoft Amiga BASIC, which allow you to manipulate sprites, vsprites, and bobs, provide easy access to some of the Amiga's most powerful animation routines. However, you must store the data for each object image in its own, separate file. Thus, if your program uses six objects, you'll have to manage seven separate disk files (six object files, plus the program itself). Before long, your previously-neat disk directory can start looking like a zoo.

"Zookeeper" offers a neat solution to this problem by converting image definition files into DATA statements which can be part of the main program. The DATA lines are organized into meaningful sections with commentary, bringing order to the object zoo.

Defining objects under program control does make the program itself somewhat larger. But the advantages of this method definitely outweight the drawbacks. Only one file need be duplicated when exchanging the program with a friend, and a printed listing of the program shows everything needed to make it run properly. The program also initializes faster, since it simply READs DATA statements already in memory, rather than seeking and loading separate files on disk. And, finally, it eliminates the problems that can occur when a program is not able to load the necessary object files.

Using The Zookeeper

Type in Program 1 and save a copy. The Zookeeper can handle object definition files for both sprites and bobs, in the format produced by the object editor program on the Amiga BASIC Extras disk. Let's demonstrate how it works using an example image file from the Extras disk.

In the BASICDemos drawer of the Extras disk is an image definition file named ball. Copy that file onto the same disk (and directory, if applicable) where you saved the Zookeeper program.

Run Zookeeper and enter the appropriate filename at the prompt. The program then asks you to enter the maximum number of data elements for each DATA statement (eight is a good number). With this information, Zookeeper creates a text file consisting of commented DATA statements. The DATA lines contain the same information as the image definition file. This new file has the same filename as the one which you entered earlier, with the filename extension .ZOO. Thus, if you are converting the image file named ball, the new file is named ball.ZOO.

When the .ZOO file has been created, the Zookeeper program gives you the option to delete the original image definition file. Do not delete anything at this point.

Demonstration

After you have created the ball .ZOO file, type in Program 2. This program will show you how easy it is to use the new image format. After you type in all the lines listed in Program 2, enter this command in the BASIC Output window:

MERGE "ball.ZOO"

The effect of this command is to merge the DATA lines from the ball.ZOO file with Program 2, which is already in memory. The DATA lines appear at the end of the current program.

Before you run the combined program, look at the subroutine named initPlayer, near the end of Program 2. That routine sets a variable named ByteCount, which is used to indicate how many items to read from the DATA statments. If you examine the comments at the beginning of the ball.ZOO data, you will see a comment indicating how many bytes this particular set of DATA lines contains.

Since we knew in advance that ball.ZOO would create 106 bytes of data, we were able to use that number in the statement from initPlayer which sets ByteCount. For any other image, however, that value will be different. When using these routines to display your own objects, you will need to examine the comment at the beginning of the DATA lines and modify the statement in InitPlayer to match the number shown.

When you run the demonstration, notice how much faster the program begins. Not having to access the disk drive is a great advantage. Another advantage is easy accessibility to the image data itself. To see what we mean, find the twenty-second DATA number in the ball.ZOO data set, change that number from 24 to 48, and then rerun the program.

For instructions on entering these programs, please refer to "COMPUTE!'s Guide to Typing In Programs" elsewhere in this issue.

Program 1: Zookeeper

' ZooKeeper
' Convert image definition files to DATA statements
' Copyright 1987 COMPUTE! Publications, Inc.
' All rights reserved.
PRINT"Copyright 1987" : PRINT"Compute! Publications, Inc."
PRINT"All Rights Reserved." : FOR X = 1 TO 2000 : NEXT X
CLS
MainLine :
GOSUB HouseKeeping
GOSUB ParameterEntry
GOSUB DefineFieLds
IF NoErrors THEN
GOSUB CreateZooFiLe
GOSUB FiLeMaintenance
END IF
GOSUB EndJob
END
HouseKeeping :
DEFINT a-z
WINDOW 1, "The ZooKeeper", (0, 56)-(500, 186), 15
TRUE = -1
FALSE = 0
HeaderBytes = 26
CoLorMapBytes = 6
RETURN
ParameterEntry :
PRINT
INPUT "Enter name of AmigaBASIC object file : ", FiLename$
INPUT "Enter maximum number of data elements per statement : ", Ma xBytes
PRINT
RETURN
DefineFieLds :
PRINT "Input file : "; FiLename$
OPEN FiLename$ FOR INPUT AS 1
Image$ = INPUT$ (LOF(l), 1)
CLOSE 1
Depth& = CVL(MID$(Image$, 9, 4))
Wide& = CVL(MID$(Image$, 13, 4))
Height& = CVL(MID$(Image$, 17, 4))
Flags = CVI(MID$(Image$, 21, 2))
BytesPerRow = 2 * INT((Wide& + 15)/l6)
BytesPerPlane = BytesPerRow * Heigh t&
BytesInBitmap = BytesPerPlane * Dep th&
IF Flags AND 1 THEN
ObjectIsSprite = TRUE
ReqBytes = HeaderBytes + BytesInBit map + CoLorMapBytes
ELSE
ObjectIsSprite = FALSE
ReqBytes = HeaderBytes + BytesInBit map
END IF
IF LEN(Image$) < > ReqBytes THEN
PRINT FiLename$;" is not compatible with the ZooKeeper."
NoErrors = FALSE
ELSE
NoErrors = TRUE
END IF
RETURN
CreateZooFiLe :
PRINT "Output file : "; FiLename$; ".ZOO"
PRINT
PRINT "Please wait…"
PRINT
OPEN FiLename$ + ".ZOO" FOR OUTPUT AS 1
PRINT # 1,
PRINT # 1, "ObjectData : "
IF ObjectIsSprite THEN
PRINT #1, "' SPRITE Format"
ELSE
PRINT #1, "' BOB Format"
END IF
PRINT # 1, "' Total Bytes : ";Req Bytes
PRINT # 1, "' Bit Planes : "; Depth&
PRINT # 1, "' Pixels Wide : "; Wide&
PRINT # 1, "' Pixels Tall : "; Height&
CurrentByte = 1
Comment$ = "' Object Header"
CALL FormatData(Comment$, MID$(ImageS, CurrentByte, HeaderBytes), MaxBytes, 1)
CurrentByte = CurrentByte + HeaderBytes
FOR PLane = 1 TO Depth&,
Comment$ = "’ BitPlane " + STR$(PLane)
CALL FormatData(Comment$, MID$(Image$, CurrentByte, BytesPerPlane), MaxBytes, 1)
CurrentByte = CurrentByte + BytesPerPlane
NEXT PLane
IF ObjectIsSprite THEN
Comment$ = "' Sprite Color Map"
CALL FormatData(Comment$, MID$(Image$, CurrentByte, CoLorMapBytes), MaxBytes, 1)
END IF
CLOSE 1
RETURN
FiLeMaintenance :
PRINT "Shall I delete "; FiLename $;" (y/n)";
INPUT Response$
IF UCASE$(Response$) = "Y" THEN
KILL FiLename$
PRINT FiLename$;" deleted."
END IF
PRINT
RETURN
EndJob :
PRINT "Job complete : returning to AmigaBASIC."
PRINT
RETURN
SUB FormatData(Note$, Dat$, DatLim it, FiLeNo) STATIC
PRINT # FiLeNo, Note$
NoBytes = LEN(Dat$)
NoFuLLLines = INT(NoBytes/DatLimit)
CurrentByte = 1
FOR LineOut = 1 TO NoFuLLLines
CALL PrintDataLine(MID$(Dat$, CurrentByte, DatLimit), FiLeNo)
CurrentByte = CurrentByte + DatLimit
NEXT LineOut
IF CurrentByte< = NoBytes THEN
BytesLeft = NoBytes-CurrentByte + 1
CALL PrintDataLine(MID$(Dat$, CurrentByte, BytesLeft), FiLeNo)
END IF
END SUB
SUB PrintDataLine(Dat$, FiLeNo) STATIC
NoBytes = LEN(Dat$)
PRINT # FiLeNo, USING " DATA ###";ASC(MID$(Dat$, 1, 1));
FOR ELement = 2 TO NoBytes
PRINT # FiLeNo, USING " _, ###";ASC(MID$(Dat$, ELement, 1));
NEXT ELement
PRINT # FiLeNO,
END SUB

Program 2 : Demonstration

' Zookeeper demonstration
' Copyright 1987 COMPUTE! Publications, Inc.
' All rights reserved
PRINT"Copyright 1987" : PRINT"Compute! Publications, Inc."
PRINT"A11 Rights Reserved." : FOR X = 1 TO 2000 : NEXT X
CLS
MainLine :
GOSUB HouseKeeping
GOSUB InitPLayer
WHILE INKEY$ = ""
IF MOUSE(0) < > 0 THEN
OBJECT. X 1, MOUSE(l)
OBJECT. Y 1, MOUSE (2)
END IF
WEND
END
HouseKeeping :
DEFINT a-z
WINDOW 1, "Ball Demo", (0, 136)-(450, 186), 15
PRINT "Manipulate object with mouse."
PRINT "Hit any key to exit."
RETURN
InitPLayer :
ByteCount = 106
Image$ = ""
FOR Loop = 1 TO ByteCount
READ ImageData
Image$ = Image$ + CHR$(ImageData)
NEXT Loop
OBJECT.SHAPE 1, Image$
OBJECT.ON
RETURN