SUBROUTINE COLIDE # # THIS SUBROUTINE IS CALLED TO PROCESS A COLLISION BETWEEN THE BALL # AND A BRICK. IT BLANKS OUT THE ELIMINATED BRICK, UPDATES THE SCORE, # AND CALCULATES THE NEW (REBOUND) DIRECTION OF MOTION FOR THE BALL. # (THIS CODE IS EXTENSIVELY COMMENTED, BUT YOU NEVERTHELESS WILL # HAVE NO PRAYER OF UNDERSTANDING IT WITHOUT TAKING PENCIL AND GRAPH # PAPER IN HAND AND WORKING OUT THE CONCEPTS ON PAPER). # IMPLICIT INTEGER (A-Z) INCLUDE SY:UVT100.DAT INCLUDE SY:BRKOUT.CMN BYTE OUTBUF(3) DIMENSION PREF(3,10) DATA PREF / DOWN,DOWN,DOWN, UP,UP,UP, 0,0,0, 0,0,0, DOWNL,UPR,DOWNR, UPL,DOWNR,UPR, 0,0,0, 0,0,0, DOWNR,UPL,DOWNL, UPR,DOWNL,UPL / # CALL GETADR(PRL,OUTBUF) # # CALCULATE REBOUND DIRECTION BASED ON SURROUNDING BLOCKS. THE # DIRECTION THE BALL CAN GO IS BASED ON WHAT BRICKS ARE ADJACENT TO # THE ONE IT HIT. ITS FIRST CHOICE IS TO CONTINUE ALONG THE SAME # HORIZONTAL COMPONENT OF MOTION AND 'BOUNCE' ALONG THE VERTICAL # COMPONENT. IF THAT MOTION IS BLOCKED, ITS SECOND CHOICE IS TO CONTINUE # ALONG THE SAME VERTICAL COMPONENT, AND 'BOUNCE' ALONG THE HORIZONTAL. # IF THAT IS ALSO BLOCKED, ITS ONLY REMAINING CHOICE IS TO BOUNCE BACK # OPPOSITE TO ITS CURRENT DIRECTION (GO WHERE IT CAME FROM). # IF (MOTION == UP) #CURRENT DIRECTION IS UP BALDIR = 180 #NO PROBLEM-BOUNCE DOWN. ELSE IF (MOTION == DOWN) #CURRENT DIRECTION IS DOWN BALDIR = 0 #NO PROBLEM-BOUNCE UP. ELSE [ #CURRENT DIRECTION IS AN TMP1 = BSTATE(BALLX,BALLY) #ANGLE. CALCULATE NEW ONE. TMP2 = PREF(1,MOTION) TMP2 = IIAND(TMP1,TMP2) TMP3 = PREF(2,MOTION) TMP3 = IIAND(TMP1,TMP3) IF (TMP2 == 0 .OR. TMP2 == UP .OR. TMP2 == DOWN .OR. TMP2 == LEFT .OR. TMP2 == RIGHT) [ #OPTION ONE IS OK BALDIR = 180 - BALDIR IF (BALDIR < 0) BALDIR = BALDIR + 360 ] ELSE IF (TMP3 == 0 .OR. TMP3 == UP .OR. TMP3 == DOWN .OR. TMP3 == LEFT .OR. TMP3 == RIGHT) [ #OPTION TWO IS OK BALDIR = 360 - BALDIR IF (BALDIR == 360) BALDIR = 0 ] ELSE [ #NEITHER OPTION ONE OR TWO BALDIR = BALDIR + 180 #IS AVAILABLE, SO OPTION THREE IF (BALDIR >= 360) BALDIR = BALDIR - 360 ] ] # # A COLLISION CAN ONLY KNOCK OUT ONE BRICK. A COLLISION CAN BE EITHER # WITH A HORIZONTAL LINE, IN WHICH CASE IT IS UNAMBIGUOUS WHICH BRICK # HAS BEEN HIT, OR IT CAN BE WITH A CORNER, IN WHICH CASE WE HAVE TO # MAKE A DECISION WHICH BRICK HAS BEEN HIT BASED ON THE ANGLE OF MOTION # AND WHICH BRICKS SHARE THE CORNER HIT. EACH BRICK CONSISTS OF SIX # SEGMENTS, FOUR CORNERS AND TWO HORIZONTAL SEGMENTS. ALL SIX OF # THESE CAN BE SHARED WITH OTHER BRICKS, SO THE DECISION WHETHER TO # BLANK THEM FROM THE SCREEN IS BASED ON WHETHER THE SEGMENTS ARE # NEEDED BY OTHER UNDESTROYED BRICKS. 'ALIVE' IS AN ARRAY CONTAINING # THE STATUS OF EACH BRICK ON THE BOARD. IT IS CONSULTED TO DETERMINE # THE STATUS OF ADJACENT BRICKS. 'BSTATE' IS USED TO MAINTAIN THE # STATUS OF EACH SCREEN LOCATION WHERE BRICKS CAN BE PRESENT. IF WE # IMAGINE OURSELVES IN THE CENTER OF A SCREEN LOCATION, THE UP, DOWN, # LEFT, AND/OR RIGHT BITS OF BSTATE WILL BE SET BASED ON WHETHER THERE # STILL EXISTS A BRICK SEGMENT ALONG THAT DIRECTION. THUS A HORIZONTAL # LINE SEGMENT WILL CAUSE BSTATE TO BE SET TO 'LEFT+RIGHT', A LOWER # RIGHT CORNER WILL CAUSE BSTATE TO BE SET TO 'UP+LEFT', ETC. # IF (BSTATE(BALLX,BALLY) == LEFT+RIGHT) [ #COLLISION WITH HORIZONTAL X = BALLX Y = BALLY ] ELSE [ #COLLISION IS AT A CORNER-FIND WHICH BLOCK TO KILL IF (TSTBIT(MOTION,UP) == 1) [ IF (TSTBIT(BSTATE(BALLX,BALLY),DOWN) == 1) [ X = BALLX + 1 IF (TSTBIT(BSTATE(BALLX+1,BALLY),LEFT) == 1) Y = BALLY - 1 ELSE Y = BALLY + 1 ] ELSE IF (TSTBIT(MOTION,LEFT) == 1) [ X = BALLX IF (TSTBIT(BSTATE(BALLX,BALLY),LEFT) == 1) Y = BALLY - 1 ELSE Y = BALLY + 1 ] ELSE [ X = BALLX IF (TSTBIT(BSTATE(BALLX,BALLY),RIGHT) == 1) Y = BALLY + 1 ELSE Y = BALLY - 1 ] ] ELSE [ IF (TSTBIT(BSTATE(BALLX,BALLY),UP) == 1) [ X = BALLX - 1 IF (TSTBIT(BSTATE(BALLX-1,BALLY),LEFT) == 1) Y = BALLY - 1 ELSE Y = BALLY + 1 ] ELSE IF (TSTBIT(MOTION,LEFT) == 1) [ X = BALLX IF (TSTBIT(BSTATE(BALLX,BALLY),LEFT) == 1) Y = BALLY - 1 ELSE Y = BALLY + 1 ] ELSE [ X = BALLX IF (TSTBIT(BSTATE(BALLX,BALLY),RIGHT) == 1) Y = BALLY + 1 ELSE Y = BALLY - 1 ] ] ] # # X AND Y ARE THE 'NORMALIZED' COORDINATES OF THE BRICK WE HIT. # THUS, REGARDLESS OF WHICH OF THE SIX SEGMENTS OF A BRICK WE # HIT, X AND Y ARE POSITIONED TO THE SAME RELATIVE LOCATION, # NAMELY THE CENTER HORIZONTAL SEGMENT ON EITHER THE TOP OR THE # BOTTOM OF THE BRICK, DEPENDING ON THE BALL'S DIRECTION OF MOTION. # IF (TSTBIT(MOTION,UP) == 1) #GET INDEX TO 'ALIVE' TABLE ALIVEX = X - 3 #FOR THIS BRICK. ELSE ALIVEX = X - 2 ALIVEY = (Y-2) / 2 IF (ALIVE(ALIVEX,ALIVEY) != 0) SCORE = SCORE + 10*(6-ALIVEX) #INCREMENT SCORE. ALIVE(ALIVEX,ALIVEY) = 0 #THIS BRICK IS NOW 'DEAD' # # FOR EACH OF THE SIX BRICK LOCATIONS, THREE OF WHICH ARE ON THIS # ROW AND THREE OF WHICH ARE ON AN ADJACENT ROW, CALCULATE THE # NEW BSTATE SETTINGS, AND REDISPLAY THE NEW SETTINGS. # IF (TSTBIT(MOTION,UP) == 1) [ #SET 3 BSTATES FOR THIS ROW IF (ALIVE(ALIVEX+1,ALIVEY) == 0) [ BSTATE(X,Y) = 0 CALL CLRBIT(BSTATE(X,Y+1),LEFT) CALL CLRBIT(BSTATE(X,Y-1),RIGHT) ] IF (ALIVE(ALIVEX,ALIVEY-1) == 0) CALL CLRBIT(BSTATE(X,Y-1),UP) IF (ALIVE(ALIVEX,ALIVEY+1) == 0) CALL CLRBIT(BSTATE(X,Y+1),UP) ] ELSE IF (TSTBIT(MOTION,DOWN) == 1) [ IF (ALIVE(ALIVEX-1,ALIVEY) == 0) [ BSTATE(X,Y) = 0 CALL CLRBIT(BSTATE(X,Y+1),LEFT) CALL CLRBIT(BSTATE(X,Y-1),RIGHT) ] IF (ALIVE(ALIVEX,ALIVEY-1) == 0) CALL CLRBIT(BSTATE(X,Y-1),DOWN) IF (ALIVE(ALIVEX,ALIVEY+1) == 0) CALL CLRBIT(BSTATE(X,Y+1),DOWN) ] OUTBUF(1) = DSPCHR(BSTATE(X,Y-1)) #AND DISPLAY THEM. 'DSPCHR' OUTBUF(2) = DSPCHR(BSTATE(X,Y)) #MAPS BSTATE SETTINGS INTO OUTBUF(3) = DSPCHR(BSTATE(X,Y+1)) #DISPLAYABLE CHARACTERS CALL UVT100(CUP,X,Y-1) PRL(2) = 3 CALL WTQIO(IOWVB,5,2,,,PRL) IF (TSTBIT(MOTION,UP) == 1) [ #SAME THING FOR 3 BSTATES IF (ALIVE(ALIVEX-1,ALIVEY) == 0) [ #ON ADJACENT ROW CALL CLRBIT(BSTATE(X-1,Y-1),RIGHT) BSTATE(X-1,Y) = 0 CALL CLRBIT(BSTATE(X-1,Y+1),LEFT) ] IF (ALIVE(ALIVEX,ALIVEY-1) == 0) CALL CLRBIT(BSTATE(X-1,Y-1),DOWN) IF (ALIVE(ALIVEX,ALIVEY+1) == 0) CALL CLRBIT(BSTATE(X-1,Y+1),DOWN) OUTBUF(1) = DSPCHR(BSTATE(X-1,Y-1)) OUTBUF(2) = DSPCHR(BSTATE(X-1,Y)) OUTBUF(3) = DSPCHR(BSTATE(X-1,Y+1)) CALL UVT100(CUP,X-1,Y-1) CALL WTQIO(IOWVB,5,2,,,PRL) ] ELSE IF (TSTBIT(MOTION,DOWN) == 1) [ IF (ALIVE(ALIVEX+1,ALIVEY) == 0) [ CALL CLRBIT(BSTATE(X+1,Y-1),RIGHT) BSTATE(X+1,Y) = 0 CALL CLRBIT(BSTATE(X+1,Y+1),LEFT) ] IF (ALIVE(ALIVEX,ALIVEY-1) == 0) CALL CLRBIT(BSTATE(X+1,Y-1),UP) IF (ALIVE(ALIVEX,ALIVEY+1) == 0) CALL CLRBIT(BSTATE(X+1,Y+1),UP) OUTBUF(1) = DSPCHR(BSTATE(X+1,Y-1)) OUTBUF(2) = DSPCHR(BSTATE(X+1,Y)) OUTBUF(3) = DSPCHR(BSTATE(X+1,Y+1)) CALL UVT100(CUP,X+1,Y-1) CALL WTQIO(IOWVB,5,2,,,PRL) ] PRL(2) = 1 RETURN END