'---------------------------------------------------------------------------- ' Tricycle Ball programming tutorial, by F.Lionet ' ' STEP FOUR: the ball '---------------------------------------------------------------------------- ' ' In a ball game, the ball is obviously quite important! We will therefore ' take great pains to make the ball movements as realistic as possible. ' ' At first glance, the ball is very similar to our trikes. As with the trikes ' we'll need to keep track of it's location, speed and direction. ' ' The speed and direction bit's easy, as we can define a couple of simple ' variables SB (for the speed), and DB (for the direction) ' ' There is however, one massive difference between the ball and the trikes. ' Unlike the trikes which are limited to moving on the actual playfield, ' the ball can also fly in the air. So we'll need to add a vertical ' component to our speed to allow the ball to bounce realistically ' on the ground. ' ' This vertical movement is handled in two ways. ' ' The Location: ' ' Our coordinates are extended into the vertical 'Z' direction. ' The position is now measured using three coordinates in XB,YB and ZB ' Like the trike, these values are first multipled by 32 for extra accurracy ' ' The Appearance: ' ' When the ball falls toward the player, it will seem to grow in size. ' So we'll have to create several different images for the ball, ' depending on it's apparent distance from the ground. ' Before programming this stage, I loaded the bob editor, and drew ' up some crude mock-up of these balls starting from position 22. ' ' One side effect of our system, is if you hit the other player and push him ' against the ball, the ball will move away! This wasn't actually programmed, ' it was just a lucky accident! When you are developing a game, these ' types of surprises crop up all the time. That's part of the fun! ' ' ' Well, that's the introduction. Let's get down to the main program! '---------------------------------------------------------------------------- Close Editor Hide On PATH$="Easy_Examples:" ' ' As before Dim XP(1),YP(1),XDP(15),YDP(15),DB(1),DP(1),SP(1),IP(15,1),FL(1) Dim XR(1),YR(1) Dim XH(15),YH(15) Dim XHH(15),YHH(15) Dim CP(1),CB(1),CC(1),XC(1),YC(1) ' *** ' We'll start by defining an array to hold the 'bounce table'. ' A bounce table is an important part of any realistic ball game ' If we had to calculate the rebound directions in our program directly, ' the game would pause for 1/2 a second every time the ball hit a wall. YUCK! ' It's much faster to perform all our calculations in advance, and place them ' in a bounce table, ready for instant use. See the GAME_INIT and BALL_ANIM ' procedures for more info... Dim BOUNCE(8,15) ' ' Now, we've dimensioned our arrays, let's make them global Global XP(),YP(),XDP(),YDP(),DB(),DP(),SP(),IP(),FL() Global XR(),YR() Global P2BOB,BBP,BBB,PSIZE Global PLA Global XC(),YC() Global XH(),YH(),XHH(),YHH(),CP(),CB(),CC() Global P2BOB,BBP,BBB,PSIZE ' *** ' Since we're only using a single ball, we will just have to define ' a few global variables for it. ' XB, YB and ZB will hold the coordinates of the ball, multipled by 32 Global XB,YB,ZB ' *** ' DB is the ball direction, from 0 to 14 ' SB is the speed. Global DB,SB ' *** ' SZB is the ball speed on the Z axis. (UP or DOWN) Global SZB ' *** ' ZBALL is the zoom factor used by the ball display. ' It determines the apparent size of the ball on the screen. See BALL_ANIM Global ZBALL ' *** ' BBALL holds the number of the bob used to display the ball Global BBALL ' *** ' CPT is a small counter used for the ball animation ' BOUNCE() is the array holding our bounce table. Global CPT,BOUNCE() ' *** ' Here are some new variables that will set the limits of the playing area Global YTOP,YBOTTOM,XCENTER,YCENTER ' Load PATH$+"Bobs/Tricycle_Bobs.Abk" Load PATH$+"Pictures/Tricycle_Screen.Abk",10 Load PATH$+"Pictures/Tricycle_Playfield.Abk",11 ' GAME_INIT ' *** ' Notice that we are now using X and YCENTER to set the player's ' coordinates. For P=0 To 1 XP(P)=XCENTER : YP(P)=YCENTER-25*32+P*50*32 Next ' *** ' Next, set the initial coordinates of the ball to the center of the screen. XB=XCENTER : YB=YCENTER : DB=0 : SB=0 ' *** ' Let's start the ball game by kicking the ball in the air with a random speed ZB=0 : SZB=Rnd(15)+16 ' GAME ' ALL_ERASE Edit ' Procedure GAME_INIT ' BBP=1 : P2BOB=10 : BBB=4 PSIZE=10 ' *** ' BBALL holds the number of bob used to display the ball BBALL=3 ' *** ' ZBALL sets the Ball height zoom factor. It's used to determine the ' image numbers used by the ball when it reaches various heights. ' I worked it out by careful experimentation ' Feel free to change it to see the effects! ZBALL=30 ' *** ' Defines the limits of the playfield, top and bottom, ' All coordinates are multipled by 32 YTOP=64*32 : YBOTTOM=432*32 ' *** ' Sets the coordinates to the centre of the playfield, *32 XCENTER=124*32 : YCENTER=236*32 ' Restore _DIRECTIONS ANGLE#=Pi#/2.0 : A=32 : B=3 : S=8 For D=0 To 15 XDP(D)=S*Cos(ANGLE#) : YDP(D)=-S*Sin(ANGLE#) XH(D)=A*Cos(ANGLE#) : YH(D)=-A*Sin(ANGLE#) XHH(D)=B*Cos(ANGLE#-Pi#/2) : YHH(D)=-B*Sin(ANGLE#-Pi#/2) ANGLE#=ANGLE#-Pi#/8.0 Read IP(D,0),IP(D,1) Next ' *** ' We will now read the bounce tables into the BOUNCE array ' This takes the number of the ZONE underneath the ball, and the current ' movement direction, and returns the new ball direction after the ' rebound. ' ' The first dimension is the number of the ZONE the ball ' has collided with on the screen. (Z). ' ' The second dimension is the current ball direction (DB). ' ' I calculated the bounce table by hand, using pencil and paper. ' I began with a crude sketch of the playfield, and then ' just drew in each boundary zone, and worked out the possible bounce ' directions. Restore _BOUNCE For Z=1 To 8 For B=0 To 15 Read BOUNCE(Z,B) Next Next ' Unpack 11 To 1 Reserve Zone 10 Set Zone 1,21,0 To 223,24 : Set Zone 2,21,487 To 220,511 Set Zone 3,0,21 To 25,487 : Set Zone 4,220,24 To 256,487 Set Zone 5,0,0 To 21,24 : Set Zone 6,220,0 To 256,24 Set Zone 7,0,486 To 24,511 : Set Zone 8,220,487 To 256,511 ' Unpack 10 To 0 Get Palette 1 Screen Display 0,,,,200 Double Buffer Bob Update Off Autoback 1 ' CLR_DISPLAY ' Screen 1 ' Pop Proc ' _DIRECTIONS: Data 1,2 Data 3,4 Data 5,6 Data 7,8 Data 9,10 Data Vrev(7),Vrev(8) Data Vrev(5),Vrev(6) Data Vrev(3),Vrev(4) Data Vrev(1),Vrev(2) Data Rev(3),Rev(4) Data Rev(5),Rev(6) Data Rev(7),Rev(8) Data Hrev(9),Hrev(10) Data Hrev(7),Hrev(8) Data Hrev(5),Hrev(6) Data Hrev(3),Hrev(4) ' *** ' The bounce table ' Calculated by hand! ' Of course, some bounces in the table can never actually happen. ' It's impossible, for example, for the ball to bounce off the top wall, ' when it's already moving downwards. But who cares? _BOUNCE: Data 8,7,6,5,5,5,6,7,8,9,10,11,11,11,10,9 Data 0,1,2,3,3,3,2,1,0,15,14,13,13,13,14,15 Data 1,1,2,3,4,5,6,7,7,7,6,5,4,3,2,1 Data 15,15,14,13,12,11,10,9,9,9,10,11,12,13,14,15 Data 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 Data 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 Data 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 Data 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 ' End Proc Procedure GAME ' Repeat ' *** ' This small counter is currently used by the ball animation. CPT=CPT+1 ' Bob Clear ' *** ' Let's animate the ball with our new BALL_ANIM routine. BALL_ANIM ' MOVE_PLAYER[0] MOVE_PLAYER[1] ' Bob Draw ' DISPLAY_FIELD ' Screen Swap ' A$=Inkey$ If A$=Chr$(27) : Exit : End If If A$=" " : PLA=1-PLA : End If ' Wait Vbl ' Until 0 ' End Proc Procedure C0LLIDE[P,C] ' *** ' Now, we'll extend our original ON GOTO statement to handle the ball On C Goto CYCLE,CYCLE,BALL Pop Proc ' ' Collision with other player CYCLE: Q=1-P CP(Q)=1 : SP(Q)=SP(P)+4*Sgn(SP(P)) : DP(Q)=DP(P) : Bob Off BBB+Q CB(P)=B : CP(P)=1 : CC(P)=CC(P)+1 : SP(P)=-Min(SP(P),8) Pop Proc ' *** ' Collision with the ball BALL: ' *** ' If the ball is high, the tricycle will move right UNDER it! If ZB<32 ' *** ' Are we going forward? If SP(P)>2 ' *** ' YES: This will be a perfect hit, so the ball direction ' will equal the player direction DB=DP(P) ' *** ' The Ball speed will be more or less the player's speed SB=SP(P)+6 ' *** ' Let's bounce the ball upward, depending on the player's speed. SZB=SP(P)/2+Rnd(SP(P)/2) End If ' *** ' Are we going backwards? If SP(P)<2 ' *** ' YES: ball direction will be approximately equal to the player's direction DB=(DP(P)+8+1-Rnd(2)) mod 16 ' *** ' Work out the new speed of the ball SB=-(SP(P)*3)/2+4 SZB=-SP(P)/2+Rnd(SP(P)/2) End If ' *** ' Are we stationary? If Abs(SP(P))<=2 ' *** ' YES:the ball will bounce in any direction! SB=Max(SB,8) ' *** ' With a random, small speed DB=(DB-1+Rnd(2)) mod 16 : SZB=Rnd(8) End If End If End Proc Procedure BALL_ANIM ' *** ' This procedure performs all the animation on our ball ' *** ' First, we move the ball in the current direction and speed. ' Notice that the movement is done using the same system as the tricycles. XB=XB+XDP(DB)*SB : YB=YB+YDP(DB)*SB ' *** ' Then, we'll slow down the ball to simulate friction ' This will be greater if ball is stuck on the ground (ZB=0) If ZB=0 SB=Max(SB-3,0) Else SB=Max(SB-1,0) End If ' *** ' Now move the ball in the Z direction (Vertically) ZB=ZB+SZB ' *** ' Does the ball bounce? If ZB<=0 ' *** ' YES, it is bouncing: the Z coordinate is below zero! ' We'll therefore reverse its vertical movement speed SZB=-SZB/2 ' *** ' and position it OVER the ground (as SZB is positive now) ZB=SZB End If ' *** ' Gravity: If the ball is in the air, it will feel the force of gravity ' So it's vertical speed will gradually be reduced ' If ZB : SZB=SZB-2 : End If ' *** ' Calculate the new ball coordinates. ' Let's see if it hits a wall... ' We start by getting the real coordinates by dividing by 32 X=XB/32 : Y=YB/32 ' *** ' We can then find the zone under the ball. See how we are testing ' a small triangle around the center of the ball to find ' the bounce in every possible direction... Z=Max(Zone(X,Y-4),Max(Zone(X-4,Y+4),Zone(X+4,Y+4))) ' *** ' If a zone is detected, the ball has hit one of the walls. If Z ' *** ' As Michael Jackson would say, let's get it Off the Wall! ' The rebound direction can be taken straight from our bounce table DB=BOUNCE(Z,DB) End If ' *** ' So we can display the ball ' *** ' Is the ball moving? If SB+SZB ' *** ' YES: We must animate it. ' The first ball image in the bob bank is number 22 ' CPT mod 2 just returns one of two values 0 and 1. ' It's used for the animation. ' ZB/ZBALL gives a value depending on the ball height. ' Just to make life easy for myself, I've drawn the ball images ' in order of increasing size. This lets me calculate the image number ' directly from the height of the ball... I=Min(22+ZB/ZBALL*2+(CPT mod 2),31+(CPT mod 2)) Else ' *** ' NO: the ball is on the ground. Very simple. I=22 End If ' *** ' Display the bob Bob BBALL,XB/32,YB/32,I ' *** ' That's it. The ball is animated, and everything works! End Proc Procedure MOVE_PLAYER[P] ' FL(P)=FL(P)+1 ' If CP(P) If SP(P) SP(P)=SP(P)-Sgn(SP(P)) Else CP(P)=CP(P)-1 : DP(P)=DB(P) End If End If ' If CP(P)=0 ' If P=PLA : J=Joy(1) : End If ' CB(P)=0 : CC(P)=0 ' Go faster? If J and 1 : If SP(P)<16 : SP(P)=SP(P)+3 : End If : End If ' Go slower? If J and 2 : If SP(P)>-16 : SP(P)=SP(P)-3 : End If : End If ' Turn left? If J and 4 : DP(P)=DP(P)-1 : If DP(P)<0 : DP(P)=15 : End If : DB(P)=DP(P) : End If ' Turn right? If J and 8 : DP(P)=DP(P)+1 : If DP(P)>15 : DP(P)=0 : End If : DB(P)=DP(P) : End If ' Brake? If J and 16 : SP(P)=0 : End If ' End If ' XP(P)=XP(P)+XDP(DP(P))*SP(P) YP(P)=YP(P)+YDP(DP(P))*SP(P) ' XR(P)=XP(P)/32 : YR(P)=YP(P)/32 ' S=Sgn(SP(P)) I=IP(DB(P),Abs(S)*(FL(P) mod 2)) Bob BBP+P,XR(P),YR(P),I+P2BOB*P ' XD=XR(P)+S*(XH(DP(P))*PSIZE)/32 : YD=YR(P)+S*(YH(DP(P))*PSIZE)/32 ' C=Bob Col(BBP+P,BBP To 5) ' A=Max(Zone(XD,YD),Max(Zone(XD+XHH(DP(P)),YD+YHH(DP(P))),Zone(XD-XHH(DP(P)),YD-YHH(DP(P))))) ' If CC(P)>3 SP(P)=0 : CP(P)=0 : CC(P)=1 A=0 : C=0 : Bob Off BBB+P End If ' If A CP(P)=3 : XC(P)=XD : YC(P)=YD : CC(P)=CC(P)+1 SP(P)=-S*Min(Max(Abs(SP(P)+6),4),8) Else If C B=Col(-1) : If B<>CB(P) : C0LLIDE[P,B] : End If End If End If ' If CP(P)=3 : Bob BBB+P,XC(P)+Rnd(4),YC(P)+Rnd(4),21 : End If If CP(P)=2 : Bob Off BBB+P : End If ' End Proc Procedure DISPLAY_FIELD ' *** ' We will now extend this procedure to copy the BALL area into the ' small viewing window on the bottom of our display. ' X=XR(0)-78 : Y=YR(0)-67 Screen Copy 1,X,Y,X+156,Y+135 To Logic(0),2,2 ' X=XR(1)-78 : Y=YR(1)-67 Screen Copy 1,X,Y,X+156,Y+135 To Logic(0),162,2 ' *** ' Here we go X=XB/32-58 : Y=YB/32-29 Screen Copy 1,X,Y,X+117,Y+59 To Logic(0),102,139 ' End Proc Procedure CLR_DISPLAY ' Screen 0 For S=0 To 1 Cls 0,2,2 To 158,137 Cls 0,162,2 To 318,137 Cls 0,102,139 To 102+117,139+59 Screen Swap : Wait Vbl Next Screen 1 ' End Proc Procedure ALL_ERASE For B=1 To 15 : Erase B : Next End Proc