See also: part 1, part 2, part 3, part 4, unrelated, and part 5.
Previously, I took a target from the attract screen code to talk more on using arrays in BASIC than individual variables. I gave an example of moving ghosts around a screen, and then did modifications to use an array. This let the user select how many ghost they wanted to see randomly display on the screen.
I mentioned that arrays were slower, but allowed flexibility. With that in mind, here is that “wandering ghosts” example turned in to a simple game demo. The player will appear as a yellow block in the top left corner of the screen. The ghosts will randomly appear around the screen as white blocks. The goal is to navigate to the bottom right corner of the screen without hitting a ghost, or being hit by one.
To hopefully make this compatible with the MC-10 computer, it uses the keyboard letters “WASD” — A for left, D for right, W for up and S for down.
You can choose one ghost, and get a single fast moving ghost to avoid. Or you can choose 100 ghosts, and get 100 slow moving ghosts to avoid, making it more like navigating a random maze that slowly moves walls.
Ghost Run in Color BASIC
10 ' ghostrun.bas 15 INPUT "NUMBER OF GHOSTS";G:G=G-1:IF G<0 THEN 15 20 CLS0:DIM G(G):DIM C(G):C=207:B=128:FOR I=0 TO G 30 G(I)=1023+RND(512) 41 NEXT 45 D(0)=1:D(1)=-1:D(2)=-32:D(3)=32 46 PL=1056:PC=159:POKE PL,PC 50 ' DISPLAY GHOSTS 60 FOR I=0 TO G:POKE G(I),C 65 D=INSTR(" DAWS",INKEY$):IF D>1 THEN GOSUB 190 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),B:POKE NL,C:G(I)=NL 165 IF NL=PL THEN 480 170 NEXT:GOTO 60 180 ' PLAYER MOVED D 190 NL=PL+D(D-2) 200 IF NL<1024 THEN RETURN 210 IF NL>1535 THEN RETURN 220 IF NL=1535 THEN 510 230 IF PEEK(NL)=C THEN 530 240 POKE PL,B:POKE NL,PC:PL=NL 250 RETURN 470 GOTO 60 480 ' GHOST GOT PLAYER 490 PRINT "WE GOT YA!" 500 END 510 PRINT "YOU MADE IT!" 520 END 530 PRINT "YOU HIT A GHOST!" 540 END
To reduce instant death, I made the ghosts spawn no higher than one line below the player. But, with a small amount of faster ghosts, something could spawn then randomly move towards the player quickly. It’s surprisingly challenging (or frustrating).
To make the game responsive to the player, as the code it updating the position of the ghost, the player can move. For example, if drawing 100 ghosts, the player can move as each ghost being drawn. I found this much more fun than doing a turn-by-turn game like the old 1976 CHASE game (also known as Robots for Unix, Daleks for Mac, and a zillion spinoffs in the 70s and 80s). Check out the first published listing Creative Computing 1976 or the wikipedia entry for more details.
But I, as I say, digress.
Maybe we can revisit this in future installments of this series.
Until then, here is another size optimization of the attract screen code, this time removing all the hard-coded array initializations and turning them in to DATA statements loaded by the READ command:
10 ' ATTRACT3.BAS 20 FOR I=0 TO 3 30 READ L(I),LD(I),CL(I),CD(I) 40 NEXT 50 Z=143 60 CLS 0:PRINT @268,"ATTRACT!"; 70 Z=Z+16:IF Z>255 THEN Z=143 80 FOR I=0 TO 3 90 POKE L(I),Z 100 L(I)=L(I)+LD(I) 110 FOR C=0 TO 3 120 IF L(I)=CL(C) THEN LD(I)=CD(C) 130 NEXT 140 NEXT 150 GOTO 70 160 ' L,LD,CL,CD 170 DATA 1024,1,1024,1 180 DATA 1047,1,1055,32 190 DATA 1535,-1,1535,-1 200 DATA 1512,-1,1504,-32
We have no changed the original 30 line version in to a 20 line version… but that is actually two lines longer than the previous one due to adding some extra lines for DATA and READ. But, if we were dealing with 50 objects instead of just 4, we’d likely be quite ahead at this point.
Next time, we’ll try to reduce this even further by packing lines together.
To be continued…