Crafting Black Hole Graphics on the ZX81

Exploring swirling graphics as we adapt contemporary code for the ZX81.

I had forgotten about this Black Hole program until I ran across it while cleaning up some directories. It is a conversion, not an original, program that was shared on one of my BASIC forums. It doesn’t look quite as good as the original, but it was interesting to see what the ZX81 could do with its simplistic graphics.

# Having some BASIC fun.

“Black Hole,” by Dusty W. Murray, intrigued me because it already produced black and white output. Although, in the original version, the background is black. It creates a simple swirling pattern that resembles a black hole, and generated quite a lot of participation on the group at the time.

My first attempt, however, was not for the ZX81. I decided to try this in Daryl Dudey's Daric BASIC first, and it worked well.

Black Hole, Daric Screenshot, 2023 by Steven ReidBlack Hole, Daric Screenshot, 2023 by Steven Reid

Here is the Daric BASIC code for those interested. I added the range command, and the images look much nicer! This version will generate images until you press q.

rem **Black Hole**by Dusty W. Murray**
rem **Converted to Daric by Steven Reid, 3/19/2023**
Def Range:float(v:Float, minimal:Float, maximal:Float)
if v<minimal then v = minimal
if v>maximal then v = maximal
return v
End Def
Mode 800,600,Windowed
SetBg 0, 0, 8
SetFg 255,255,255
w = ScreenWidth()
h = ScreenHeight()
mw = int(w/2)
mh = int(h/2)
mr = mw * 2
ads = 0.005
rds = 0.5
r = 5.0
rd = 0.0
a = 0.0
ad = ads
For t = 0 To 1999*31
ch = Rnd(5)
if ch = 0 then rd = rds
if ch = 1 then rd = -rds * 0.991
if ch = 2 then ad = ads
if ch = 3 then ad = -ads
r = r + rd
r = Range(r, 10, mr)
a = a + ad
if a<0 then a=a+2*pi
if a>2*pi then a=a-2*pi
ar = r / 50
x= int (Sin(a+ar)*r) + mw
y= int (Cos(a+ar)*r) + mh
Plot x,y
key = GetKey() : rem Wait for a key
Until key=113 : rem Quit on "q" being entered

# Giving the ZX81 a try.

Given that the ZX81 has pretty good math, converting this to ZX81 BASIC wasn’t too hard. I started with my Daric version and added in line numbers. Most of the statements were already on separate lines, making it easy to convert.

Black Hole, ZX81 Screenshot 1, 2023 by Steven ReidBlack Hole, ZX81 Screenshot 1, 2023 by Steven Reid

I did inline the Range function as the ZX81 doesn't have a mechanism to do that. The final code looks similar to the original, with a few more comments to make things obvious. I also broke out the loop into two parts. This was so I could use the FAST command to speed it up a bit. After each iteration, I PAUSE for a bit so you can see the image progression.

You’ll also notice the function boundaries are quite a bit lower than the original. This is due to speed as well as the smaller screen size. I also created a PI2 variable that equals 2×π (2*PI in Sinclair BASIC). This reduces the overhead of multiplication where possible.

# Making adjustments

Coming back to any program, you often see things you missed. In my case, I saw a minor bug in the range code that needed fixing. In doing so, I took another look at the math. The ZX81 version didn’t quite look as nice as the original, and I wanted to see if I could improve it.

Black Hole, ZX81 Screenshot 2, 2023 by Steven ReidBlack Hole, ZX81 Screenshot 2, 2023 by Steven Reid

Using the Daric version for testing, I reverted the variables and started adjusting each individually. This helped me determine what each one did. My goal was to shrink down the output to fit the ZX81’s smaller screen.

To make it a bit easier to adjust, I refactored my ZX81 program to move the variables into their own subroutine. I also found that adjusting the division factoring when setting the AR variable made the most difference. Thus, I turned that into the RS variable to make it easier to adjust.

Black Hole, ZX81 Screenshot 3, 2023 by Steven ReidBlack Hole, ZX81 Screenshot 3, 2023 by Steven Reid

As a side effect of the changes, I found that I didn’t need as many iterations. The program tended to move out of the screen boundaries after about 5 or so iterations, but a few would go longer. I chose 10 as a compromise.

# Out the other side.

Black Hole isn’t perfect on the ZX81, but it still generated some interesting images. I’m sure I could improve it to make better-looking black holes. But for a super slow ancient computer, it still generated interesting pictures.

Black Hole, ZX81 Screenshot 4, 2023 by Steven ReidBlack Hole, ZX81 Screenshot 4, 2023 by Steven Reid

If you want more of ZX81 screensaver, it is a pretty easy modification. Comment out the FAST on line 60 and adjust the PAUSE on line 280 to 5000. You can also comment out the PAUSE on line 260 if you desire. This will give you a continuous display that can be quite fun to watch.

In the end, the most fun was programming in a different BASIC dialect other than Sinclair. I hadn’t done that since Amiga BASIC back in the earlier 90’s. The code is quite similar to that and probably would work well on the Amiga. That would be a fun trip down memory lane, but I leave it for another day. For now, you can enjoy the ZX81 version.

Comments on this article:

No comments so far.

Write a comment:

Type The Letters You See.
[captcha image][captcha image][captcha image][captcha image][captcha image][captcha image]
not case sensitive