Roller with Highest Score

by Neil: Y9 Age ~14

Introduction

This game is a new version of Roller with the highest score saved to a text file, highscores.txt. You can start with a text file containing a single previous best score such as 55. See the previous page for the original version and instructions for compilation. The code follows three screenshots of the program in action.


Game ready to start

Game ready to start


Game in progress

Game in progress


Final score

Final score

The Code

program roller;

{
    Copyright (c) 2013 Neil

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/ }

{$APPTYPE GUI}

uses
  WinCrt, WinGraph, Math, SysUtils;

const
  FrameDelay = 15;
  JumpHeight = 6;
  playerX = 100;
  barbXradius = 15;
  barbYradius = 24;

var
  gd, gm : smallint;
  playerY : integer;
  KeyboardInput, DeathScreenController : char;
  barbX, barbY : integer;
  BarbSpeed : integer;
  BarbController : integer;
  BallMovement : string;
  score : integer;
  DistanceSquared : integer;
  PlayedOnce : boolean;
  Highscores : TextFile;
  HighestScoreString : string;
  HighestScoreInt,code : integer;

  //Player Procedures:
  procedure DrawBondiBlueCircle;
  begin
    setcolor(Azure); //sets all colour to Azure, I do this because I can't find a way to specifically change the outline to Azure.
    SetFillStyle(SolidFill, BondiBlue); //sets the fill to be solid and white
    FillEllipse(playerX, playerY, 13, 13); //draws the circle
  end;

  procedure HideBondiBlueCircle;
  begin
    setcolor(Azure);
    SetFillStyle(SolidFill, Azure);
    FillEllipse(playerX, playerY, 13, 13); //covers up the circle
  end;

  procedure GoUp;
  begin
    HideBondiBlueCircle;
    playerY := playerY - JumpHeight; //makes the ball appear to go up
    DrawBondiBlueCircle;
  end;

  procedure GoDown;
  begin
    HideBondiBlueCircle;
    playerY := playerY + JumpHeight; //makes the ball appear to go down
    DrawBondiBlueCircle;
  end;

//game management procedures
procedure InitGame;
  begin
    SetFillStyle(SolidFill, azure);
    Bar(0, 0, GetMaxX, GetMaxY);
    SetFillStyle(SolidFill, PaleGreen);
    Bar(0, 226, GetMaxX, GetMaxY);
    setcolor(BondiBlue);
    SetFillStyle(SolidFill, BondiBlue);
    playerY := 212;
    FillEllipse(playerX, playerY, 13, 13);
    SetColor(scarlet);

    if PlayedOnce = false then
      begin
        SetTextStyle(MSSansSerifFont, HorizDir, 60);
        OutTextXY(250, 100, 'Roller');
        SetTextStyle(MSSansSerifFont, HorizDir, 35);
        OutTextXY(180, 163, 'Press space to play');
        HighestScoreInt := 1; //so that the "if score = highestscoreint" thing
                              //won't occur if the game hasn't been played
        if score > HighestScoreInt then
          begin
            rewrite(Highscores);
            writeln(Highscores, inttostr(score));
            close(Highscores);
            SetTextStyle(MSSansSerifFont, HorizDir, 40);
            OutTextXy(77, 270,'NEW HIGHSCORE');
            SetTextStyle(MSSansSerifFont, HorizDir, 30);
            OutTextXY(77, 305, 'Congratulations you beat the highscore of '+ HighestScoreString + ' by ' +
                      inttostr(score - HighestScoreInt) + ' points!');
          end;

       if (score < HighestScoreInt) and (score <> 0) then
         begin
           SetTextStyle(MSSansSerifFont, HorizDir, 30);
           OutTextXY(110, 240, 'The current highest score is: ' + HighestScoreString);
         end;

        if score = HighestScoreInt then
          begin
            SetTextStyle(MSSansSerifFont, HorizDir, 40);
            OutTextXY(110, 240, 'Your score was the same as the highscore!');
          end;
      end;

    if PlayedOnce = true then
      begin
        SetTextStyle(MSSansSerifFont, HorizDir, 45);
        OutTextXY(205, 117, 'Your score was: ' + inttostr(score));
        SetTextStyle(MSSansSerifFont, HorizDir, 35);
        OutTextXY(205, 163, 'Press space to play again');
      end;

    AssignFile(Highscores, 'highscores.txt');
    try
      Reset(Highscores);
      repeat
        Readln(Highscores, HighestScoreString); // Reads the whole line from the file
        val(HighestScoreString, HighestScoreInt, code);
        SetTextStyle(MSSansSerifFont, HorizDir, 35);
        if PlayedOnce = false then
          OutTextXY(110, 240, 'The current highest score is: '+ HighestScoreString);
      until(EOF(Highscores)); // EOF(End Of File) The program will keep reading new lines until there is none.
      CloseFile(Highscores);
    except
      on E : EInOutError do
      begin
        Writeln('File handling error occurred. Details: '+ E.ClassName + '/' + E.Message);
      end;
    end;

    if score > HighestScoreInt then
      begin
        rewrite(Highscores);
        writeln(Highscores, inttostr(score));
        close(Highscores);
        SetTextStyle(MSSansSerifFont, HorizDir, 40);
        OutTextXy(77, 250, 'NEW HIGHSCORE');
        SetTextStyle(MSSansSerifFont, HorizDir, 30);
        OutTextXY(77, 289, 'Congratulations you beat the highscore of '+ HighestScoreString + '.');
      end;

    if (score < HighestScoreInt) and (score <> 0) then
      begin
        SetTextStyle(MSSansSerifFont, HorizDir, 40);
        OutTextXY(110, 240, 'The current highest score is: '+ HighestScoreString + '.');
      end;

    if score = HighestScoreInt then
      begin
        SetTextStyle(MSSansSerifFont, HorizDir, 35);
        OutTextXY(110, 240, 'Your score was the same as the highscore!');
      end;


    DeathScreenController := #1;
    repeat
      if (keypressed = True) then
        DeathScreenController := readkey;  //screen stays until space, esc or the x button (on the window) are pressed
      if DeathScreenController = #27 then
        CloseGraph; //game closes when esc is pressed
    until (DeathScreenController = #32) or (CloseGraphRequest);

    SetFillStyle(SolidFill, azure);
    Bar(0, 0, GetMaxX, GetMaxY);         //drawing stuff...
    SetFillStyle(SolidFill, PaleGreen);
    Bar(0, 226, GetMaxX, GetMaxY);
    SetColor(InternationalKleinBlue);
    SetTextStyle(CourierNewFont, HorizDir, 27);
    OutTextXY(6, 4, 'Score:');

    BarbController := 1;
    BallMovement := 'stationary'; //ball starts out as still
    score := 0;
    BarbSpeed := 9;
    barbX := 615;
    barbY := RandomRange(150, 205); //sets barbY to a random integer between 150 and 205
  end;

begin
  gd := d8bit; //graphics driver settings
  gm := mCustom; //graphics mode. The window size is set to a custom size
  SetWindowSize(640, 360); //sets custom window size to 640 pixels wide and 360 high
  InitGraph(gd, gm, 'Roller'); //initiates a graphics window that uses gd and gm and has "Roller" as the title
  PlayedOnce := false; //becomes true after game is played once
  InitGame;

  repeat
    SetColor(InternationalKleinBlue);
    SetTextStyle(CourierNewFont, HorizDir, 27);  //writes out the score at 90, 4
    OutTextXY(90, 4, IntToStr(score)); //IntToStr converts the integer "score" into a string

    if score = 1 then
      OutTextXY(30, 270, 'Press the up arrow to jump');
    if score = 400 then
      begin
        SetFillStyle(SolidFill, PaleGreen);  //covers up the text
        Bar(0, 226, GetMaxX, GetMaxY);
      end;
    if score = 1000 then
      begin
        BarbSpeed := 12; //speed increasing code
        SetTextStyle(MSSansSerifFont, HorizDir, 45);
        SetColor(scarlet);
        OutTextXY(30, 270, 'Speed up!');
      end;
    if score = 1100 then
      begin
        SetFillStyle(SolidFill, PaleGreen); //covers up text
        Bar(0, 226, GetMaxX, GetMaxY);
      end;

    if (KeyPressed = true) then
      begin
        KeyboardInput := readkey;
        case KeyboardInput of
          #72 : if BallMovement = 'stationary' then
            BallMovement := 'up';  //up key to jump
          #27 : CloseGraph; //closes when esc is pressed
        end;
      end;

    if playerY = 122 then
      BallMovement := 'down'; //122 is above 212 rather than below because the Y axis is inverted.
                                                  //If it wasn't inverted I would use 302
    if BallMovement = 'up' then
      GoUp;
    if BallMovement = 'down' then
      GoDown;

    if playerY = 212 then
      BallMovement := 'stationary';

    if BarbController = 1 then
      begin
        barbX := 615;
        barbY := RandomRange(168, 205); //sets barbY to a random integer between 150 and 205
      end;

    DistanceSquared := (playerX - barbX) * (playerX - barbX) + (playerY - barbY) * (playerY - barbY); //Pythagoras collision detection stuff
    if 666 > DistanceSquared then //1300 was roughly the original number
      begin
        SetColor(DarkGray);
        SetTextStyle(ArialFont, HorizDir, 90);
        OutTextXY(barbX - barbXradius, barbY - barbYradius, '*'); //outputs '*' at barbX, barbY
        delay(2013);
        InitGame;
      end;

    if barbX > 0 then
      begin
        BarbController := 2;
        SetColor(DarkGray);
        SetTextStyle(ArialFont, HorizDir, 90);
        OutTextXY(barbX - barbXradius, barbY - barbYradius, '*'); //outputs '*' at barbX, barbY
        delay(FrameDelay); //this is an integral delay for when the game is being played
        SetFillStyle(SolidFill, azure);
        bar(barbX - 10, barbY - 37, barbX + 35, barbY + 20); //covers up the area that the barb is
        barbX := barbX - BarbSpeed; //barbX gets smaller
        SetColor(DarkGray);
        SetTextStyle(ArialFont, HorizDir, 90);
        OutTextXY(barbX - barbXradius, barbY - barbYradius, '*'); //outputs '*' at barbX, barbY
      end;

    SetColor(BondiBlue); //this is here so that parts of the ball don't seem to be cut off by the barb
    SetFillStyle(SolidFill, BondiBlue);
    FillEllipse(playerX, playerY, 13, 13);

    if barbX = 3 then     //I use 3 instead of 0 because the distance between 615 and 3 is 612, which has lots of factors that I can use for BarbSpeed
      begin
        SetColor(DarkGray);
        SetTextStyle(ArialFont, HorizDir, 90);
        OutTextXY(0, barbY - barbYradius, '*');
        delay(FrameDelay);
        barbX := 0;
        SetColor(Azure);
        SetFillStyle(SolidFill, Azure);
        Bar(0, 105, 45, 225); //puts a bar over the entire area that the barb could be
        OutTextXY(0, barbY - barbYradius, '*');
        BarbController := 1;
      end;

    SetColor(BondiBlue);//this is here so that parts of the ball don't seem to be cut off by the barb
    SetFillStyle(SolidFill, BondiBlue);
    FillEllipse(playerX, playerY, 13, 13);

    SetColor(Azure);
    SetFillStyle(SolidFill, Azure);//covers up the previously written score so that it can be written again
    bar(90, 4, 200, 60);

    Inc(score); //increments the score by one

    if PlayedOnce = false then
      PlayedOnce := true; //only happens once

  until (CloseGraphRequest); //waits until the user clicks the X on the window

  CloseGraph; //closes the graphics window

end.

Programming - a skill for life!

by Neil: Y9 Age ~14