📄 gorilla.bas
字号:
' Q B a s i c G o r i l l a s
'
' Copyright (C) Microsoft Corporation 1990
'
' Your mission is to hit your opponent with the exploding banana
' by varying the angle and power of your throw, taking into account
' wind speed, gravity, and the city skyline.
'
' Speed of this game is determined by the constant SPEEDCONST. If the
' program is too slow or too fast adjust the "CONST SPEEDCONST = 500" line
' below. The larger the number the faster the game will go.
'
' To run this game, press Shift+F5.
'
' To exit QBasic, press Alt, F, X.
'
' To get help on a BASIC keyword, move the cursor to the keyword and press
' F1 or click the right mouse button.
'
'Set default data type to integer for faster game play
DEFINT A-Z
'Sub Declarations
DECLARE SUB DoSun (Mouth)
DECLARE SUB SetScreen ()
DECLARE SUB EndGame ()
DECLARE SUB Center (Row, Text$)
DECLARE SUB Intro ()
DECLARE SUB SparklePause ()
DECLARE SUB GetInputs (Player1$, Player2$, NumGames)
DECLARE SUB PlayGame (Player1$, Player2$, NumGames)
DECLARE SUB DoExplosion (x#, y#)
DECLARE SUB MakeCityScape (BCoor() AS ANY)
DECLARE SUB PlaceGorillas (BCoor() AS ANY)
DECLARE SUB UpdateScores (Record(), PlayerNum, Results)
DECLARE SUB DrawGorilla (x, y, arms)
DECLARE SUB GorillaIntro (Player1$, Player2$)
DECLARE SUB Rest (t#)
DECLARE SUB VictoryDance (Player)
DECLARE SUB ClearGorillas ()
DECLARE SUB DrawBan (xc#, yc#, r, bc)
DECLARE FUNCTION Scl (n!)
DECLARE FUNCTION GetNum# (Row, Col)
DECLARE FUNCTION DoShot (PlayerNum, x, y)
DECLARE FUNCTION ExplodeGorilla (x#, y#)
DECLARE FUNCTION Getn# (Row, Col)
DECLARE FUNCTION PlotShot (StartX, StartY, Angle#, Velocity, PlayerNum)
DECLARE FUNCTION CalcDelay! ()
'Make all arrays Dynamic
'$DYNAMIC
'User-Defined TYPEs
TYPE XYPoint
XCoor AS INTEGER
YCoor AS INTEGER
END TYPE
'Constants
CONST SPEEDCONST = 500
CONST TRUE = -1
CONST FALSE = NOT TRUE
CONST HITSELF = 1
CONST BACKATTR = 0
CONST OBJECTCOLOR = 1
CONST WINDOWCOLOR = 14
CONST SUNATTR = 3
CONST SUNHAPPY = FALSE
CONST SUNSHOCK = TRUE
CONST RIGHTUP = 1
CONST LEFTUP = 2
CONST ARMSDOWN = 3
'Global Variables
DIM SHARED GorillaX(1 TO 2) 'Location of the two gorillas
DIM SHARED GorillaY(1 TO 2)
DIM SHARED LastBuilding
DIM SHARED pi#
DIM SHARED LBan&(x), RBan&(x), UBan&(x), DBan&(x) 'Graphical picture of banana
DIM SHARED GorD&(120) 'Graphical picture of Gorilla arms down
DIM SHARED GorL&(120) 'Gorilla left arm raised
DIM SHARED GorR&(120) 'Gorilla right arm raised
DIM SHARED gravity#
DIM SHARED Wind
'Screen Mode Variables
DIM SHARED ScrHeight
DIM SHARED ScrWidth
DIM SHARED Mode
DIM SHARED MaxCol
'Screen Color Variables
DIM SHARED ExplosionColor
DIM SHARED SunColor
DIM SHARED BackColor
DIM SHARED SunHit
DIM SHARED SunHt
DIM SHARED GHeight
DIM SHARED MachSpeed AS SINGLE
DEF FnRan (x) = INT(RND(1) * x) + 1
DEF SEG = 0 ' Set NumLock to ON
KeyFlags = PEEK(1047)
IF (KeyFlags AND 32) = 0 THEN
POKE 1047, KeyFlags OR 32
END IF
DEF SEG
GOSUB InitVars
Intro
GetInputs Name1$, Name2$, NumGames
GorillaIntro Name1$, Name2$
PlayGame Name1$, Name2$, NumGames
DEF SEG = 0 ' Restore NumLock state
POKE 1047, KeyFlags
DEF SEG
END
CGABanana:
'BananaLeft
DATA 327686, -252645316, 60
'BananaDown
DATA 196618, -1057030081, 49344
'BananaUp
DATA 196618, -1056980800, 63
'BananaRight
DATA 327686, 1010580720, 240
EGABanana:
'BananaLeft
DATA 458758,202116096,471604224,943208448,943208448,943208448,471604224,202116096,0
'BananaDown
DATA 262153, -2134835200, -2134802239, -2130771968, -2130738945,8323072, 8323199, 4063232, 4063294
'BananaUp
DATA 262153, 4063232, 4063294, 8323072, 8323199, -2130771968, -2130738945, -2134835200,-2134802239
'BananaRight
DATA 458758, -1061109760, -522133504, 1886416896, 1886416896, 1886416896,-522133504,-1061109760,0
InitVars:
pi# = 4 * ATN(1#)
'This is a clever way to pick the best graphics mode available
ON ERROR GOTO ScreenModeError
Mode = 9
SCREEN Mode
ON ERROR GOTO PaletteError
IF Mode = 9 THEN PALETTE 4, 0 'Check for 64K EGA
ON ERROR GOTO 0
MachSpeed = CalcDelay
IF Mode = 9 THEN
ScrWidth = 640
ScrHeight = 350
GHeight = 25
RESTORE EGABanana
REDIM LBan&(8), RBan&(8), UBan&(8), DBan&(8)
FOR i = 0 TO 8
READ LBan&(i)
NEXT i
FOR i = 0 TO 8
READ DBan&(i)
NEXT i
FOR i = 0 TO 8
READ UBan&(i)
NEXT i
FOR i = 0 TO 8
READ RBan&(i)
NEXT i
SunHt = 39
ELSE
ScrWidth = 320
ScrHeight = 200
GHeight = 12
RESTORE CGABanana
REDIM LBan&(2), RBan&(2), UBan&(2), DBan&(2)
REDIM GorL&(20), GorD&(20), GorR&(20)
FOR i = 0 TO 2
READ LBan&(i)
NEXT i
FOR i = 0 TO 2
READ DBan&(i)
NEXT i
FOR i = 0 TO 2
READ UBan&(i)
NEXT i
FOR i = 0 TO 2
READ RBan&(i)
NEXT i
MachSpeed = MachSpeed * 1.3
SunHt = 20
END IF
RETURN
ScreenModeError:
IF Mode = 1 THEN
CLS
LOCATE 10, 5
PRINT "Sorry, you must have CGA, EGA color, or VGA graphics to play GORILLA.BAS"
END
ELSE
Mode = 1
RESUME
END IF
PaletteError:
Mode = 1 '64K EGA cards will run in CGA mode.
RESUME NEXT
REM $STATIC
'CalcDelay:
' Checks speed of the machine.
FUNCTION CalcDelay!
s! = TIMER
DO
i! = i! + 1
LOOP UNTIL TIMER - s! >= .5
CalcDelay! = i!
END FUNCTION
' Center:
' Centers and prints a text string on a given row
' Parameters:
' Row - screen row number
' Text$ - text to be printed
'
SUB Center (Row, Text$)
Col = MaxCol \ 2
LOCATE Row, Col - (LEN(Text$) / 2 + .5)
PRINT Text$;
END SUB
' DoExplosion:
' Produces explosion when a shot is fired
' Parameters:
' X#, Y# - location of explosion
'
SUB DoExplosion (x#, y#)
PLAY "MBO0L32EFGEFDC"
Radius = ScrHeight / 50
IF Mode = 9 THEN Inc# = .5 ELSE Inc# = .41
FOR c# = 0 TO Radius STEP Inc#
CIRCLE (x#, y#), c#, ExplosionColor
NEXT c#
FOR c# = Radius TO 0 STEP (-1 * Inc#)
CIRCLE (x#, y#), c#, BACKATTR
FOR i = 1 TO 100
NEXT i
Rest .005
NEXT c#
END SUB
' DoShot:
' Controls banana shots by accepting player input and plotting
' shot angle
' Parameters:
' PlayerNum - Player
' x, y - Player's gorilla position
'
FUNCTION DoShot (PlayerNum, x, y)
'Input shot
IF PlayerNum = 1 THEN
LocateCol = 1
ELSE
IF Mode = 9 THEN
LocateCol = 66
ELSE
LocateCol = 26
END IF
END IF
LOCATE 2, LocateCol
PRINT "Angle:";
Angle# = GetNum#(2, LocateCol + 7)
LOCATE 3, LocateCol
PRINT "Velocity:";
Velocity = GetNum#(3, LocateCol + 10)
IF PlayerNum = 2 THEN
Angle# = 180 - Angle#
END IF
'Erase input
FOR i = 1 TO 4
LOCATE i, 1
PRINT SPACE$(30 \ (80 \ MaxCol));
LOCATE i, (50 \ (80 \ MaxCol))
PRINT SPACE$(30 \ (80 \ MaxCol));
NEXT
SunHit = FALSE
PlayerHit = PlotShot(x, y, Angle#, Velocity, PlayerNum)
IF PlayerHit = 0 THEN
DoShot = FALSE
ELSE
DoShot = TRUE
IF PlayerHit = PlayerNum THEN PlayerNum = 3 - PlayerNum
VictoryDance PlayerNum
END IF
END FUNCTION
' DoSun:
' Draws the sun at the top of the screen.
' Parameters:
' Mouth - If TRUE draws "O" mouth else draws a smile mouth.
'
SUB DoSun (Mouth)
'set position of sun
x = ScrWidth \ 2: y = Scl(25)
'clear old sun
LINE (x - Scl(22), y - Scl(18))-(x + Scl(22), y + Scl(18)), BACKATTR, BF
'draw new sun:
'body
CIRCLE (x, y), Scl(12), SUNATTR
PAINT (x, y), SUNATTR
'rays
LINE (x - Scl(20), y)-(x + Scl(20), y), SUNATTR
LINE (x, y - Scl(15))-(x, y + Scl(15)), SUNATTR
LINE (x - Scl(15), y - Scl(10))-(x + Scl(15), y + Scl(10)), SUNATTR
LINE (x - Scl(15), y + Scl(10))-(x + Scl(15), y - Scl(10)), SUNATTR
LINE (x - Scl(8), y - Scl(13))-(x + Scl(8), y + Scl(13)), SUNATTR
LINE (x - Scl(8), y + Scl(13))-(x + Scl(8), y - Scl(13)), SUNATTR
LINE (x - Scl(18), y - Scl(5))-(x + Scl(18), y + Scl(5)), SUNATTR
LINE (x - Scl(18), y + Scl(5))-(x + Scl(18), y - Scl(5)), SUNATTR
'mouth
IF Mouth THEN 'draw "o" mouth
CIRCLE (x, y + Scl(5)), Scl(2.9), 0
PAINT (x, y + Scl(5)), 0, 0
ELSE 'draw smile
CIRCLE (x, y), Scl(8), 0, (210 * pi# / 180), (330 * pi# / 180)
END IF
'eyes
CIRCLE (x - 3, y - 2), 1, 0
CIRCLE (x + 3, y - 2), 1, 0
PSET (x - 3, y - 2), 0
PSET (x + 3, y - 2), 0
END SUB
'DrawBan:
' Draws the banana
'Parameters:
' xc# - Horizontal Coordinate
' yc# - Vertical Coordinate
' r - rotation position (0-3). ( \_/ ) /-\
' bc - if TRUE then DrawBan draws the banana ELSE it erases the banana
SUB DrawBan (xc#, yc#, r, bc)
SELECT CASE r
CASE 0
IF bc THEN PUT (xc#, yc#), LBan&, PSET ELSE PUT (xc#, yc#), LBan&, XOR
CASE 1
IF bc THEN PUT (xc#, yc#), UBan&, PSET ELSE PUT (xc#, yc#), UBan&, XOR
CASE 2
IF bc THEN PUT (xc#, yc#), DBan&, PSET ELSE PUT (xc#, yc#), DBan&, XOR
CASE 3
IF bc THEN PUT (xc#, yc#), RBan&, PSET ELSE PUT (xc#, yc#), RBan&, XOR
END SELECT
END SUB
'DrawGorilla:
' Draws the Gorilla in either CGA or EGA mode
' and saves the graphics data in an array.
'Parameters:
' x - x coordinate of gorilla
' y - y coordinate of the gorilla
' arms - either Left up, Right up, or both down
SUB DrawGorilla (x, y, arms)
DIM i AS SINGLE ' Local index must be single precision
'draw head
LINE (x - Scl(4), y)-(x + Scl(2.9), y + Scl(6)), OBJECTCOLOR, BF
LINE (x - Scl(5), y + Scl(2))-(x + Scl(4), y + Scl(4)), OBJECTCOLOR, BF
'draw eyes/brow
LINE (x - Scl(3), y + Scl(2))-(x + Scl(2), y + Scl(2)), 0
'draw nose if ega
IF Mode = 9 THEN
FOR i = -2 TO -1
PSET (x + i, y + 4), 0
PSET (x + i + 3, y + 4), 0
NEXT i
END IF
'neck
LINE (x - Scl(3), y + Scl(7))-(x + Scl(2), y + Scl(7)), OBJECTCOLOR
'body
LINE (x - Scl(8), y + Scl(8))-(x + Scl(6.9), y + Scl(14)), OBJECTCOLOR, BF
LINE (x - Scl(6), y + Scl(15))-(x + Scl(4.9), y + Scl(20)), OBJECTCOLOR, BF
'legs
FOR i = 0 TO 4
CIRCLE (x + Scl(i), y + Scl(25)), Scl(10), OBJECTCOLOR, 3 * pi# / 4, 9 * pi# / 8
CIRCLE (x + Scl(-6) + Scl(i - .1), y + Scl(25)), Scl(10), OBJECTCOLOR, 15 * pi# / 8, pi# / 4
NEXT
'chest
CIRCLE (x - Scl(4.9), y + Scl(10)), Scl(4.9), 0, 3 * pi# / 2, 0
CIRCLE (x + Scl(4.9), y + Scl(10)), Scl(4.9), 0, pi#, 3 * pi# / 2
FOR i = -5 TO -1
SELECT CASE arms
CASE 1
'Right arm up
CIRCLE (x + Scl(i - .1), y + Scl(14)), Scl(9), OBJECTCOLOR, 3 * pi# / 4, 5 * pi# / 4
CIRCLE (x + Scl(4.9) + Scl(i), y + Scl(4)), Scl(9), OBJECTCOLOR, 7 * pi# / 4, pi# / 4
GET (x - Scl(15), y - Scl(1))-(x + Scl(14), y + Scl(28)), GorR&
CASE 2
'Left arm up
CIRCLE (x + Scl(i - .1), y + Scl(4)), Scl(9), OBJECTCOLOR, 3 * pi# / 4, 5 * pi# / 4
CIRCLE (x + Scl(4.9) + Scl(i), y + Scl(14)), Scl(9), OBJECTCOLOR, 7 * pi# / 4, pi# / 4
GET (x - Scl(15), y - Scl(1))-(x + Scl(14), y + Scl(28)), GorL&
CASE 3
'Both arms down
CIRCLE (x + Scl(i - .1), y + Scl(14)), Scl(9), OBJECTCOLOR, 3 * pi# / 4, 5 * pi# / 4
CIRCLE (x + Scl(4.9) + Scl(i), y + Scl(14)), Scl(9), OBJECTCOLOR, 7 * pi# / 4, pi# / 4
GET (x - Scl(15), y - Scl(1))-(x + Scl(14), y + Scl(28)), GorD&
END SELECT
NEXT i
END SUB
'ExplodeGorilla:
' Causes gorilla explosion when a direct hit occurs
'Parameters:
' X#, Y# - shot location
FUNCTION ExplodeGorilla (x#, y#)
YAdj = Scl(12)
XAdj = Scl(5)
SclX# = ScrWidth / 320
SclY# = ScrHeight / 200
IF x# < ScrWidth / 2 THEN PlayerHit = 1 ELSE PlayerHit = 2
PLAY "MBO0L16EFGEFDC"
FOR i = 1 TO 8 * SclX#
CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + 7 * SclY# + YAdj), i, ExplosionColor, , , -1.57
LINE (GorillaX(PlayerHit) + 7 * SclX#, GorillaY(PlayerHit) + 9 * SclY# - i)-(GorillaX(PlayerHit), GorillaY(PlayerHit) + 9 * SclY# - i), ExplosionColor
NEXT i
FOR i = 1 TO 16 * SclX#
IF i < (8 * SclX#) THEN CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + 7 * SclY# + YAdj), (8 * SclX# + 1) - i, BACKATTR, , , -1.57
CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + YAdj), i, i MOD 2 + 1, , , -1.57
NEXT i
FOR i = 24 * SclX# TO 1 STEP -1
CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + YAdj), i, BACKATTR, , , -1.57
FOR Count = 1 TO 200
NEXT
NEXT i
ExplodeGorilla = PlayerHit
END FUNCTION
'GetInputs:
' Gets user inputs at beginning of game
'Parameters:
' Player1$, Player2$ - player names
' NumGames - number of games to play
SUB GetInputs (Player1$, Player2$, NumGames)
COLOR 7, 0
CLS
LOCATE 8, 15
LINE INPUT "Name of Player 1 (Default = 'Player 1'): "; Player1$
IF Player1$ = "" THEN
Player1$ = "Player 1"
ELSE
Player1$ = LEFT$(Player1$, 10)
END IF
LOCATE 10, 15
LINE INPUT "Name of Player 2 (Default = 'Player 2'): "; Player2$
IF Player2$ = "" THEN
Player2$ = "Player 2"
ELSE
Player2$ = LEFT$(Player2$, 10)
END IF
DO
LOCATE 12, 56: PRINT SPACE$(25);
LOCATE 12, 13
INPUT "Play to how many total points (Default = 3)"; game$
NumGames = VAL(LEFT$(game$, 2))
LOOP UNTIL NumGames > 0 AND LEN(game$) < 3 OR LEN(game$) = 0
IF NumGames = 0 THEN NumGames = 3
DO
LOCATE 14, 53: PRINT SPACE$(28);
LOCATE 14, 17
INPUT "Gravity in Meters/Sec (Earth = 9.8)"; grav$
gravity# = VAL(grav$)
LOOP UNTIL gravity# > 0 OR LEN(grav$) = 0
IF gravity# = 0 THEN gravity# = 9.8
END SUB
'GetNum:
' Gets valid numeric input from user
'Parameters:
' Row, Col - location to echo input
FUNCTION GetNum# (Row, Col)
Result$ = ""
Done = FALSE
WHILE INKEY$ <> "": WEND 'Clear keyboard buffer
DO WHILE NOT Done
LOCATE Row, Col
PRINT Result$; CHR$(95); " ";
Kbd$ = INKEY$
SELECT CASE Kbd$
CASE "0" TO "9"
Result$ = Result$ + Kbd$
CASE "."
IF INSTR(Result$, ".") = 0 THEN
Result$ = Result$ + Kbd$
END IF
CASE CHR$(13)
IF VAL(Result$) > 360 THEN
Result$ = ""
ELSE
Done = TRUE
END IF
CASE CHR$(8)
IF LEN(Result$) > 0 THEN
Result$ = LEFT$(Result$, LEN(Result$) - 1)
END IF
CASE ELSE
IF LEN(Kbd$) > 0 THEN
BEEP
END IF
END SELECT
LOOP
LOCATE Row, Col
PRINT Result$; " ";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -