TGC Codebase Backup



TRON : 2 by vibe runner

14th Nov 2006 9:06
Summary

A simple TRON lightcycle game for 2-4 players at the same keyboard. Menu screen with various screen options and delays/fps for fast CPUs.



Description

A simple TRON lightcycle game for 2-4 players at the same keyboard. Menu screen with various screen options and delays/fps for fast CPUs. Gameplay modes are Easy/Hard, easy you don't die if you hit your own trail; and Border modes, Arena Border anyone dies if they hit the screen border; random it changes randomly to a player colour (so only they can pass), updated every second or so; Champion is the border is the colour of the last player, so they can pass through it.

Code is pretty good, I think, structured okay, but I use a lot of GOSUBs and not Functions. That might change by Version 2, which should have simple AI.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    
REMSTART =========================================

         TRON

         09/11/2006
         v1.0  First Version

         13/11/2006
         v1.1  Border Modes
               Replay option
               Consolidate Menus
               Game, Keyboard, FPS settings
               Tidy Variables/Code
               Tweaks

         14/11/2006
         v1.2  Get to work on different monitors

REMEND `==========================================

` Version at top of code to remind programmers to update it!!
vers$ = "v1.2"

` Load the sprite image, set x/y maximums and halfs
GOSUB load_media

` Set screen SYNC on
SYNC ON

` Used for testing other boolean TRUE and FALSE conditions
true AS BOOLEAN
false AS BOOLEAN
TRUE = 1
FALSE = 0

REMSTART =========================================

         VARIOUS VARIABLES

         CREATE MAIN VARIABLES
         LOAD WITH DEFAULT DATA

REMEND `==========================================

` maximum number of players in a game
maxplayers AS BYTE
maxplayers = 4

` actual number of players
number_of_players AS BYTE
number_of_players = 0

` number of surviving players
survivors AS BYTE
survivors = 0

` used in game_delay timing
counter AS DWORD
counter = 0

` amount of time to delay game (for fast CPUs)
game_delay AS INTEGER
game_delay = -1

` amount of delay to keys
` (also know as "key sensitivity")
key_delay AS BYTE
key_delay = 100

` sync rate (frames per second, 0 = as fast as possible)
sync_rate AS BYTE
sync_rate = 0

