Inty Road Race Written by Ian Holbrough (ianholbrough@callnetuk.com) First place, Winter 1999 ECS BASIC Programming Competition March 18, 1999 __________________________________________________________ DESCRIPTION Inty Road Race is a simple vertical scrolling racing game, kind of a cross between Bump 'n' Jump and River Raid, though clearly nowhere near as good as either. The object of the game is simple, drive your ill handling ride as far as possible down a winding road, without crashing off the road. INSTRUCTIONS Initially you are asked to enter the width of the road and visibility. Use the ECS keyboard to do this. The width of the road is measured in ECS characters, typically 4, or 5 gives a good game. The visibility defines how far down the screen your car is displayed, this affects the time that you have to react to curves in the road. A low visibility places the car at the bottom of the screen, and provides little reaction time. Values less than 4 are very challenging. Clearly these two values provide some opportunity to adjust the difficulty of the game, and handicap players. Having entered these numbers the screen clears and the road is plotted out, initially straight. Your car is placed on the screen (The blue uncar like shape). The race starts.... Subsequent sections of the road are drawn at the bottom of the screen, and force the road to scroll, up giving a basic illusion of movement. Use the 4,5 and 6 keys on either hand controller to move the car.] 4 - makes the car move left continuously 6 - makes the car move right continuously 5 - stops the car moving Note that you vehicle is not a Porsche, or Ferrari. More like a station wagon or Reliant Robin (Euro joke, the Robin is a three wheeled crate of a car made in the UK and ridiculed mercilessly), expect it to handle like a dog. I point this out to stop people winging about how poor the controls are (I know they are and if I could program it better I would). Besides if the controls were any good the game would just be too easy! Should you crash into the walls (yeah, yeah the collision detection is a bit suspect too) the screen will clear and you will informed how far you managed to travel. One mile corresponds to 1 segment of road being drawn. At this point pressing the following keys on the controller have the effects detailed below. 1 - replays the game with the existing settings 2 - goes to the selection screens and allows you to reset the difficulty 3 - quits the game THE CODE 10 GSUB 900 20 PRIN "ENTER ROAD WIDTH" 30 INPU "(3-8) ",G 40 IF (G<3) GOTO 10 50 IF (G>8) GOTO 10 60 GSUB 900 70 PRIN "ENTER VISIBILITY" 80 INPU "(1-10) ",E 90 IF (E<1) GOTO 60 100 IF (E>10) GOTO 60 200 DIM AA(11) 210 DIM AB(11) 220 L=G/2 230 L=10-IT(L) 240 R=L+G 250 F=0 300 CLR 310 FOR C=1TO11 320 GSUB 1000 330 NEXT C 350 O=0 360 D=0 370 N=6 380 CALL SHOW 390 XP(0)=80 400 YP(0)=(11-E)*8 410 CO(0)=1 420 XS(0)=1 430 C=1 500 P=(XP(0)/8) 510 IF (PAB(C)) GOTO 1100 560 CALL HAND 570 IF (H=4) XV(0)=-16 580 IF (H=6) XV(0)=16 590 IF (H=5) XV(0)=0 600 M=0 610 P=RN(0) 620 IF (P>40) GOTO 720 630 IF (P>20) GOTO 670 650 IF (L>1) M=-1 660 GOTO 700 670 IF (R<19) M=1 700 L=L+M 710 R=R+M 720 GSUB 1000 750 C=C+1 760 IF (C>(E+1)) C=1 770 F=F+1 780 GOTO 500 900 CLR 910 FM(4)=1 920 PRIN " INTY ROAD RACE!" 930 PRIN " BY FASTED" 940 FM(4)=0 950 PRIN "-------------------- " 960 RET 1000 SET A$=" " 1010 A$(L)=16 1020 A$(R)=16 1030 PUT A$ 1040 AA(C)=L+1 1050 AB(C)=R-1 1060 RET 1100 XV(0)=0 1110 VS(0)=-1 1120 GSUB 900 1130 PRIN "MILES COVERED",F 1140 CALL HAND 1150 IF (H=1) GOTO 200 1160 IF (H=2) GOTO 10 1170 IF (H=3) GOTO 1200 1180 GOTO 1140 1200 GSUB 900 1210 PRIN "THANK YOU" POSSIBLE EXTENSIONS/VARIATIONS A number of extensions to this game are possible. 1 - Give it some sound 2 - Put in pedestrians and cars either to avoid or hit (Carmageddon on the Inty ???!!) 3 - Make the width of the road, and or visibility change during the race 4 - Put in a start procedure with traffic lights 5 - Tidy up the collision detection and controls Or how about this 1 - A vertical version of Frogger where you have to avoid on coming trucks. You could have up to three trucks per track segment, points scored per frog across the screen 2 - An upside down version of Kaboom / Spike's Balloons / Stampede. You must touch all the rocks / balloons whatever dropped (clearly more than one per segment would be unreasonable). I doubt if I will get time to look at these, but do feel free. Should you have any success please drop me a line with the results. TECHNICAL NOTES For those who are interested... There are two interesting aspects to this game, the rest of it is pretty boilerplate, and can be understood by reading the annotated code below. * Drawing The Road Whilst this might seem simple it is in fact quite interesting to achieve this on the ECS. When writing games like this before in BASIC I have used string arithmetic to construct the next segment of road. Thus the next road segment A$ is built with A$=STRING$(LEFT," ") + "0" + STRING$(WIDTH, " ") + "0" where STRING$(A,B$) produces are repetition of B$ A times. However, ECS basic does not have string arithmetic let alone a function like STRING$. Instead like C and other languages it exposes the programmer to the fact that strings are stored as arrays. So constructing the next segment of track is achieved by defining a blank string A$=" " and then resetting certain characters to the be the edge A$(left)=16 A$(right)=16 This is actually much faster and neater than the methods I have used before, and I like it lots. This method of poking characters into strings makes possible all kinds of effects. Notably it means that plotting graphs, both line and bar are feasible (see Inty Chaos). * Collision Detection The second interesting area is in detecting collisions. This would more normally be done by PEEKing the memory location of the character immediately in front of the car. * * ** <---- Car ** < > <---- Check to see what is here However, once again ECS Basic lets us down (I seem to remember reading that Microsoft wrote ECS basic somewhere, now that would explain alot!). So some way around this must be found. The problem is that whilst we know where the road is when we plot it, some time passes before we need to be concerned with collision detection. So the position of the left and right boundaries are stored in the arrays AA and AB. Within these arrays it would be possible to always use an array element for each row of the screen (i.e. AA(0) would always represent the top row of the screen, AA(11) the bottom). However, as the screen scrolls it would be necessary to shift all the data in the arrays up, which given the incredible speed of the ECS would limit the playability of the game. The way round this is to use a pointer. Thus in each loop through the game, the left and right values of the track pointed to by the pointer are checked. If no crash is detected the values of the new track segment are calculated and these replace the values just read, and the pointer incremented. Thus over time AA(0) represents the bottom, middle and top of the screen. The pointer always points to the array element that contains the next segment to be checked. The only further complication to this is that the visibility changes which segment is checked (clearly the car cannot crash into segments it has already passed, and these can be ignored). This visibility effect is captured by changing the number maximum number the pointer can take. As the visibility falls the pointer rotates faster and faster around the array. Anyway, overall these two elements made this quite an interesting little piece to code and test. ANNOTATED CODE 10 GSUB 900 ;Call title screen 20 PRIN "ENTER ROAD WIDTH" ;Request the user enter the road width 30 INPU "(3-8) ",G 40 IF (G<3) GOTO 10 50 IF (G>8) GOTO 10 60 GSUB 900 70 PRIN "ENTER VISIBILITY" ;Request the user enter the visibility 80 INPU "(1-10) ",E 90 IF (E<1) GOTO 60 100 IF (E>10) GOTO 60 200 DIM AA(11) ;Allocate array to store left hand road data 210 DIM AB(11) ;Allocate array to store right hand road data 220 L=G/2 ;Calculate the left hand edge given that it is to be 230 L=10-IT(L) ;centred on the screen 240 R=L+G ;Right hand edge = left hand edge + width 250 F=0 ;Set miles covered = 0 300 CLR ;Lets go 310 FOR C=1TO11 ;Draw out initial straight section of road 320 GSUB 1000 ;Draw each segment 330 NEXT C 350 O=0 ;Display the car 360 D=0 370 N=6 380 CALL SHOW 390 XP(0)=80 ;Put the car in the middle of the screen 400 YP(0)=(11-E)*8 ;Use the visibility to play it vertically 410 CO(0)=1 420 XS(0)=1 430 C=1 ;This is the pointer to the location of the car (see collision detection) 500 P=(XP(0)/8) ;Calculate position of car in characters 510 IF (PAB(C)) GOTO 1100 ;Check to see it you are off the road (right) 560 CALL HAND ;Lets see if you want to change direction 570 IF (H=4) XV(0)=-16 ;4 means left 580 IF (H=6) XV(0)=16 ;6 means right 590 IF (H=5) XV(0)=0 ;5 means stop 600 M=0 ;As a default the road is straight 610 P=RN(0) ;This is the probability it will turn 620 IF (P>40) GOTO 720 ;60% of the time it is straight 630 IF (P>20) GOTO 670 ;20% of the time it moves right 650 IF (L>1) M=-1 ;The remainder it moves left 660 GOTO 700 670 IF (R<19) M=1 ;Ok if we can we move right 700 L=L+M ;Calculate the new left 710 R=R+M ;and right positions 720 GSUB 1000 ;Plot the segment 750 C=C+1 ;Increment the pointer 760 IF (C>(E+1)) C=1 ;If the pointer has run past the end of the array set to 1 770 F=F+1 ;Increase the number of miles travelled 780 GOTO 500 ;End of main game loop 900 CLR ;Title screen plot 910 FM(4)=1 ;Blue text 920 PRIN " INTY ROAD RACE!" 930 PRIN " BY FASTED" ;Self seeking ego maniac alert! 940 FM(4)=0 ;Black text 950 PRIN "-------------------- " 960 RET 1000 SET A$=" " ;Plot road segment, by default no road edges 1010 A$(L)=16 ;Poke into the string the left hand edge 1020 A$(R)=16 ;Poke into the string the right hand edge 1030 PUT A$ ;Draw the road 1040 AA(C)=L+1 ;Store the last valid left hand bit of the road in AA 1050 AB(C)=R-1 ;Store the last valid right hand bit of road in AB 1060 RET 1100 XV(0)=0 ;You crashed. Stop the car moving 1110 VS(0)=-1 ;Hide the car 1120 GSUB 900 ;Plot the title screen 1130 PRIN "MILES COVERED",F ;Your score ? 1140 CALL HAND 1150 IF (H=1) GOTO 200 ;replay the same settings 1160 IF (H=2) GOTO 10 ;Ask for the settings again 1170 IF (H=3) GOTO 1200 ;quit 1180 GOTO 1140 ;wait for a valid reply 1200 GSUB 900 1210 PRIN "THANK YOU" ;I am so polite !?