'===========================================================================
' Subject: TOAD HOP (FROGGER CLONE)           Date: 07-15-96 (16:16)       
'  Author: The ABC Programmer                 Code: QB, QBasic, PDS        
'  Origin: Adapted from Pascal code         Packet: GAMES.ABC
'===========================================================================
'==============================================================
' TOAD HOP (Frogger Clone) Programmed by William Yu (07-15-96)
'  Adapted from Pascal code (Frogger v0.90) by Jonas Maebe
'  Thanks for the tiles! :)
'
' System Recommendations:
'    486/16MHz or better or compile for best performance
'    EGA or better
'
' I have never played the actual Frogger game, so I have no
' idea if this is even close to it :)
'
' Improvements (Just some suggestions)
' ------------------------------------
'    Levels!  Try removing some of the cars or turtle
'             and adding them later as the level increases.
'             As well as the speed of course.
'    Score?   Have frogger pick up misc. material laying on
'             the street or something <shrug>.
' Background? Because of my crude collision detection routine,
'             you might want to limit this.
'--------------------------------------------------------------

DEFINT A-Z
DECLARE SUB UpDate.Sprite ()
DECLARE SUB Initialize.Sprites ()
DECLARE SUB Draw.Sprite (Sprite() AS INTEGER, XCor%, YCor%)
DECLARE SUB Read.Sprite (Sprite() AS INTEGER)
DECLARE SUB Draw.Background ()
DECLARE SUB Display.Lives ()

DIM SHARED Frog(100) AS INTEGER
DIM SHARED Car1(100) AS INTEGER
DIM SHARED Car2(100) AS INTEGER
DIM SHARED Car3(100) AS INTEGER
DIM SHARED Car4(100) AS INTEGER
DIM SHARED Turtle(100) AS INTEGER
DIM SHARED Turtle2(100) AS INTEGER
DIM SHARED Turtle3(100) AS INTEGER
DIM SHARED XCor, XCor2, XCor3, XCor4, XCor5       ' You can modify the
DIM SHARED YCor, YCor2, YCor3, YCor4, YCor5       ' value of any of
DIM SHARED Speed1, Speed2, Speed3, Speed4, Speed5 ' these variables
DIM SHARED FrogX, FrogY, Lives, Clock             ' if you want to.
DIM SHARED Finished, Hit                          ' Boolean variables

TIMER ON                           ' Remove this if you do not want
ON TIMER(1) GOSUB DecreaseTime     ' to impose a time limit

CONST False = 0
CONST True = NOT False
CONST Apart = 20     ' Distance from one lane to the next (10 < Apart < 30)
CONST Seconds = 30   ' Maximum allotted time to complete level

Clock = Seconds
Lives = 3            ' Number of lives REMAINING.  As many as you want.
                     ' Maximum of four will be displayed, the rest are not.

YCor = 160                  ' Starting position of first sprite  '
YCor2 = YCor - Apart        ' so on and so forth                 '
YCor3 = YCor - (Apart * 2)  ' .                                  '
YCor4 = YCor - (Apart * 3)  ' .                                  '
YCor5 = YCor - (Apart * 5)  ' You can add more if you wish       '

SCREEN 7, , 1, 0               ' Start by hiding everything
PRINT "Initializing data..."   ' Just so the user doesn't fall asleep...
PCOPY 1, 0                     ' Display the message on the visual page

Initialize.Sprites  ' Read in all the sprite data
Draw.Background     ' Spiffy background, create your own artistic scene

FrogX = 130: FrogY = YCor + Apart    ' Starting position of your spiffy frog
Draw.Sprite Frog(), FrogX, FrogY     ' Let's draw the handsome dude

I = -60                              ' Okay, some weird values here.
I2 = 0                               ' These are for the sprites to
I3 = -80                             '  scroll across the screen smoothly.
I4 = 0                               ' Mostly guess & test values here
I5 = 0                               '  but it works.
XCor = I                             ' The real location of each sprite
XCor2 = I2                           '  to detect collision.
XCor3 = I3
XCor4 = I4
XCor5 = I5
UpDate.Sprite                        ' Draws all the sprites onto the screen

Speed1 = 2                           ' Speed of sprite one and so on...
Speed2 = -3                          ' (-) Negative = Sprite moves left
Speed3 = 6                           ' (+) Positive = Sprite moves right
Speed4 = -2                          ' Increase numbers for a faster
Speed5 = -2                          ' and much more challenging game!