` game difficulty
` 0 = easy (can ride through own trail
` 1 = hard (cannot touch own trail, can touch own-colour borders)
` to have hard crash into walls use "ARENA" mode
difficulty AS BOOLEAN
difficulty = 0

` border mode
` 0 - off
` 1 - arena, static colour
` 2 - random, picks randomly between players for a while
` 3 - champion, winner of previous race
` border_counter times change of borders
border_mode AS BYTE
border_mode = 0

border_colour AS DWORD
border_colour = 0

border_counter AS DWORD
border_counter = 0

` when set to true, a new game should be started
` when set to false a restat game is initiated
new_game AS BOOLEAN
new_game = TRUE

` collision detection (based on colour of a coordinate)
hit_spot AS DWORD
hit_spot = 0

` collision detection
collision AS BOOLEAN
collision = FALSE

` Some monitors don't different black variables
` EG my CRT monitor is 0, my school LCD is 4278190080
` so find out what it is and store it for testing vs black
back_black AS DWORD

` A few strings. They don't need initial values.
` input key
pressed$ AS STRING
` difficulty text
difficulty_text$ AS STRING
` border type text
border_text$ AS STRING

` humour string
tron_man$ AS STRING

` A bit of humour, work it out!
bad_humour AS BOOLEAN
bad_humour = FALSE

bad_humour_radius AS BYTE
bad_humour_radius = 255

bad_humour_final AS BYTE
bad_humour_final = 17

REMSTART =========================================

         VARIOUS ARRAYS

         Arrays are created here
         Loaded in PlayerInitialisation subroutine

REMEND `==========================================

DIM colour(5) as DWORD
DIM colour_trail (5) as DWORD
DIM colourname(5) as STRING
DIM location(3) as BOOLEAN


REMSTART =========================================

         CREATE THE PLAYER CLASS

         X Y co-ordinates
         and keep the start locations for replays
         colour
         colour trail
         (on hard mode trails are very slightly different,
         so player will crash into them)
         direction
         and keep the starting direction for replays
         key-press help text
         left/right keyscan codes
         player alive true/false


         The players array is created after
         "number of players" has been chosen

REMEND `==========================================

TYPE PlayerClass
   X AS WORD
   Y AS WORD
   X_start AS WORD
   Y_start AS WORD
   colour AS DWORD
   colour_trail AS DWORD
   direction AS BYTE
   direction_start AS BYTE
   helpstring AS STRING
   namestring AS STRING
   left AS BYTE
   right AS BYTE
   alive AS BOOLEAN
ENDTYPE



REMSTART =========================================

         GAME LOOP

REMEND `==========================================

` Store screen black value
CLS
SYNC
back_black = point(xhalf,yhalf)

DO

   ` If this is a new game then get Difficulty and Number of Players
   IF (new_game = TRUE)

      `Reset number of players
      number_of_players = 0

      ` Set difficulty, screen size, frame rates
      ` And get numbe of players
      GOSUB MenuScreen

      ` Create player class
      DIM players(number_of_players) AS PlayerClass

      ` Initalise players (colour, starting location, etc.)
      GOSUB PlayerInitialisation

      ` Set Frames Per Second
      SYNC RATE sync_rate

   ENDIF


   ` prepare players
   GOSUB ReadyPlayers

   ` timers
   counter = TIMER() + key_delay
   IF (border_mode = 2) THEN border_counter = TIMER() + RND(1000)


   REMSTART =========================================

            MAIN ACTION LOOP

   REMEND `==========================================

   REPEAT

      GOSUB PlayerInput
      GOSUB MovePlayers
      GOSUB TestEnd

      WAIT game_delay

   UNTIL (survivors < 2)

LOOP



REMSTART =========================================

         SUBROUTINES

REMEND `==========================================


REMSTART =========================================

         INTIALISATION SUBROUTINES

REMEND `==========================================


REMSTART =========================================

         MEDIA LOAD
         BASIC SCREEN EFFECTS AND VARIABLES

REMEND `==========================================

load_media:
   LOAD IMAGE "TronMan.png",1
   HIDE MOUSE
   xmax = SCREEN WIDTH ()
   ymax = SCREEN HEIGHT ()
   xhalf = xmax / 2
   yhalf = ymax / 2
RETURN


REMSTART =========================================

      INITIAL MENU SCREEN
      DIFFICULTIES, NUMBER OF PLAYERS, DELAYS

REMEND `==========================================

MenuScreen:

   counter=TIMER()+3000

   ` Set so the humour graphics look good over text
   SET TEXT TRANSPARENT

   REPEAT

      GOSUB MenuScreenPrint

      IF (TIMER() > counter) THEN GOSUB tronmans_advice

      ` Write a FRAME
      SYNC
      WAIT 55

      pressed$ = INKEY$()

      GOSUB MenuScreenKeys

   UNTIL number_of_players <> 0

   ` Set so victory splashes can be seen over trails
   SET TEXT OPAQUE

RETURN


REMSTART =========================================

         PRINT THE MENU SCREEN

REMEND `==========================================

MenuScreenPrint:

      CLS

      ` Show THE TRON DUDE on the screen
      PASTE IMAGE 1,xhalf-175,0

      ` Game Name and version
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      SET TEXT TO BOLD
      CENTER TEXT xhalf*0.4,ymax*0.1,"TRON"
      TEXT (xmax - 40),ymax-20,vers$

      ` Request number of riders (when sets this starts the game)

      SET TEXT TO NORMAL
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.2,"PRESS NUMBER OF RIDERS"
      CENTER TEXT xhalf*0.4,ymax*0.2+15,"(2-4) TO BEGIN GAME"

      ` Difficulty
      IF ( difficulty = 0 ) THEN difficulty_text$ = "EASY"
      IF ( difficulty = 1 ) THEN difficulty_text$ = "HARD"

      SET TEXT TO BOLD
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.3,"DIFFICULTY (E/H)"
      SET TEXT TO NORMAL
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.3+15,difficulty_text$


      IF ( border_mode = 0 ) THEN border_text$ = "NO BORDER"
      IF ( border_mode = 1 ) THEN border_text$ = "ARENA"
      IF ( border_mode = 2 ) THEN border_text$ = "RANDOM"
      IF ( border_mode = 3 ) THEN border_text$ = "CHAMPION"

      SET TEXT TO BOLD
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.4,"BORDER MODE (B)"
      SET TEXT TO NORMAL
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.4+15,border_text$

      ` Appalling humour, circle the poor lunatic's nuts
      IF (bad_humour = TRUE)
         INK RGB(RND(100)+150,RND(100)+150,RND(100)+150),0
         CIRCLE xhalf+1,347,bad_humour_radius
         IF (bad_humour_radius >  bad_humour_final)
            bad_humour_radius = bad_humour_radius - 4
         ENDIF
      ENDIF

      ` And let him say something
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      TEXT xhalf+70,380, tron_man$

   ` Screen size
      SET TEXT TO BOLD
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf+xhalf*0.37,yhalf*0.25,"S"
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf+xhalf*0.37,yhalf*0.3, "M"
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf+xhalf*0.37,yhalf*0.35,"L"

      SET TEXT TO NORMAL
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      CENTER TEXT xhalf+xhalf*0.7,yhalf*0.25,"SMALL SCREEN (FASTEST)"
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      CENTER TEXT xhalf+xhalf*0.7,yhalf*0.3, "MEDIUM SCREEN (FASTER)"
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      CENTER TEXT xhalf+xhalf*0.7,yhalf*0.35,"LARGE SCREEN (FAST)"

      ` Two mechanisms to delay the game (WAIT delay, Frames Per Second)
      ` And the keyscan delay
      SET TEXT TO BOLD
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.5,"- and +"
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.6,"[ and ]"
      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.7,"< and >"

      SET TEXT TO NORMAL
      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      IF (game_delay = -1)
         CENTER TEXT xhalf*0.4,ymax*0.5+15,("DELAY: *TURBO*")
      ELSE
         CENTER TEXT xhalf*0.4,ymax*0.5+15,("GAME DELAY: " + STR$(game_delay) )
      ENDIF

      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      IF (sync_rate)
         CENTER TEXT xhalf*0.4,ymax*0.6+15,("FPS: " + STR$(sync_rate) )
      ELSE
         CENTER TEXT xhalf*0.4,ymax*0.6+15,("FPS: *MAXIMUM*")
      ENDIF

      INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
      CENTER TEXT xhalf*0.4,ymax*0.7+15,("KEY DELAY: " + STR$(key_delay) )

      INK RGB(RND(150)+100,RND(150)+100,RND(150)+100),0
      SET TEXT TO BOLD
      CENTER TEXT xhalf*0.4,ymax*0.85,"X to MAXIMISE"


RETURN

REMSTART =========================================

         ACTION MENU SCREEN KEYPRESSES

REMEND `==========================================

MenuScreenKeys:

   ` Screen sizes
   IF UPPER$(pressed$) = "S" THEN GOSUB small_window
   IF UPPER$(pressed$) = "M" THEN GOSUB medium_window
   IF UPPER$(pressed$) = "L" THEN GOSUB large_window


   ` Difficulty
   IF UPPER$(pressed$) = "E" THEN difficulty = 0
   IF UPPER$(pressed$) = "H" THEN difficulty = 1

   ` Border Mode
   IF UPPER$(pressed$) = "B" THEN border_mode = border_mode + 1
   IF (border_mode = 4) THEN border_mode = 0

   ` Game delay, key delay, frames per second (sync)
   IF (UPPER$(pressed$) = "X")
      game_delay = -1
      sync_rate = 0
      key_delay = 100
   ENDIF

   IF ((pressed$ = "2") OR (pressed$ = "3") OR (pressed$ = "4"))
      number_of_players = VAL(pressed$)
   ENDIF

   ` Delay
   IF ( ((pressed$ = "-") OR (pressed$ = "_")) AND (game_delay > -1) ) THEN game_delay = game_delay - 1
   IF ( (pressed$ = "=") OR (pressed$ = "+") ) THEN game_delay = game_delay + 1

   ` SYNC
   IF ( (pressed$ = "[") AND (sync_rate > 0) ) THEN sync_rate = sync_rate - 1
   IF ( (pressed$ = "]") ) THEN sync_rate = sync_rate + 1

   ` KEY DELAY
   IF ( (pressed$ = "<") OR (pressed$ = ",") ) THEN key_delay = key_delay - 1
   IF ( (pressed$ = ">") OR (pressed$ = ".") ) THEN key_delay = key_delay + 1

RETURN


REMSTART =========================================

         SET THE VARIOUS SCREEN SIZES

REMEND `==========================================

small_window:
   SET DISPLAY MODE 640,480,16
   SET WINDOW POSITION 300,200
   GOSUB load_media
RETURN

medium_window:
   SET DISPLAY MODE 800,600,16
   SET WINDOW POSITION 200,100
   GOSUB load_media
RETURN

large_window:
   SET DISPLAY MODE 1024,768,16
   SET WINDOW POSITION 50,50
   GOSUB load_media
RETURN


REMSTART =========================================

         A BIT OF HUMOUR

REMEND `==========================================

tronmans_advice:

   counter=TIMER()+2500

   IF (RND(2))
      tron_man$ = ""
   ELSE
      SELECT RND(9)
         CASE 0 : tron_man$ = "  'THE KIDS LOVE MY COSTUME'   " : ENDCASE
         CASE 1 : tron_man$ = "        'MY NUTS ITCH'         " : ENDCASE
         CASE 2 : tron_man$ = "     'I LIKE BABYSITTING'      " : ENDCASE
         CASE 3 : tron_man$ = "'I'M A MACHINE : A SEX MACHINE'" : ENDCASE
         CASE 4 : tron_man$ = "  'MY MUMMY SAYS I'M SPECIAL'  " : ENDCASE
         CASE 5 : tron_man$ = "   'I CAN SMELL YOUR FEAR'     " : ENDCASE
         CASE 6 : tron_man$ = "   'WILL YOU BE MY FRIEND?'    " : ENDCASE
         CASE 7 : tron_man$ = "    'I'M ONLY 47 YEARS OLD'    " : ENDCASE
         CASE 8 : tron_man$ = "    'DOES MY BOTTOM SMELL?'    " : ENDCASE
         CASE 9 : tron_man$ = "      'I CAN'T WEE WEE'        " : ENDCASE
      ENDSELECT
   ENDIF

   IF ( (RND(3)=0) AND (bad_humour = FALSE) )
      bad_humour = TRUE
      bad_humour_radius = 255
   ENDIF

RETURN

REMSTART =========================================

         PLAYER INITIALISATION

            player colour
            starting location
            direction
            left/right keyscans
            help strings

            note we set the player().alive
            in the "readyplayers" subroutine
            to permit the same player playing
            multiple times (replay), replays
            do not enter this subroutine.

REMEND `==========================================

PlayerInitialisation:

` PLAYER COLOUR

   colour(0)= RGB(255,0,0)
   colour(1)= RGB(0,255,0)
   colour(2)= RGB(0,0,255)
   colour(3)= RGB(255,255,0)
   colour(4)= RGB(255,0,255)
   colour(5)= RGB(0,255,255)

   colour_trail(0)= RGB(254,0,0)
   colour_trail(1)= RGB(0,254,0)
   colour_trail(2)= RGB(0,0,254)
   colour_trail(3)= RGB(254,254,0)
   colour_trail(4)= RGB(254,0,254)
   colour_trail(5)= RGB(0,254,254)

   colourname(0) = "RED DEVIL"
   colourname(1) = "MEAN GREEN"
   colourname(2) = "RAVEY NAVY"
   colourname(3) = "YELLOW PERIL"
   colourname(4) = "VIOLENT VIOLET"
   colourname(5) = "CRAZY CYAN"

   FOR i = 1 to number_of_players

      ` This REPEAT looks difficult but it's not
      ` A random pick is made from 0 to 5 which relates to above colours
      ` And it is then set to black indicating it has been picked
      `
      ` But if the player has a black colour, keep doing the repeat loop
      ` because it has picked a colour already taken

      REPEAT
         pick = RND(5)
         players(i).colour = colour(pick)
         players(i).colour_trail = colour_trail(pick)
         players(i).namestring = colourname(pick)
         colour(pick) = back_black
      UNTIL (players(i).colour <> back_black)
   NEXT i

   ` Set player black colour, sometimes it's picked during hard
   players(0).colour = back_black

` PLAYER STARTING LOCATION

   ` loc 0 = TL
   ` loc 1 = TR
   ` loc 2 = BL
   ` loc 3 = BR

   ` Setting the four possible locations to TRUE
   ` it means it is still available for selection

   location(0) = TRUE
   location(1) = TRUE
   location(2) = TRUE
   location(3) = TRUE

   FOR i = 1 to number_of_players

      ` Keep picking from the locations until
      ` one that's still available (TRUE) is found
      REPEAT
         pick = RND(3)
      UNTIL location(pick)=TRUE

      ` Now we have picked a location, we set the availablity of it to FALSE
      ` to prevent the next player starting there
      location(pick) = FALSE

      ` Start in the TOP LEFT
      IF (pick = 0)
         players(i).x = xhalf - (xhalf/2)
         players(i).y = yhalf - (yhalf/2)
         players(i).direction = 2
      ENDIF

      ` Start in the TOP RIGHT
      IF (pick=1)
         players(i).x = xhalf + (xhalf/2)
         players(i).y = yhalf - (yhalf/2)
         players(i).direction = 3
      ENDIF

      ` Start in the BOTTOM LEFT
      IF (pick=2)
         players(i).x = xhalf - (xhalf/2)
         players(i).y = yhalf + (yhalf/2)
         players(i).direction = 1
      ENDIF

      ` Start in the BOTTOM RIGHT
      IF (pick=3)
         players(i).x = xhalf + (xhalf/2)
         players(i).y = yhalf + (yhalf/2)
         players(i).direction = 4
      ENDIF

      players(i).x_start = players(i).x
      players(i).y_start = players(i).y
      players(i).direction_start = players(i).direction

   NEXT i

   ` Set the players LEFT/RIGHT keys.
   ` Note they are not ASCII or UNICODE but DARKBASIC's version (bah)
   ` Also set the "help string" telling the player which keys they are to use

   FOR i = 1 to number_of_players

      IF (i = 1)
         players(i).helpstring = "Z and X"
         players(i).left = 44
         players(i).right = 45
      ENDIF

      IF (i = 2)
         players(i).helpstring = "LEFT and RIGHT arrows"
         players(i).left = 203
         players(i).right = 205
      ENDIF

      IF (i = 3)
         players(i).helpstring = "keypad 7 and 8"
         players(i).left = 75
         players(i).right = 77
      ENDIF

      IF (i = 4)
         players(i).helpstring = ", and ."
         players(i).left = 51
         players(i).right = 52
      ENDIF

   NEXT i

   ` Set the border colour to black
   border_colour = back_black

RETURN


REMSTART =========================================

         PRE-GAME SCREEN, TELL PLAYERS THEIR KEYS

REMEND `==========================================

ReadyPlayers:

   CLS

   ` If border mode is on (above 0) then draw borders
   IF (border_mode)
      ` If the mode is 1 (arena) set the ink to white
      ` If the mode is 2 (random) select one at random
      ` If the mode is 3 then it will be set in-game to the champion!
      ` The first game on 3 it will be black
      IF (border_mode = 1) THEN border_colour = RGB(255,255,255)
      IF (border_mode = 2) THEN border_colour = players(RND(number_of_players)).colour
      GOSUB draw_border

   ENDIF

   ` Set surviving number of players to the number of players in the game
   survivors = number_of_players

   FOR i = 1 TO number_of_players
      INK players(i).colour,0
      CENTER TEXT players(i).x,players(i).y-20,players(i).namestring + " GET READY!"
      CENTER TEXT players(i).x,players(i).y,players(i).helpstring

      ` Set the player to live
      players(i).alive = TRUE
   NEXT i

   INK RGB(255,255,255),0
   CENTER TEXT xhalf,yhalf,"SPACEBAR WHEN READY, RIDERS!"

   ` Write a FRAME
   SYNC

   REPEAT UNTIL SPACEKEY() : CLS


   ` Redraw the border after the CLS
   IF (border_mode) THEN GOSUB draw_border


RETURN


REMSTART =========================================

         MAIN GAME SUBROUTINES

REMEND `==========================================


REMSTART =========================================

         GET KEYSCANS, CHANGE PLAYER DIRECTION

REMEND `==========================================

PlayerInput:

   IF (TIMER() > counter)

      FOR i = 1 to number_of_players

         IF KEYSTATE(players(i).left) then players(i).direction = players(i).direction - 1
         IF KEYSTATE(players(i).right) then players(i).direction = players(i).direction + 1

         IF players(i).direction > 4 then players(i).direction = 1
         IF players(i).direction < 1 then players(i).direction = 4

      NEXT i

      counter = TIMER() + key_delay

   ENDIF

   KEYSTATE(44)=0 : KEYSTATE(45)=0
   KEYSTATE(203)=0 : KEYSTATE(205)=0
   KEYSTATE(51)=0 : KEYSTATE(52)=0
   KEYSTATE(75)=0 : KEYSTATE(77)=0

RETURN


REMSTART =========================================

         MOVE PLAYERS
         TEST COLLISION (KILL PLAYER IF REQUIRED)

REMEND `==========================================

MovePlayers:

   ` If border mode 2 (random) then sometimes redraw the border randomly, including black
   IF (border_mode = 2)
      IF ( TIMER() > border_counter )
         border_colour = players(RND(number_of_players)).colour
         GOSUB draw_border
         border_counter = TIMER() + RND(2000)
      ENDIF
   ENDIF

   FOR i = 1 to number_of_players

      ` Don't both moving or checking dead players
      IF (players(i).alive = TRUE)


         IF (difficulty = 0)
            ` On EASY difficulty put the player's colour as a trial - won't die
            DOT players(i).x,players(i).y,players(i).colour
         ELSE
            ` On HARD difficulty put player's variant colour as a trial - will die
            DOT players(i).x,players(i).y,players(i).colour_trail
         ENDIF

         SELECT players(i).direction
            CASE 1 : players(i).y = players(i).y - 1 : ENDCASE
            CASE 2 : players(i).x = players(i).x + 1 : ENDCASE
            CASE 3 : players(i).y = players(i).y + 1 : ENDCASE
            CASE 4 : players(i).x = players(i).x - 1 : ENDCASE
         ENDSELECT

         IF (players(i).x = 0) then players(i).x = xmax
         IF (players(i).y = 0) then players(i).y = ymax
         IF (players(i).x > xmax) then players(i).x = 0
         IF (players(i).y > ymax) then players(i).y = 0

         ` Assume we have not hit anything
         collision = FALSE

         ` Get a colour, if the colour is not black then we have hit something
         ` So set collision to true
         hit_spot = POINT(players(i).x,players(i).y)


         ` If player hits nonblack he has collided
         ` Test against back_black AND zero (standard blacK)
         ` as some monitors have both
         IF ((hit_spot <> back_black) AND (hit_spot <> 0)) THEN collision = TRUE

         ` If player has hit own colour, then has not collided
         IF (hit_spot =  players(i).colour)
            collision = FALSE
         ENDIF

         IF (collision = TRUE)
            ` If the player is dead, set an explosion circle
            ` Set their alive status to false
            ` And decrement the number of surviving players
            INK players(i).colour,0
            CIRCLE players(i).x,players(i).y,0.5
            CIRCLE players(i).x,players(i).y,1
            CIRCLE players(i).x,players(i).y,1.5
            CIRCLE players(i).x,players(i).y,2
            players(i).alive = FALSE
            survivors = survivors - 1
         ENDIF

      ` Player Alive TEST condition
      ENDIF

   NEXT i

   ` Write a FRAME
   SYNC

RETURN


REMSTART =========================================

         CHECK FOR WIN CONDITIONS

REMEND `==========================================

TestEnd:

   IF (survivors = 1)
      FOR i = 1 to number_of_players
         IF (players(i).alive = TRUE)
            ` Set the border colour to the player
            border_colour = players(i).colour
            INK players(i).colour,0
            CENTER TEXT xhalf,ymax*0.1,players(i).namestring + " WINS!!"
            REPEAT
               INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
               CENTER TEXT xhalf,ymax*0.2,"PRESS F1 TO RESTART"
               INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
               CENTER TEXT xhalf,ymax*0.2+15,"PRESS F5 TO REPLAY"

               ` Write a FRAME
               SYNC
               WAIT 90
            UNTIL (KEYSTATE(59) OR KEYSTATE(63))

            IF KEYSTATE(59)
               ` F1 has been pressed - NEW GAME (restart) is TRUE
               new_game=TRUE
            ELSE
               ` F5 has been pressed - not a new game but a replay
               new_game=FALSE
            ENDIF

         ENDIF
      NEXT i
   ENDIF

   ` This only happens if the last 2 (or more) players hit at exactly the same time
   ` This is unlikely unless no key is pressed at the start and the bikers collide
   IF (survivors = 0)
      INK RGB(255,255,255),0
      CENTER TEXT xhalf,ymax*0.1,"IT'S A DRAW!"
      REPEAT
         INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
         CENTER TEXT xhalf,ymax*0.2,"PRESS F1 TO RESTART"
         INK RGB(RND(100)+100,RND(100)+100,RND(100)+100),0
         CENTER TEXT xhalf,ymax*0.2+15,"PRESS F5 TO REPLAY"

         ` Write a FRAME
         SYNC
         WAIT 90
      UNTIL (KEYSTATE(59) OR KEYSTATE(63))

      IF KEYSTATE(59)
            ` F1 has been pressed - NEW GAME (restart) is TRUE
            new_game=TRUE
      ELSE
         ` F5 has been pressed - not a new game but a replay
         new_game=FALSE
      ENDIF

   ENDIF

   ` Delete the player class when the game is over, it'll be re-created, possibly
   ` as a different size
   IF (survivors < 2)
      IF (new_game = TRUE)
         ` Brand new game, so erase player array, it will be re-created
         ` Possibly as a different size (if a different number of players are chosen)
         UNDIM players()
      ELSE
         ` A restart was requested, that means simply resetting the existing players
         ` To their original locations
         FOR i = 1 TO number_of_players
            players(i).x = players(i).x_start
            players(i).y = players(i).y_start
            players(i).direction = players(i).direction_start
         NEXT i
      ENDIF
   ENDIF

RETURN


REMSTART =========================================

         DRAW THE BORDER
         MUST BE DOT, LINE COMMAND DOESN'T WORK

REMEND `==========================================

draw_border:

   FOR i = 5 TO xmax-5
      DOT i,5,border_colour
      DOT i,ymax-5,border_colour
   NEXT i

   FOR i = 5 TO ymax-5
      DOT 5,i,border_colour
      DOT xmax-5,i,border_colour
   NEXT i

RETURN