SUBROUTINE BALMOV # # THIS SUBROUTINE CONTROLS THE MOTION OF THE BALL. 'BALDIR' IS THE # ANGLE OF MOTION AS MEASURED FROM STRAIGHT UP. (45 IS UP AND RIGHT, # 180 IS STRAIGHT DOWN, ETC.) 'MOTION' IS SET ACCORDING TO WHICH # COMPONENTS OF MOTION (UP, DOWN, LEFT, AND RIGHT) ARE CONTAINED IN # THE CURRENT ANGLE OF MOTION, AND IS USED FOR CALCULATING REBOUNDS. # IMPLICIT INTEGER (A-Z) INCLUDE SY:UVT100.DAT INCLUDE SY:BRKOUT.CMN PARAMETER BELL=7 REAL X,RAN BALCYC = BALCYC + 1 IF (BALCYC > 4) BALCYC = 1 # # GENERATE RANDOM NUMBER # X = RAN(SEED) ITMP = X * 5 # # CLEAR DISPLAY OF BALL AT ITS CURRENT LOCATION # IF (BALLX < BMAR .AND. BALLX >= TMAR) [ CALL UVT100(CUP,BALLX,BALLY) OUTBUF(LEN+1) = SPACE IF (BALLX > 2 .AND. BALLX < 9) OUTBUF(LEN+1) = DSPCHR(BSTATE(BALLX,BALLY)) LEN = LEN + 1 ] # # PERFORM TWO MOTIONS OF THE BALL IN THIS CALL TO BALMOV. THIS # IS NECESSARY BECAUSE SOME MOTIONS REQUIRE THE BALL TO MOVE # LIKE A KNIGHT IN CHESS, AND WOULD APPEAR ERRATIC IF DISPLAYED # AT EVERY LOCATION. BY ONLY DISPLAYING EVERY OTHER LOCATION, THE # MOTION OF THE BALL ALWAYS APPEARS STRAIGHT. THE ONLY EXCEPTIONS # TO THIS ARE WHEN THE BALL IS AT THE TOP OF THE SCREEN OR ABOUT # TO HIT THE PLAYER'S PADDLE. HERE WE DISPLAY BOTH MOTIONS SO THE # PLAYER CAN 'SEE' THE BALL ONTO HIS PADDLE. # DO I = 1,2 [ #LOOP TWICE IF (FLAG == 1) [ #IF WE DISPLAYED THE BALL FLAG = 0 #ON FIRST ITERATION OF LOOP, CALL UVT100(CUP,BALLX,BALLY) #BLANK IT OUT. OUTBUF(LEN+1) = SPACE LEN = LEN + 1 ] OLDDIR = BALDIR #REMEMBER OLD DIRECTION # # MOVE THE BALL TO ITS NEW LOCATION BASED ON ITS CURRENT DIRECTION # OF MOTION. MOVEMENTS ALONG ANY 45 DEGREE SLOPE ARE SKIPPED ONE # QUARTER OF THE TIME, TO PAY SOME HOMAGE TO THE PYTHAGOREAN THEOREM. # IF (BALDIR == 0) [ #0 DEGREES BALLX = BALLX - 1 MOTION = UP ] ELSE IF (BALDIR == 30) [ #30 DEGREES BALLX = BALLX - 1 IF (I == 1) BALLY = BALLY + 1 MOTION = UPR ] ELSE IF (BALDIR == 45) [ #45 DEGREES IF (I == 1 .AND. BALCYC == 2) NEXT ELSE IF (I == 2 .AND. BALCYC == 4) NEXT BALLX = BALLX - 1 BALLY = BALLY + 1 MOTION = UPR ] ELSE IF (BALDIR == 60) [ #60 DEGREES IF (I == 1) BALLX = BALLX - 1 BALLY = BALLY + 1 MOTION = UPR ] ELSE IF (BALDIR == 120) [ #120 DEGREES IF (I == 1) BALLX = BALLX + 1 BALLY = BALLY + 1 MOTION = DOWNR ] ELSE IF (BALDIR == 135) [ #135 DEGREES IF (I == 1 .AND. BALCYC == 2) NEXT ELSE IF (I == 2 .AND. BALCYC == 4) NEXT BALLX = BALLX + 1 BALLY = BALLY + 1 MOTION = DOWNR ] ELSE IF (BALDIR == 150) [ #150 DEGREES BALLX = BALLX + 1 IF (I == 1 .AND. (BALLX != BMAR .OR. BALLY != PDLY+2)) BALLY = BALLY + 1 MOTION = DOWNR ] ELSE IF (BALDIR == 180) [ #180 DEGREES BALLX = BALLX + 1 MOTION = DOWN ] ELSE IF (BALDIR == 210) [ #210 DEGREES BALLX = BALLX + 1 IF (I == 1 .AND. (BALLX != BMAR .OR. BALLY != PDLY)) BALLY = BALLY - 1 MOTION = DOWNL ] ELSE IF (BALDIR == 225) [ #225 DEGREES IF (I == 1 .AND. BALCYC == 2) NEXT ELSE IF (I == 2 .AND. BALCYC == 4) NEXT BALLX = BALLX + 1 BALLY = BALLY - 1 MOTION = DOWNL ] ELSE IF (BALDIR == 240) [ #240 DEGREES IF (I == 1) BALLX = BALLX + 1 BALLY = BALLY - 1 MOTION = DOWNL ] ELSE IF (BALDIR == 300) [ #300 DEGREES IF (I == 1) BALLX = BALLX - 1 BALLY = BALLY - 1 MOTION = UPL ] ELSE IF (BALDIR == 315) [ #315 DEGREES IF (I == 1 .AND. BALCYC == 2) NEXT ELSE IF (I == 2 .AND. BALCYC == 4) NEXT BALLX = BALLX - 1 BALLY = BALLY - 1 MOTION = UPL ] ELSE IF (BALDIR == 330) [ #330 DEGREES BALLX = BALLX - 1 IF (I == 1) BALLY = BALLY - 1 MOTION = UPL ] # # IF THE BALL'S NEW LOCATION COINCIDES WITH A BRICK LOCATION, # CALL COLIDE TO PERFORM THE COLLISION AND CALCULATE THE REBOUND. # IF (BALLX > 2 .AND. BALLX < 9 .AND. BSTATE(BALLX,BALLY) != 0) [ CALL COLIDE IF (SCORE/2100*2100 == SCORE) [ #IF WE JUST KILLED LAST BRICK CURTIM = TIMER #ON BOARD, RESET NEW BOARD CALL GETADR(PRL,OUTBUF) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 CALL WAIT(1,2) CALL START RETURN ] BREAK ] RBOUND = 0 #SET IF REBOUND REQUIRED IF (BALLX <= TMAR) [ #REBOUND OFF TOP WALL IF (BALDIR < 90 .OR. BALDIR > 270) RBOUND = 1 ] IF (BALLY <= LMAR) [ #REBOUND OFF LEFT WALL IF (BALDIR > 180) RBOUND = 2 ] ELSE IF ( BALLY >= RMAR) [ #REBOUND OFF RIGHT WALL IF (BALDIR < 180) RBOUND = 2 ] PDLHIT = 0 #SET IF BALL HITS PADDLE. IF (BALLX == BMAR) [ #BALL IS ON PADDLE ROW. IF (BALLY <= LMAR) #FORCE IT WITHIN BOUNDS BALLY = LMAR + 1 ELSE IF (BALLY >= RMAR) BALLY = RMAR - 1 DO J = 0,2 [ #CHECK IF BALL HITS ANY OF IF (BALLY == PDLY + J) [ #THE THREE PADDLE LOCATIONS PDLHIT = J + 1 IF (BALDIR > 90 .AND. BALDIR < 270) RBOUND = 1 #IF SO, SET REBOUND FLAG ] ] ] IF (BALLX > BMAR) [ #IF BALL HAS GONE OFF BOTTOM.. PDLCNT = PDLCNT - 1 #DECREMENT PADDLE COUNT. CURTIM = TIMER #RESET TIMER (USED FOR OUTBUF(LEN+1) = BELL #CALCULATING BALL SPEED). LEN = LEN + 1 #RING BELL. IF (PDLCNT == 0) [ #IF NO PADDLES LEFT, GAME OVER CALL UVT100(CUP,BMAR-1,36) OUTBUF(LEN+1) = "G" OUTBUF(LEN+2) = "A" OUTBUF(LEN+3) = "M" OUTBUF(LEN+4) = "E" LEN = LEN + 4 CALL UVT100(CUP,BMAR,36) OUTBUF(LEN+1) = "O" OUTBUF(LEN+2) = "V" OUTBUF(LEN+3) = "E" OUTBUF(LEN+4) = "R" LEN = LEN + 4 OUTBUF(LEN+1) = SHFIN #RRENABLE NORMAL CHARACTER SET LEN = LEN + 1 CALL UVT100(CUP,1,1) #HOME CURSOR CALL GETADR(PRL,OUTBUF) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) CALL EXIT #EXIT TASK ] BALLX = 10 #RESET BALL TO INITIAL LOC. BALLY = LMAR BALDIR = 135 CALL GETADR(PRL,OUTBUF) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 CALL WAIT(1,2) RETURN ] IF (RBOUND == 1) [ #IF REBOUND OFF TOP OR BOTTOM BALDIR = 180 - BALDIR IF (BALDIR < 0) #CALCULATE NEW DIRECTION BALDIR = BALDIR + 360 # # IF THIS IS A REBOUND OFF A PADDLE, WE OCCASIONALLY SELECT OTHER # THAN A 'TRUE' REBOUND. IN GENERAL, A HIT ON THE CENTER OF THE # PADDLE WILL LEND ITSELF TO BOUNCING MORE VERTICALLY, AND A HIT # ON EITHER EDGE OF THE PADDLE WILL LEND ITSELF TO SKEWING IN # THAT DIRECTION. WE ALSO OCCASIONALLY SKEW STRAIGHT UP AND DOWN # BOUNCING TO KEEP BALL FROM BOUNCING THAT WAY INDEFINITELY. # IF (PDLHIT > 0 .AND. ITMP > 1) [ #IF PADDLE HIT... IF (PDLHIT == 1 .OR. (PDLHIT == 2 .AND. BALDIR > 0 .AND. BALDIR < 90)) [ BALDIR = BALDIR - 15 #SKEW 15 DEGREES COUNTERCLOCK. IF (BALDIR == 15) BALDIR = 0 ELSE IF (BALDIR == -15) BALDIR = 330 ELSE IF (BALDIR == 285) BALDIR = 300 ] ELSE IF (PDLHIT == 3 .OR. (PDLHIT == 2 .AND. BALDIR > 270)) [ BALDIR = BALDIR + 15 #SKEW 15 DEGREES CLOCKWISE IF (BALDIR == 15) BALDIR = 30 ELSE IF (BALDIR == 75) BALDIR = 60 ELSE IF (BALDIR == 345) BALDIR = 0 ] ] ] ELSE IF (RBOUND == 2) [ #REBOUND OFF A SIDE WALL BALDIR = 360 - BALDIR IF (BALDIR == 360) #CALCULATE NEW DIRECTION BALDIR = 0 ] IF (BALDIR == 0 .AND. OLDDIR == 180) [ X = RAN(SEED) #THIS IS THE RANDOM SKEWING ITMP = X * 4 #OF STRAIGHT UP AND DOWN IF (ITMP == 2) #BOUNCING OF THE BALL BALDIR = 30 ELSE IF (ITMP == 3) BALDIR = 330 ] IF (I == 1 .AND. (BALLX == BMAR-1 .OR. BALLX == TMAR)) [ CALL UVT100(CUP,BALLX,BALLY) #SPECIAL CASE-- OUTBUF(LEN+1) = BALCHR #DISPLAY BALL ON FIRST LEN = LEN + 1 #ITERATION OF LOOP. FLAG = 1 #MARK SPECIAL CASE. ] ] IF (BALLX < BMAR .AND. BALLX >= TMAR) [ #IF NEW BALL LOCATION IN CALL UVT100(CUP,BALLX,BALLY) #RANGE, DISPLAY IT. OUTBUF(LEN+1) = BALCHR LEN = LEN + 1 ] RETURN END