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