Color BASIC Attract Screen – part 2

See also: part 1, part 2, part 3, part 4, unrelated, and part 5.

In part 1, I showed a simple but slow way to recreate a classic CoCo game startup screen with color blocks moving around the screen. I recall many early CoCo games had startup screens similar to this, though fancier. The assembly language games would rotate all the blocks around the screen, rather than just moving four blocks like my BASIC demo does. For instance, Steve Bjork‘s port of Clowns and Balloons:

You can check it out in videos on YouTube, or play it in a web browser via the wonderful JS Mocha CoCo emulator.

My BASIC attract screen does not attempt to recreate that one, but is more of an homage to the style of attract screens we had in those early years.

My initial version clocked in at about 30 lines, and I suggested ways to make it smaller, such as using arrays to store screen locations rather than individual variables. Arrays make things smaller, but are slower. i.e., if you wanted to track four ghosts on the screen for a Pac-Man game, you could have variables like G1, G2, G3 and G4 and then have a block of code that handled each one individually. Or, you could have an array such as DIM G(3) and access the four ghost locations using G(0), G(1), G(2) and G(3). This allows handling the ghosts in a FOR/NEXT loop instead of four individual blocks of code using separate variables.

Here is a verbose example of randomly moving around four “ghosts”:

10 ' WANDERING.BAS
20 CLS0
30 G1=1024:G2=1055:G3=1504:G4=1535
40 C1=191:C2=239:C3=223:C4=255
50 ' DISPLAY GHOSTS
60 POKE G1,C1:POKE G2,C2:POKE G3,C3:POKE G4,C4
70 ' RANDOM MOVE G1
80 ON RND(4) GOTO 90,100,110,120
90 NL=G1+1:GOTO 130
100 NL=G1-1:GOTO 130
110 NL=G1-32:GOTO 130
120 NL=G1+32
130 IF NL<1024 THEN 180
140 IF NL>1535 THEN 180
150 ' ERASE G1 AND UPDATE LOCATION
160 POKE G1,128:POKE NL,C1:G1=NL
170 ' RANDOM MOVE G2
180 ON RND(4) GOTO 190,200,210,220
190 NL=G2+1:GOTO 230
200 NL=G2-1:GOTO 230
210 NL=G2-32:GOTO 230
220 NL=G2+32
230 IF NL<1024 THEN 280
240 IF NL>1535 THEN 280
250 ' ERASE G2 AND UPDATE LOCATION
260 POKE G2,128:POKE NL,C2:G2=NL
270 ' RANDOM MOVE G3
280 ON RND(4) GOTO 290,300,310,320
290 NL=G3+1:GOTO 330
300 NL=G3-1:GOTO 330
310 NL=G3-32:GOTO 330
320 NL=G3+32
330 IF NL<1024 THEN 380
340 IF NL>1535 THEN 380
350 ' ERASE G4 AND UPDATE LOCATION
360 POKE G3,128:POKE NL,C3:G3=NL
370 ' RANDOM MOVE G4
380 ON RND(4) GOTO 390,400,410,420
390 NL=G4+1:GOTO 430
400 NL=G4-1:GOTO 430
410 NL=G4-32:GOTO 430
420 NL=G4+32
430 IF NL<1024 THEN 470
440 IF NL>1535 THEN 470
450 ' ERASE G4 AND UPDATE LOCATIOn
460 POKE G4,128:POKE NL,C4:G4=NL
470 GOTO 60

And here is that same program, converted to use arrays for the four ghost locations, four ghost colors, and four directions:

10 ' WANDERING2.BAS
20 CLS0
30 G(0)=1024:G(1)=1055:G(2)=1504:G(3)=1535
40 C(0)=191:C(1)=239:C(2)=223:C(3)=255
45 D(0)=1:D(1)=-1:D(2)=-32:D(3)=32
50 ' DISPLAY GHOSTS
60 FOR I=0 TO 3:POKE G(I),C(I)
70 ' RANDOM MOVE G(I)
80 NL=G(I)+D(RND(4)-1)
130 IF NL<1024 THEN 170
140 IF NL>1535 THEN 170
150 ' ERASE G(I) AND UPDATE LOCATION
160 POKE G(I),128:POKE NL,C(I):G(I)=NL
170 NEXT
470 GOTO 60

I tried to keep common line numbers where I could. 47 lines of code down to 15.

And, now that it is an array, it’s easy to make it handle as many ghosts as you want. By adding one more element to the array, and changing the FOR/NEXT loop to count 0-4 instead of 0-3, we get an extra ghost:

10 ' WANDERING3.BAS
20 CLS0
30 G(0)=1024:G(1)=1055:G(2)=1504:G(3)=1535:G(4)=1263
40 C(0)=191:C(1)=239:C(2)=223:C(3)=255:C(4)=143
45 D(0)=1:D(1)=-1:D(2)=-32:D(3)=32
50 ' DISPLAY GHOSTS
60 FOR I=0 TO 4:POKE G(I),C(I)
70 ' RANDOM MOVE G(I)
80 NL=G(I)+D(RND(4)-1)
130 IF NL<1024 THEN 170
140 IF NL>1535 THEN 170
150 ' ERASE G(I) AND UPDATE LOCATION
160 POKE G(I),128:POKE NL,C(I):G(I)=NL
170 NEXT
470 GOTO 60

Arrays are great for reducing code size, and making it so one routine can handle multiple instances of something (locations, colors, etc.).

But, it is slower. Looking up X(3) is slower than looking up X3 since looking up an array has to first look up the variable, and then index in to it to find the entry.

Here is the attract code, converted to use arrays for the block positions and movement directions. As you can see, I’m basically handling the blocks like I did the ghosts above — as objects that can be moved around the screen. Instead of making their movement random, they follow a pattern around the outline of the screen. Instead of having a set color, they just cycle through the seven available non-black VDG colors:

10 ' ATTRACT2.BAS
20 L(0)=1024:L(1)=1024+23:L(2)=1535:L(3)=1535-23
30 Z=143
40 CL(0)=1024:CD(0)=1
50 CL(1)=1055:CD(1)=32
60 CL(2)=1535:CD(2)=-1
70 CL(3)=1504:CD(3)=-32
80 CLS 0:PRINT @268,"ATTRACT!";
90 LD(0)=1:LD(1)=1:LD(2)=-1:LD(3)=-1
100 FOR I=0 TO 3:POKE L(I),Z:NEXT
110 Z=Z+16:IF Z>255 THEN Z=143
120 FOR I=0 TO 3:L(I)=L(I)+LD(I):NEXT
130 FOR L=0 TO 3
140 FOR C=0 TO 3
150 IF L(L)=CL(C) THEN LD(L)=CD(C)
160 NEXT
170 NEXT
180 GOTO 100

30 lines of the originally down to 18 by using arrays.

When time isn’t as important as code size (or convenience), arrays are a great thing.

I have two more iterations of this attract screen to share, so I’ll end with…

To be continue…

2 thoughts on “Color BASIC Attract Screen – part 2

  1. Erico

    Very nice!
    The fight game I´m making does not use arrays for the speed impact is enormous. Code size increases but since each enemy is more or less unique, it is worth, otherwise I would have to add too many exceptions to the for/next array… not worth on a one on one fight style game.

    Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.