(© Richard Ashbery)
For some years now I've been experimenting with BASIC to create simple graphic animations and needed a method to produce GIF images to be uploaded to a website.
Many many years ago (1988 to be precise) Acorn Computers Ltd. published the BBC BASIC GUIDE. This has been updated and re-issued by RISC OS Open Ltd in 2017. The original guide illustrated a method using a VDU command to create a group of sprites from an animated shape. Although simple to understand it required quite a few operations in order to create the sprites.
An improved method which communicates directly with the operating system through an SWI command SYS "OS_SpriteOp" is more powerful and flexible and should be used instead. The following tutorial describes the 2 methods with a simple animated rotating square (figure 1).
Please note: Tutorial only covers creation of a sprite group. A GIF suitable for web pages can be built with InterGif but the process it is not covered in this tutorial.
Fig 1 Rotating Square
Examine the program below...
MODE 1920,1080,32 : OFF
ORIGIN 1920,1080
n=0
REM Set up rotation variable for square
FOR m=0 TO 2*PI-PI/12 STEP PI/12
GCOL 3,63 : PROCdraw_square
z=INKEY(10)
REM Generate sprite group for animation
MOVE-200,-200
MOVE 200,200
VDU 23,27,1,n|
n+=1
REM Erase previous square after a delay
GCOL 3,63 : PROCdraw_square
NEXT m
END
DEF PROCdraw_square
FOR T = 0 TO 2*PI STEP PI/2
X=SIN(T+m)*200
Y=COS(T+m)*200
IF T=0 THEN MOVE X,Y ELSE DRAW X,Y
NEXT T
ENDPROC
The highlighted section in red performs the sprite group saving routine. The rotation of the square is controlled by a FOR-NEXT statement with the code inserted in the body of the program such that 'n' would be advanced a step at a time. For each rotation (n=n+1) a sprite is created. To generate the sprite group...
There are some quite serious limitations:
Important Note: Above method deprecated in favour of the following...
The recommended technique of creating an animated sprite is to use SYS "OS_SpriteOp". It appears more complicated but is much more flexible and fully automated. No additional commands need typing into a TaskWindow and no dragging of the Next slot in Tasks is required.
The basic form of the SWI command is shown in table below...
Function | SWI command |
Initialise sprite | SYS "OS_SpriteOp", &009,, |
Create sprite group | SYS "OS_SpriteOp", &00E,, STR$(n) Note 2 |
Save sprite to current working dir. Note 1 | SYS "OS_SpriteOp", &00C,, "MyFileName" |
Important: These basic SpriteOp codes use the 'System Sprites' memory which is
limited to 16MB.
The program below uses a 'User Sprite Area' instead of the 'System Sprites' memory. This is important as it enables the user to set sprite area memory much greater than 16MB. By simply adding &100 to the Reason code in all three SWI commands enables this action to be performed.
Function | SWI command |
Initialise sprite | SYS "OS_SpriteOp", &109,sprite_area% |
Create sprite group | SYS "OS_SpriteOp", &10E,sprite_area%, STR$(n) Note 2 |
Save sprite to CWD Note 1 | SYS "OS_SpriteOp", &10C,sprite_area%, "MyFilename" |
These statements are coloured green in the program. Sandwitched between them are 2 lines (highlighted in black) that automatically set the amount of memory required for the sprite processing in the Next slot in the Task Manager.
Without these 2 lines creating the required animated sprite would require additional memory that would normally be assigned by dragging the Next slot to give a value greater than sprite_area_size%. With the example shown where sprite_area_size% = 4000K then to be on the safe side Next slot should be dragged to say 5000K. By including another 2 lines this process can be done automatically.
Line 3 (calculate the memory shortfall)
shortfall% = (sprite_area_size% + &19000) - (HIMEM - END)
The variable, shortfall% calculates how much extra memory is needed. BASIC requires about 100Kbytes (&19000) free to work in so this is added to sprite_area_size%.
sprite_area_size% + 102K = 4194K+102K = 4296K
Memory currently free in BASIC = HIMEM-END = 4255Kbytes
shortfall% = (sprite_area_size% + 102K) - (HIMEM - END) = 4296-4255K = 41K
Line 4 (calculate HIMEM+shortfall creating the equivalent of dragging Next slot)
IF shortfall% > 0 THEN END = HIMEM + shortfall%
With HIMEM at 4292K...
HIMEM + shortfall% = 4292+41 = 4333. This figure is then used to set the program's slot in the Task Manager using the BASIC keyword... END.
sprite_area_size% = 4
sprite_area_size% = sprite_area_size% * 1024 * 1024
shortfall% = (sprite_area_size% + &19000) - (HIMEM - END)
IF shortfall% > 0 THEN END = HIMEM + shortfall%
DIM sprite_area% (sprite_area_size% - 1)
sprite_area%!0 = sprite_area_size%
sprite_area%!8 = 16
SYS "OS_SpriteOp", &109, sprite_area% : REM start initialisation
MODE 1920,1080,32 : OFF
ORIGIN 1920,1080
n=0
REM Set up rotation variable for square
FOR m=0 TO 2*PI-PI/12 STEP PI/12
GCOL 3,63 : PROCdraw_square
z=INKEY(10)
REM Generate sprite group for animation
MOVE-200,-200
MOVE 200,200
SYS "OS_SpriteOp", &10E, sprite_area%, STR$(n) : REM Create sprite group
n+=1
REM Erase previous square after a delay
GCOL 3,63 : PROCdraw_square
NEXT m
SYS "OS_SpriteOp", &10C, sprite_area%, "MyFilename" : REM Save sprite group to disc
END
DEF PROCdraw_square
FOR T = 0 TO 2*PI STEP PI/2
X=SIN(T+m)*200
Y=COS(T+m)*200
IF T=0 THEN MOVE X,Y ELSE DRAW X,Y
NEXT T
ENDPROC
1. Current working directory = CWD. If the sprite requires saving to a specified directory then a full path to the directory must be given.
2. The STR$ keyword changes sprite group names to a string rather than just a numerical value.
A big thanks to Steve Fryatt for submitting various mini-tutorials describing how to implement these BASIC procedures. I hope I've understood the mechanics correctly. A steep learning curve but a very useful exercise and because program is fully automated makes process of creating animated sprites considerably easier.
©Richard Ashbery (18/4/20)