Finished = False                     ' Game just started.

DO                                   ' Main Game Loop
    I = I + Speed1: XCor = I         ' Let's move the sprites
    IF XCor >= 32 THEN I = -83
    I2 = I2 + Speed2: XCor2 = I2
    IF XCor2 <= -69 THEN I2 = 45
    I3 = I3 + Speed3: XCor3 = I3
    IF XCor3 > 60 THEN I3 = -27
    I4 = I4 + Speed4: XCor4 = I4
    IF XCor4 <= -64 THEN I4 = 50
    I5 = I5 + Speed5: XCor5 = I5
    IF XCor5 <= -32 THEN I5 = 48
    UpDate.Sprite                    ' Update the screen to reflect new values
    IF Finished THEN                 ' Really not necessary :)
       PCOPY 2, 1                    ' You can end the game here.
       LOCATE 2, 16: COLOR 2
       PRINT "Please go back!"; CHR$(34); "   "
       PCOPY 1, 2
       Finished = NOT Finished
    END IF
    IF Hit = True THEN
      LINE (20, 65)-(250, 85), 0, BF
      LINE (20, 65)-(250, 85), 15, B
      IF Clock <= 0 THEN
        LOCATE 10, 5: COLOR 13: PRINT "Sorry, time's up Mr. Slug!"
      ELSE
        IF FrogY = YCor5 THEN
          IF FrogX <= -1 THEN
            LOCATE 10, 5: COLOR 11: PRINT "You went over a waterfall!"
          ELSE
            LOCATE 10, 5: COLOR 11: PRINT "Try staying ON their backs"
          END IF
        ELSE
          LOCATE 10, 5: COLOR 14: PRINT "Attention: Look both ways!"
        END IF
      END IF
      PCOPY 1, 0
      T! = TIMER
      DO
      LOOP UNTIL INKEY$ = "" AND TIMER - T! > 1.5
      Clock = Seconds                     ' Reset Clock
      FrogY = YCor + Apart: FrogX = 130   ' Restart frogger
      Lives = Lives - 1                   ' Decrease lives
      IF Lives = -1 THEN EXIT DO          ' If no more, then game over
      PCOPY 2, 1
      LINE (271, 0)-(319, 11), 0, BF
      Display.Lives
      PCOPY 1, 2
    END IF
LOOP                                 ' LOOP Until Finished

SCREEN 7, , 0, 0                     ' Funky ending screen
RANDOMIZE TIMER
DO
  X = INT(RND * 320) - 5
  Y = INT(RND * 206) - 5
  PSET (X, Y), 0
  IF K& > 25000 THEN
    LINE (X - 1, Y - 1)-(X + 10, Y + 10), 0
    LINE (X, Y)-(X - 10, Y - 10), 0
  END IF
  IF K& > 37500 THEN LINE (X - 1, Y - 1)-(X + 10, Y + 10), 0, BF
  K& = K& + 1
LOOP UNTIL INKEY$ <> "" OR K& > 40000
CLS
LOCATE 1, 1: PRINT "Thanks for playing!"
END

DecreaseTime:
  Clock = Clock - 1
RETURN

' Frogger
DATA 00,00,00,00,02,02,00,00,00,00
DATA 00,00,00,12,10,10,12,00,00,00
DATA 00,10,00,00,10,10,00,00,10,00
DATA 00,00,10,10,10,02,10,10,00,00
DATA 00,00,00,10,02,10,10,00,00,00
DATA 00,00,00,10,10,02,10,00,00,00
DATA 00,00,00,10,02,10,10,00,00,00
DATA 00,00,10,10,10,02,10,10,00,00
DATA 00,10,00,10,10,10,10,00,10,00
DATA 00,00,00,00,10,10,00,00,00,00

' Normal Car
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,12,12,12,00,00,00,00
DATA 00,00,12,04,11,11,11,00,00,00
DATA 12,12,12,12,04,12,12,12,12,00
DATA 04,08,08,08,04,04,08,08,08,04
DATA 00,00,07,00,00,00,00,07,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00

' Flat Car
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,07,07,00,00,00,07,07,00
DATA 00,01,09,09,01,01,01,09,09,00
DATA 14,01,09,09,09,09,08,08,09,09
DATA 01,09,09,09,09,15,09,09,08,09
DATA 01,09,09,09,09,15,09,09,08,09
DATA 14,01,09,09,09,09,08,08,09,09
DATA 00,01,09,09,01,01,01,09,09,00
DATA 00,00,07,07,00,00,00,07,07,00
DATA 00,00,00,00,00,00,00,00,00,00

' Race Car
DATA 00,00,00,00,00,00,00,00,00,00
DATA 12,00,07,08,00,00,00,00,00,00
DATA 12,00,07,08,00,00,07,00,12,04
DATA 12,00,04,04,12,04,08,00,12,04
DATA 12,04,04,12,12,12,12,12,12,04
DATA 12,00,04,04,12,04,08,00,12,04
DATA 12,00,07,08,00,00,07,00,12,04
DATA 12,00,07,08,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00

' Bulldozer
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,14,14,00,00,00,00,00,00,00
DATA 00,07,08,14,00,07,08,00,07,08
DATA 00,07,08,00,14,14,14,14,14,08
DATA 00,07,08,00,00,14,08,07,14,08
DATA 00,07,08,00,14,14,06,09,14,08
DATA 00,07,08,00,00,14,08,07,14,08
DATA 00,07,08,00,14,14,14,14,14,08
DATA 00,07,08,14,00,07,08,00,07,08
DATA 00,14,14,00,00,00,00,00,00,00

' Turtle
DATA 00,00,00,05,00,00,00,00,05,00
DATA 00,00,00,00,05,05,05,05,00,00
DATA 00,00,05,06,06,06,05,06,05,00
DATA 12,05,05,05,06,05,06,05,06,05
DATA 00,03,06,06,06,06,06,06,06,05
DATA 00,03,05,05,06,06,06,05,06,05
DATA 12,05,05,06,05,06,06,06,05,05
DATA 00,00,05,05,06,06,06,05,05,00
DATA 00,00,00,00,05,05,05,05,00,00
DATA 00,00,00,05,00,00,00,00,05,00

' Turtle Half Under Water
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,06,06,06,05,06,00,00
DATA 12,00,05,05,06,05,06,05,06,00
DATA 00,00,06,06,06,06,06,06,06,00
DATA 00,00,05,05,06,06,06,05,06,00
DATA 12,00,05,06,05,06,06,06,05,00
DATA 00,00,00,05,06,06,06,05,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00

' Turtle Under Water
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,06,05,06,00,00,00
DATA 00,00,00,06,06,06,06,06,00,00
DATA 00,00,00,05,06,06,06,05,00,00
DATA 00,00,00,00,05,06,06,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00

SUB Display.Lives

IF Lives > 4 THEN L = 4 ELSE L = Lives
FOR I = 1 TO L
  Draw.Sprite Frog(), 263 + I * 12, 1
NEXT I

END SUB

SUB Draw.Background

LINE (0, 0)-(270, 199), 14, B
LINE (1, 198)-(269, 175), 8, BF
LOCATE 2, 2: COLOR 2
PRINT "Mother Toad: "; CHR$(34); "Please come home!"; CHR$(34)
LINE (1, YCor5 - 6)-(269, YCor5 + 15), 1, BF
LINE (1, YCor5 + 15)-(269, YCor4 - 7), 8, BF
LINE (1, YCor5 - 6)-(269, YCor5 - 26), 2, BF
DO
  RANDOMIZE TIMER
  Y = ((YCor5 - 6) - (YCor5 - 26) + 1) * RND + (YCor5 - 26)
  X = RND * 269
  PSET (X, Y), 10
  N = N + 1
LOOP UNTIL N = 100
Display.Lives
PCOPY 1, 2     ' Save Background

END SUB

SUB Draw.Sprite (Sprite() AS INTEGER, XCor, YCor)

I = 0
FOR Y = 1 TO 10
  FOR X = 1 TO 10
    I = I + 1
    IF Sprite(I) > 0 THEN PSET (XCor + X - 1, YCor + Y - 1), Sprite(I)
  NEXT X
NEXT Y

END SUB

SUB Initialize.Sprites

Read.Sprite Frog()
Read.Sprite Car1()
Read.Sprite Car2()
Read.Sprite Car3()
Read.Sprite Car4()
Read.Sprite Turtle()
Read.Sprite Turtle2()
Read.Sprite Turtle3()
CLS

END SUB

SUB Read.Sprite (Sprite() AS INTEGER)

I = 0
FOR Y = 1 TO 10
  FOR X = 1 TO 10
    I = I + 1
    READ Sprite(I)
    IF Sprite(I) > 0 THEN PSET (X, Y), Sprite(I)
  NEXT X
NEXT Y

END SUB

SUB UpDate.Sprite

LINE (0, 0)-(319, 199), 0, BF  ' Clear the screen for next update
PCOPY 2, 1                     ' Restore the saved background

IF XCor5 < 5 OR XCor5 > 25 THEN Under = 1
IF XCor5 < -15 OR XCor5 > 35 THEN Under = 2
IF XCor5 < -25 THEN Under = 3
IF XCor5 > 5 AND XCor5 < 30 THEN Under = 0
IF FrogY = YCor5 THEN FrogX = FrogX + Speed5  ' Frog on Turtle's back
Hit = False: NoMore = False
   
FOR Y = 1 TO 4
   IF NOT NoMore THEN A$ = INKEY$   ' Depending upon the position of Frogger
   FOR X = 1 TO 3
     IF A$ <> "" AND NOT Hit THEN
       IF LEN(A$) > 1 THEN Char = -ASC(RIGHT$(A$, 1)) ELSE Char = ASC(A$)
          SELECT CASE Char
            CASE 27
               END
            CASE -72  ' Up
               IF FrogY > YCor5 - Apart THEN
                 FrogY = FrogY - Apart
                 IF FrogY = YCor5 - Apart THEN Finished = True
               END IF
            CASE -75  ' Left
               IF FrogX > 9 THEN
                 FrogX = FrogX - 10
               END IF
            CASE -77  ' Right
               IF FrogX < 260 THEN
                 FrogX = FrogX + 10
               END IF
            CASE -80  ' Down
               IF FrogY < 200 - Apart THEN
                 FrogY = FrogY + Apart
               END IF
          END SELECT
          A$ = ""
     END IF
     ' Cheap way of detecting a collision
     IF (FrogY < YCor + Apart) AND (FrogY > YCor - (Apart * 4)) THEN
       A = POINT(FrogX + 1, FrogY + 5)
       B = POINT(FrogX + 8, FrogY + 5)
       C = POINT(FrogX + 5, FrogY + 5)
       IF (A OR B OR C) > 0 THEN Hit = True
     END IF
     IF FrogY = YCor5 THEN NoMore = True  ' Frogger is on the river
     Draw.Sprite Car1(), XCor, YCor
     Draw.Sprite Car2(), XCor2, YCor2
     Draw.Sprite Car3(), XCor3, YCor3
     Draw.Sprite Car4(), XCor4, YCor4
     IF Under = 1 THEN          ' Half way below water
       Draw.Sprite Turtle2(), XCor5, YCor5
     ELSEIF Under = 2 THEN      ' Almost under water
       Draw.Sprite Turtle3(), XCor5, YCor5
     ELSEIF Under = 3 THEN      ' Submerged under water
       LINE (1, YCor5 - 4)-(269, YCor5 + 12), 1, BF
     ELSEIF Under = 0 THEN      ' Completely above water
       Draw.Sprite Turtle(), XCor5, YCor5
     END IF
     XCor = XCor + 30        ' Distance between common sprites
     XCor2 = XCor2 + 30      ' To chain three sprites at a time
     XCor3 = XCor3 + 90
     XCor4 = XCor4 + 30
     XCor5 = XCor5 + 15
   NEXT X
   XCor = XCor + 25          ' Extra distance between the sprites
   XCor2 = XCor2 + 25        ' This allows room for your frog to pass
   XCor4 = XCor4 + 25
   XCor5 = XCor5 + 35
NEXT Y
IF FrogY = YCor5 THEN              ' Frogger is on the river.
  C = POINT(FrogX + 5, FrogY + 5)  ' Check if frog is on a turtle
  IF C = 1 THEN Hit = True         ' or not.
  IF FrogX <= -1 THEN Hit = True   ' Or if the frog sits too long
END IF
Draw.Sprite Frog(), FrogX, FrogY   ' Update frog position
LINE (0, 0)-(270, 199), 14, B      ' Redraw the border
LINE (271, 12)-(319, 199), 0, BF   ' Hide tailing sprites
LOCATE 4, 36: COLOR 15: PRINT Clock
IF Clock = 0 THEN Hit = True
PCOPY 1, 0                         ' Display to finished screen

END SUB
