Friday 27 March 2015

"Overtake" another 4K Game for Allen Huffman's Contest



I've made another 4K game for Allen Huffman's programming contest. It's called "Overtake" and it is a car racing game. I've also submitted a 10 Line version of it to the NOMAM BASIC programming contest in Germany for a retro event there.

1 DIMK(128),P,G,V,R,D:K(9)=1:K(8)=2:K(94)=3:POKE65495,0:M=1024:FORR=1TO18:R$=R$+CHR$(143):NEXT:FORR=1TO10:R$=R$+CHR$(175):NEXT:FORR=1TO18:R$=R$+CHR$(143):NEXT
2 FORR=1TO32:W$=W$+CHR$(201):NEXT:Y$=CHR$(174)+CHR$(207)+CHR$(173):O$=CHR$(174)+CHR$(191)+CHR$(173):B$=CHR$(175):C$=B$+B$+B$:GOTO3
3 V=1:P=-10:G=50:S=0:PRINT@480,"SPEED"200-G;:FORD=1TO50:FORT=14TO0STEP-1:PRINT@T*32,MID$(R$,V,32);:R=2-RND(3):V=V+(R<0AND(V+R)>0)-(R>0AND(V+R)<16):NEXT
4 P=P+448:PRINT@496,"DIST"INT(D);:ONRND(2)GOTO5:R=P-(RND(5)*32)-256:IFPEEK(M+R)=175ANDPEEK(M+R+2)=175THENPRINT@R,O$;:PRINT@R+32,O$;
5 IF(PEEK(344)ANDPEEK(343)ANDPEEK(342)ANDPEEK(341))<>255THENONK(PEEK(135))GOSUB8,9,10
6 PRINT@P+32,C$;:P=P-32:IFP<0THENNEXTD:PRINT@0,W$;"SCORE";S:PRINTW$;:END ELSE IFPEEK(M+P)<>175ORPEEK(M+P+2)<>175THENSOUND1,1:G=50:PRINT@485,200-G;
7 PRINT@P,Y$;:PRINT@P+32,Y$;:FORZ=1TO G:NEXT:S=S+(50-G):GOTO5
8 PRINT@P,B$;:PRINT@P+32,B$;:P=P+1:RETURN
9 PRINT@P+2,B$;:PRINT@P+34,B$;:P=P-1:RETURN
10 G=G+(G>0):PRINT@480,"SPEED"200-G;:RETURN

I use some speedup techniques I've never used before. These involve doing checks and additions in the same line/command by using the logical operators and relying on the fact that they return either a zero (False) or -1 (True). If you are only moving by increments of 1, then you can efficiently use what these operators return to not only do boundary checking, but also, at the same time add or subtract a 1 if the check is okay. I suppose you could also multiply the result by another number to do additions for move increments other than 1, but it is especially efficient with movements of just 1 and helps avoid the use of lots of IF statements, which although generally fast commands, can when used in large numbers really slow down execution. So I have a command like this:

10 V=V+(R<0AND(V+R)>0)-(R>0AND(V+R)<16):program flow continues

This line basically adds or subtracts a random number (R) to one section of the track location unless that will put the track too far left or too far right on the screen. In the past I would have had multiple IFs like this:

10 IFR=-1ANDV+R>0THENV=V-1:GOTO 30
20 IFR=1ANDV+R<16THENV=V+1
30 program flow continues

The new way also saves having to use multiple lines on the MC-10, which was also helpful for my 10-Liner programming contest entry code (see above).

I also had some recent comments on my NBLITZ about how to avoid flicker in BASIC game animations.  I'll repeat my comments here for others who might have missed them.

Just make sure you remove all unnecessary spaces and pack lines as tightly as possible using colons (See my post here for advice on the few places you must leave spaces in for the Coco). I also find it is important to resist the temptation to stop working on a program's basic structure once you've got it basically working in terms of the animation. There are usually many ways to improve the logic and make the flow of a main loop more efficient. For example, if you're doing repetitive calculations in your animation loop, put them in a variable at start up, or do a pre-calculation loop at startup and store the results in an array. Then just consult the variable rather than do a calculation in your animation loop. Also, although in NBLITZ I use the SET command to display the planes, I don't use RESET to clear them. Instead, I have two large strings filled with CHR$(128)s (the black sky character) and the little graphic of London characters for the bottom of the screen. I just print these two strings @0, and they clear the entire screen to the background of black sky and city skyline (except for the very bottom left position, which I just pre POKE to the right color character at startup). Then I just redraw the planes in their new locations. This is much faster than RESETing the individual pixels of each plane or having complicated procedures to POKE them to black.

Also, in NBLITZ I originally checked that the location of my plane did not go beyond the boundary of the top, left, right or bottom of the screen, but I was also checking for any collisions with other planes or the city at the bottom the screen.  So I was eventually able to remove the bottom bounds check since the city effectively blocks any movement towards that boundary. There's always some temptation when programming to leave such redundancies in, especially in the old days (or even still today) when you had to use to kludgy EDIT and LIST commands to make any changes. By programming using a good line editor like WordPad, such editing awkwardness is overcome. Here's a video showing the advantages of using the VMC-10 emulator and its quicktype feature to make quick and easy changes to one's BASIC source before "quicktyping" it in, which takes just a few seconds, and running it: