rem YTRON
rem
rem Author: Jacob Busby (Jacob.Busby@hants.gov.uk)
rem
rem Controls
rem
rem  Direction keys - move in appropriate direction.
rem  R1 - Jump
rem  Press X to restart after a crash.
rem  Press O to restart after Game Over.
rem 
rem Notes:
rem
rem  Engine loosely based based on YNIBBLES
rem
rem Known bugs/ineficiencies:
rem
rem  Very slight slowdown if you play one player for long
rem  enough.
rem
rem Change History
rem
rem 01/08/01 Decide to develop Tron using YNIBBLES as a 
rem          template.
rem 07/08/01 Working game. Still to do: Jump guage.
rem 17/08/01 (free time at last) Jump guage now done.

rem Sanity variables

TRUE = 1
FALSE = 0

rem PS2 controller variables

EX = 16384
OH = 8192
UP = 16
DOWN = 64
LEFT = 128
RIGHT = 32
R1 = 2048

rem Screen variables

GRIDHEIGHT = 49
GRIDWIDTH = 49
SQUARESIZE = 10

rem Game variables.
rem
rem Change these variables to alter various aspects of the
rem game. The variables are as follows:
rem
rem  PLAYERS - The number of players (1-2)
rem  SPEED - The speed at which the game is played.
rem  STARTLIVES - The number of lives each bike starts 
rem               with.
rem  CHAMELEONBIKES - Do bikes change colour over time?
rem  JUMPSIZE - The size each jump covers. If set to zero
rem             jumps are not in use.
rem  GUAGESPEED - Speed at which the jump guage fills up.

PLAYERS = 2
SPEED = 0.05
STARTLIVES = 5
CHAMELEONBIKES = TRUE
JUMPSIZE = 5
GUAGESPEED = 10

rem OK. Let's play.

Play_Game()

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Play_Game()

  while (TRUE = TRUE)
    Set_Up()
    GameOver = FALSE
    while (GameOver = FALSE)
      Draw_Grid()
      Create_New_Bike()
      Set_Up_Per_Match()
      while (RestartMatch = FALSE)
        Determine_Direction_Change()
        Update_Bike()
        Update_Jump_Guage()
        Evaluate_Strikes()
        wait SPEED
      wend
      Create_Grid()
    wend
  wend

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Set_Up_Per_Match()

  pot = 0
  Pot_Red = 0
  Pot_Green = 0
  Pot_Blue = 0
  RestartMatch = FALSE
  for player = 1 to PLAYERS
    JumpGuage(player) = 0
  next player

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Create_Grid()

  for h = 1 to GRIDHEIGHT
    for w = 1 to GRIDWIDTH
      if h = 1 or h = GRIDHEIGHT or w = 1 or w = GRIDWIDTH then
        grid(w, h) = 1
      else 
        grid(w, h) = 0
      fi
      initgrid(w, h) = grid(w, h)
    next w
  next h

end sub

rem ------------------------------------------------------
rem Draw_Grid
rem
rem This routine uses the data in the grid array to draw 
rem the current grid.
rem ------------------------------------------------------

sub Draw_Grid()

  clear window
  scry = 0
  setrgb 1, 0, 255, 0
  for h = 1 to GRIDHEIGHT
    scrx = 0
    for w = 1 to GRIDWIDTH
      if grid(w, h) <> 0 then
        if grid(w, h) = 1 setrgb 1, 0, 255, 0
        fill rectangle scrx, scry to scrx + SQUARESIZE, scry + SQUARESIZE
      fi
      scrx = scrx + SQUARESIZE
    next w
    scry = scry + SQUARESIZE
  next h

  rem Now draw the lines that mark out the "pot" and 
  rem the two areas for Lives and score.

  setrgb 1, 255, 255, 255
  line (GRIDWIDTH * SQUARESIZE) + 20, 0 to (GRIDWIDTH * SQUARESIZE) + 20, (GRIDHEIGHT * SQUARESIZE)
  line (GRIDWIDTH * SQUARESIZE) + 20, ((GRIDHEIGHT * SQUARESIZE) / 2) - 20 to 640, ((GRIDHEIGHT * SQUARESIZE) / 2) - 20
  line (GRIDWIDTH * SQUARESIZE) + 20, ((GRIDHEIGHT * SQUARESIZE) / 2) + 20 to 640, ((GRIDHEIGHT * SQUARESIZE) / 2) + 20 

  Update_Text()

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Create_New_Bike()

  BikeHead(1,1) = 4
  BikeHead(1,2) = (GRIDHEIGHT / 2)
  if PLAYERS > 1 then
    BikeHead(2,1) = GRIDWIDTH - 3
    BikeHead(2,2) = (GRIDHEIGHT / 2) + 1
  fi
  for player = 1 to PLAYERS
    if player = 1 then
      dirx(player,1) = 1
    else 
      dirx(player,1) = -1
    fi
    diry(player,1) = 0
  next player

end sub

rem ------------------------------------------------------
rem Determine_Direction_Change
rem
rem This routine reads the input from the joypads and 
rem adjusts the bikes direction accordingly.
rem ------------------------------------------------------
 
sub Determine_Direction_Change()

  for player = 1 to PLAYERS
    dirx(player,2) = dirx(player,1)
    diry(player,2) = diry(player,1)
    if player = 1 then
      k = peek("port1")
    else
      k = peek("port2")
    fi
    if and(k, DOWN) <> 0 then
      dirx(player,1) = 0
      diry(player,1) = 1
      if diry(player,2) = -1 then
        diry(player,1) = -1 
      fi
    elsif and(k, UP) <> 0 then
      dirx(player,1) = 0
      diry(player,1) = -1
      if diry(player,2) = 1 then
        diry(player,1) = 1 
      fi
    elsif and(k, LEFT) <> 0 then
      dirx(player,1) = -1
      diry(player,1) = 0
      if dirx(player,2) = 1 then
        dirx(player,1) = 1 
      fi
    elsif and(k, RIGHT) <> 0 then
      dirx(player,1) = 1
      diry(player,1) = 0
      if dirx(player,2) = -1 then
        dirx(player,1) = -1 
      fi
    elsif and(k, R1) <> 0 and JumpGuage(player) = GUAGESPEED then
      PlayerJumped = TRUE
      dirx(player,1) = dirx(player,1) * JUMPSIZE
      diry(player,1) = diry(player,1) * JUMPSIZE
      JumpGuage(player) = 0
    fi  
    newBikeX(player) = BikeHead(player,1) + dirx(player,1)
    newBikeY(player) = BikeHead(player,2) + diry(player,1)
    if newBikeX(player) < 0 newBikeX(player) = 0
    if newBikeX(player) > GRIDWIDTH newBikeX(player) = GRIDWIDTH
    if newBikeY(player) < 0 newBikeY(player) = 0
    if newBikeY(player) > GRIDWIDTH newBikeY(player) = GRIDHEIGHT
    if PlayerJumped = TRUE then 
      dirx(player,1) = dirx(player,1) / JUMPSIZE
      diry(player,1) = diry(player,1) / JUMPSIZE
      PlayerJumped = FALSE
    fi
  next player

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Update_Bike()

  for player = 1 to PLAYERS
    if CHAMELEONBIKES = TRUE then
      if player = 1 setrgb 1, 0, (255 - Pot_Green), 255
      if player = 2 setrgb 1, 255, (255 - Pot_Green), 0
    else
      if player = 1 setrgb 1, 0, 0, 255
      if player = 2 setrgb 1, 255, 0, 0
    fi
    fill rectangle (BikeHead(player,1)-1) * SQUARESIZE, (BikeHead(player,2)-1) * SQUARESIZE to BikeHead(player,1) * SQUARESIZE, BikeHead(player,2) * SQUARESIZE
    grid(BikeHead(player,1),BikeHead(player,2)) = 1
    BikeHead(player,1) = newBikeX(player)
    BikeHead(player,2) = newBikeY(player)
    if player = PLAYERS pot = pot + 1
    if mod(Pot,10) = 0 Update_Pot()
  next player  

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Update_Jump_Guage()

  for player = 1 to PLAYERS
    if JumpGuage(player) < GUAGESPEED then
      JumpGuage(player) = JumpGuage(player) + 1

rem   Set up the appropriate colour for the guage

     if CHAMELEONBIKES = TRUE then
       if player = 1 setrgb 1, 0, (255 - Pot_Green), 255
       if player = 2 setrgb 1, 255, (255 - Pot_Green), 0
     else
       if player = 1 setrgb 1, 0, 0, 255
       if player = 2 setrgb 1, 255, 0, 0
     fi

rem   If just jumped, set guage back to "black"

      if JumpGuage(player) = 1 then
        clear fill rectangle (GRIDWIDTH * SQUARESIZE + 100), ((player - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20))  + 80 to (GRIDWIDTH * SQUARESIZE + 140), ((player - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20)) + 90
      fi

rem   Update the guage.

      rectangle (GRIDWIDTH * SQUARESIZE + 100), ((player - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20))  + 80 to (GRIDWIDTH * SQUARESIZE) + 140, ((player - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20)) + 90
      fill rectangle (GRIDWIDTH * SQUARESIZE + 100), ((player - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20))  + 80 to (GRIDWIDTH * SQUARESIZE + 100 + ((JumpGuage(player) / GUAGESPEED) * 40)), ((player - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20)) + 90
    fi
  next player

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Evaluate_Strikes()

  for player = 1 to PLAYERS

    if grid(BikeHead(player,1),BikeHead(player,2)) = 1 then
      lives(player) = lives(player) - 1
      if (player = 1 and PLAYERS = 2) then
        score(2) = score(2) + pot
        Update_Text()
      else
        if player = PLAYERS then
          score(1) = score(1) + pot
          Update_Text()
        fi
      fi
      clear fill rectangle (GRIDWIDTH * SQUARESIZE + 24), ((GRIDHEIGHT * SQUARESIZE) / 2) - 18 to 640, ((GRIDHEIGHT * SQUARESIZE) / 2) + 18
      setrgb 1, 255, 255, 255

rem Suss out if this a crash or game over

      if lives(player) = 0 then
        GameOver = TRUE
        text (GRIDWIDTH * SQUARESIZE + 35), ((GRIDHEIGHT * SQUARESIZE) / 2) + 5, "GAME OVER!"
       Wait_For_Key(OH)
      else
        text (GRIDWIDTH * SQUARESIZE + 60), ((GRIDHEIGHT * SQUARESIZE) / 2) + 5, "CRASH"
        Wait_For_Key(EX)
      fi

rem Now restart the match

      RestartMatch = TRUE
    fi  
  next player

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Update_Text()

  setrgb 1, 255, 255, 255
  for user = 1 to PLAYERS
    clear fill rectangle (GRIDWIDTH * SQUARESIZE + 90), ((user - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20)) + 40 to 640, ((user - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20)) + 90
    text (GRIDWIDTH * SQUARESIZE + 30), ((user - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20))  + 50, "SCORE: " + str$(score(user))
    text (GRIDWIDTH * SQUARESIZE + 30), ((user - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20))  + 70, "LIVES: " + str$(lives(user))
    text (GRIDWIDTH * SQUARESIZE + 30), ((user - 1) * (((GRIDHEIGHT * SQUARESIZE) / 2) + 20))  + 90, "JUMPS:"
  next user

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Update_Pot()

  Pot_Green = min(pot,255)
  Pot_Red = min((pot - Pot_Green),255)
  Pot_Blue = min((pot - Pot_Red - Pot_Green),255)

  setrgb 1, Pot_Red, Pot_Green, Pot_Blue 
  setrgb 2, Pot_Red, Pot_Green, Pot_Blue 
  setrgb 3, 255,255,255

  gtriangle (GRIDWIDTH * SQUARESIZE + 24), ((GRIDHEIGHT * SQUARESIZE) / 2) - 18 to (GRIDWIDTH * SQUARESIZE + 24), ((GRIDHEIGHT * SQUARESIZE) / 2) + 18 to 640, ((GRIDHEIGHT * SQUARESIZE) / 2) - 18

  setrgb 2,255,255,255
  gtriangle (GRIDWIDTH * SQUARESIZE + 24), ((GRIDHEIGHT * SQUARESIZE) / 2) + 18 to 640, ((GRIDHEIGHT * SQUARESIZE) / 2) - 18 to 640, ((GRIDHEIGHT * SQUARESIZE) / 2) + 18

end sub

rem ------------------------------------------------------
rem ------------------------------------------------------

sub Set_Up()

  close window
  open window 640, 512
  dim grid(GRIDWIDTH, GRIDHEIGHT)
  dim initgrid(GRIDWIDTH, GRIDHEIGHT)

rem BikeHead
rem  1: Which player
rem  2: X co-ordinate (1), Y co-ordinate (2)

  dim BikeHead(PLAYERS,2)

rem dirx
rem  1: Which player
rem  2: Current direction(1), Previous direction(2)

  dim dirx(PLAYERS,2)
  dim diry(PLAYERS,2)
  dim newBikeX(PLAYERS)
  dim newBikeY(PLAYERS)

  dim score(PLAYERS)
  dim lives(PLAYERS)
  dim JumpGuage(PLAYERS)

  for player = 1 to PLAYERS
    lives(player) = STARTLIVES
    score(player) = 0
    JumpGuage(player) = 0
  next player
  Create_Grid()

end sub

rem ------------------------------------------------------
rem Wait_For_Key(KeyNeeded)
rem ------------------------------------------------------

sub Wait_For_Key(KeyNeeded)

  KeyPress1 = peek("port1")
  KeyPress2 = peek("port2")
  while (KeyPress1 <> KeyNeeded and KeyPress2 <> KeyNeeded) 
    KeyPress1 = peek("port1")
    KeyPress2 = peek("port2")
    wait 0.05
  wend

end sub


