Adventures

Platform game: Adventures of a Donkey

Introduction

Peter wrote this effective platform game in about one week without the use of specialist game development software. We enjoy the donkey's adventures and trust that you will too. The following screen shot shows the game in action.

Platform game in action

Platform game in action

Click the left or right mouse button to make the donkey jump. If it lands on a spring it will jump higher. See how many carrots your donkey can catch. The velocity of the donkey in the x-direction depends on the x-coordinate of the cursor:

tileXIncTemp := (getMouseX-250)/30;

The width of the window is 500, so you should deduce how to control the donkey. If the donkey falls without a platform to land on, the game ends. You might expect standard image files such as .bmp files to be used for the donkey, carrots, background mountains and the terrain for the donkey to negotiate. However, Peter stores some of the image data in text files and uses the PutPixel, Bar and FillPoly procedures to render the graphics.

The text files spring.txt, carrot.txt, donkey_left.txt, donkey_right.txt are included with the source file adventures.txt in a compressed file, adventures.zip. Download adventures.zip. In order to run program Adventures, you will need to have downloaded also Stefan Berinde`s wingraph.zip file as described in our Graphics tutorial. You should copy the unzipped wincrt.pas, wingraph.pas and winmouse.pas (from the src folder) into your program folder. (The compiled units are included in the zip file but you might as well have the source code available for reference). You should find these three files useful for your own motion graphics programs.

The Program

program Adventures;
  {$APPTYPE GUI}

{
    Copyright (c) 2011 Peter Hearnshaw

    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/
}

uses
  SysUtils, wingraph, wincrt, winmouse;
var                                              //0 is empty   1 is soil  2 is top platform
  Gd, Gm : smallint;                             //3 is downleft  4 is downright  5 is leftBarrier
                                                 //6 is rightBarrier

                                                 //11 is soil  12 is top platform
                                                 //13 is downleft  14 is downright  15 is leftBarrier
                                                 //16 is rightBarrier
  allTiles : array [1..10, 1..171] of integer = (
  (0, 0,40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,40, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0),
  (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,40,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0),
  (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0, 0, 0, 0,40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,40,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13,12,14,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0),
  (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,0 ,0 ,0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,40, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,0 ,0 ,0 ,0 ,0 ,0 ,0 , 0, 0,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,40,0 ,0 ,0 ,0 ,0 ,0 ,13,12,14,0 ,0 ,0 ,0 ,0 ,0 ,40,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,15,11,16,0 ,0 ,0 ,0 ,0 ,0 ,40,40,0 ,0 ,0 ,0 ,0 ,0),
  (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,12,12,14,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , 0, 0,30,0 ,0 ,0 ,0, 0 ,0 ,0 ,40,13,12,12,14,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,15,11,16,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13,12,12,12,12,12,14,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,30,15,11,16,0 ,0 ,0 ,0 ,0 ,13,12,12,14,0 ,0 ,0 ,0 ,0),
  (0, 0, 0, 0, 0, 3, 2, 4, 0, 0, 0, 0, 13,14,0 ,0, 0, 0, 0, 0, 0, 15,11,11,16,0, 0, 0, 0, 0, 0,13,12,14, 0, 0, 0, 5, 6, 0, 0, 3, 2, 4, 0,30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 ,2 ,2 ,2 ,2 ,4 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13,12,12,12,12,14,0 ,0 ,0, 0 ,0 ,13,12,12,14,11,11,12,14,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13,12,12,12,12,14,0 ,0 ,0 ,15,11,16,0 ,0 ,0 ,0 ,0 ,0 ,30,0 ,0 ,0 ,0 ,13,12,12,14,0 ,0 ,15,11,11,11,11,11,16,0 ,0 ,0 ,13,12,12,12,12,12,12,14,0 ,0 ,3 ,2 ,2 ,4 ,16,0 ,0 ,0 ,0 ,0 ,15,11,11,16,0 ,0 ,0 ,0 ,0),
  (3, 4,30, 0, 3, 1, 1, 6, 0, 0, 0, 0, 15,16,0 ,3, 4, 0, 0, 13,12,12,12,14,16,0, 0, 0, 0, 0, 0,15,11,16, 0, 0,30, 5, 6, 0, 0, 5, 1, 1, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1 ,1 ,1 ,1 ,1 ,6 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,15,11,11,11,11,16,0 ,0 ,30,0 ,0 ,15,11,11,16,11,11,11,16,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13,12,12,12,12,14,11,11,11,16,0 ,0 ,0 ,15,11,16,0 ,0 ,0 ,0 ,0 ,3 ,2 ,4 ,0 ,0 ,13,11,11,11,16,0 ,0 ,15,11,11,11,11,11,16,0 ,13,12,12,14,11,11,11,11,11,16,0 ,0 ,5 ,1 ,1 ,6 ,16,0 ,0 ,3 ,4 ,0 ,15,11,11,16,0 ,0 ,0 ,0 ,0),
  (5, 1, 2, 2, 1, 1, 1, 1, 4, 0, 0, 0, 15,16,0 ,5, 1, 2, 2, 2, 2, 4, 11,16,16,0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 6, 0, 0, 5, 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0,30, 0, 0, 0, 3, 1, 1 ,1 ,1 ,1 ,1 ,6 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,15,11,11,3 ,2 ,2 ,2 ,2 ,4, 0 ,0 ,15,11,11,16,11,11,11,16,0 ,0 ,0 ,40,0 ,40,0 ,0 ,15,11,11,11,11,16,11,11,11,16,30,0 ,0 ,15,11,16,0 ,0 ,3 ,2 ,2 ,1 ,1 ,6 ,0 ,0 ,15,11,11,11,16,0 ,0 ,15,11,11,11,11,11,3 ,2 ,2 ,2 ,2 ,2 ,2 ,4 ,11,11,11,16,0 ,0 ,5 ,1 ,1 ,6 ,16,0 ,0 ,5 ,6 ,0 ,15,11,11,16,0 ,0 ,0 ,0 ,0),
  (5, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 6, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 0, 0, 5, 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 1, 1, 1 ,1 ,1 ,1 ,1 ,6 ,0 ,0 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,6, 0 ,3 ,2 ,2 ,2 ,2 ,4 ,11,11,16,0 ,0 ,0 ,3 ,2 ,2 ,2 ,2 ,2 ,4 ,11,11,3 ,2 ,2 ,4 ,11,3 ,4 ,0 ,0 ,15,11,16,0 ,3 ,1 ,1 ,1 ,1 ,1 ,6 ,0 ,0 ,15,3 ,2 ,2 ,2 ,2 ,2 ,2 ,4 ,11,11,11,3 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,6 ,11,11,11,16,0 ,0 ,5 ,1 ,1 ,6 ,16,0 ,0 ,5 ,6 ,0 ,15,11,11,16,0 ,3 ,2 ,2 ,4),
  (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0));
  x1, y1, shiftU, shiftR :integer;
  PosValue, PosValueLeft, PosValueRight : integer;
  charY, tileX : double;
  charYSpeed : double;
  goingLeft : boolean = true;
  rightMovementDisabled, leftMovementDisabled : boolean;
  exitNow : boolean = false;

procedure LoadDonkey;
var
  f:text;
  e, longColour : longint;
  strColour : string;
begin
  if(goingLeft=true)then
    begin
      assignFile(f, 'donkey_left.txt');
    end
  else
    begin
      assignFile(f, 'donkey_right.txt');
    end;
  reset(f);
  e := 0;
  repeat
    readln(f, strColour);
    longColour := strtoint(strColour);
    if not(longColour = 16777215)then
      putPixel(250-18+(e div 32), round(chary) - 32 + (e mod 32), longColour);
    inc(e);
  until Eof(f);
  closeFile(f);
end;

procedure LoadSpring (x3 : integer; y3 : integer);
var
  f:text;
  e, longColour : longint;
  strColour : string;
begin
  assignFile(f, 'spring.txt');
  reset(f);
  e := 0;
  repeat
    readln(f, strColour);
    longColour := strtoint(strColour);
    if not(longColour= 16777215)then
      putPixel(x3+(e div 39), y3+(e mod 39), longColour);
    inc(e);
  until Eof(f);
  closeFile(f);
end;

procedure LoadCarrot (x3 : integer; y3 : integer);
var
  f:text;
  e, longColour : longint;
  strColour : string;
begin
  assignFile(f, 'carrot.txt');
  reset(f);
  e := 0;
  repeat
    readln(f, strColour);
    longColour := strtoint(strColour);
    if not(longColour = 16777215)then
      putPixel(x3+(e div 28), y3+(e mod 28), longColour);
    inc(e);
  until Eof(f);
  closeFile(f);
end;

procedure loadTile (x2 : integer; y2 : integer; tileNum : integer);
var
  pattern: FillPatternType;
  fillShape:Array[1..8] Of PointType;
begin
  if(tileNum = 30)then
      loadSpring(x2, y2);
  if(tileNum = 40)then
      loadCarrot(x2, y2);
  if(tileNum=1)or(tileNum=11)then
    begin    //gound tile
      GetFillPattern(pattern);
      SetFillPattern(pattern, green);
      bar(1+x2,1+y2,40+x2,40+y2);
      setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon
      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 11+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 2+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 10+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 19+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 10+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 2+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 22+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 31+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 22+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 30+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 39+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 30+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 22+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);
    end;
  if(tileNum=2)or(tileNum=12)then
    begin    //platform/ground tile
      GetFillPattern(pattern);
      SetFillPattern(pattern, green);
      setLineStyle(NullLn, UserBitLn,NormWidth);
      bar(1+x2,1+y2,40+x2,40+y2);
      setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[2].Y := 2+y2;
      fillShape[3].X := 20+x2;
      fillShape[3].Y := 11+y2;
      fillShape[4].X := 1+x2;
      fillShape[4].Y := 2+y2;
      SetFillPattern(pattern, yellowgreen);
      FillPoly(4, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 11+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 2+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 10+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 19+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 10+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 2+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 22+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 31+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 22+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 30+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 39+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 30+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 22+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      setLineStyle(solidLn, UserBitLn, NormWidth);
      setcolor(sepia);
      line(1+x2, 1+y2, 40+x2, 1+y2);
      setcolor(ochre);
      line(1+x2, 2+y2, 40+x2, 2+y2);
      setcolor(saffron);
      line(1+x2, 3+y2, 40+x2, 3+y2);
    end;
  if(tileNum=3)or(tileNum=13)then
    begin    //down left
      GetFillPattern(pattern);
      SetFillPattern(pattern, green);
      setLineStyle(NullLn, UserBitLn,NormWidth);

      fillShape[1].X := 6+x2;
      fillShape[1].Y := 1+y2;
      fillShape[2].X := 41+x2;
      fillShape[2].Y := 1+y2;
      fillShape[3].X := 41+x2;
      fillShape[3].Y := 41+y2;
      fillShape[4].X := 1+x2;
      fillShape[4].Y := 41+y2;
      fillShape[5].X := 1+x2;
      fillShape[5].Y := 6+y2;
      fillShape[6].X := 6+x2;
      fillShape[6].Y := 1+y2;
      FillPoly(6, fillShape);

      setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[2].Y := 2+y2;
      fillShape[3].X := 20+x2;
      fillShape[3].Y := 11+y2;
      fillShape[4].X := 1+x2;
      fillShape[4].Y := 2+y2;
      SetFillPattern(pattern, yellowgreen);
      FillPoly(4, fillShape);

      fillShape[1].X := 4+x2;
      fillShape[1].Y := 3+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 11+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 2+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 10+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 19+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 10+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 6+y2;
      fillShape[8].X := 4+x2;
      fillShape[8].Y := 3+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(8, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 22+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 31+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 22+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 30+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 39+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 30+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 22+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      setLineStyle(solidLn, UserBitLn,NormWidth);
      setcolor(sepia);
      line(6+x2, 1+y2, 40+x2, 1+y2);
      setcolor(ochre);
      line(6+x2, 2+y2, 40+x2, 2+y2);
      setcolor(saffron);
      line(6+x2, 3+y2, 40+x2, 3+y2);

      setcolor(sepia);
      line(1+x2, 6+y2, 1+x2, 40+y2);
      setcolor(ochre);
      line(2+x2, 6+y2, 2+x2, 40+y2);
      setcolor(saffron);
      line(3+x2, 6+y2, 3+x2, 40+y2);

      setcolor(sepia);
      line(1+x2, 6+y2, 6+x2, 1+y2);
      setcolor(ochre);
      line(2+x2, 6+y2, 6+x2, 2+y2);
      setcolor(saffron);
      line(3+x2, 6+y2, 6+x2, 3+y2);
    end;
  if(tileNum=4)or(tileNum=14)then
    begin    //down right
      GetFillPattern(pattern);
      SetFillPattern(pattern, green);
      setLineStyle(NullLn, UserBitLn,NormWidth);

      fillShape[1].X := 34+x2;
      fillShape[1].Y := 1+y2;
      fillShape[2].X := 41+x2;
      fillShape[2].Y := 6+y2;
      fillShape[3].X := 41+x2;
      fillShape[3].Y := 41+y2;
      fillShape[4].X := 1+x2;
      fillShape[4].Y := 41+y2;
      fillShape[5].X := 1+x2;
      fillShape[5].Y := 1+y2;
      fillShape[6].X := 34+x2;
      fillShape[6].Y := 1+y2;
      FillPoly(6, fillShape);

      setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[2].Y := 2+y2;
      fillShape[3].X := 20+x2;
      fillShape[3].Y := 11+y2;
      fillShape[4].X := 1+x2;
      fillShape[4].Y := 2+y2;
      SetFillPattern(pattern, yellowgreen);
      FillPoly(4, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 11+y2;
      fillShape[3].X := 37+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 3+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 10+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 19+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 10+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 2+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 22+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 31+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 22+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 30+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 39+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 30+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 22+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      setLineStyle(solidLn, UserBitLn,NormWidth);
      setcolor(sepia);
      line(1+x2, 1+y2, 34+x2, 1+y2);
      setcolor(ochre);
      line(1+x2, 2+y2, 34+x2, 2+y2);
      setcolor(saffron);
      line(1+x2, 3+y2, 34+x2, 3+y2);

      setcolor(sepia);
      line(40+x2, 6+y2, 34+x2, 1+y2);
      setcolor(ochre);
      line(39+x2, 6+y2, 34+x2, 2+y2);
      setcolor(saffron);
      line(38+x2, 6+y2, 34+x2, 3+y2);

      setcolor(sepia);
      line(40+x2, 40+y2, 40+x2, 6+y2);
      setcolor(ochre);
      line(39+x2, 40+y2, 39+x2, 6+y2);
      setcolor(saffron);
      line(38+x2, 40+y2, 38+x2, 6+y2);
    end;
  if(tileNum=5)or(tileNum=15)then
    begin    //left
      GetFillPattern(pattern);
      SetFillPattern(pattern, green);
      bar(1+x2,1+y2,40+x2,40+y2);
      setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon
      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 11+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 2+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 10+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 19+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 10+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 2+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 22+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 31+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 22+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 30+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 39+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 30+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 22+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      setLineStyle(solidLn, UserBitLn,NormWidth);
      setcolor(sepia);
      line(1+x2, 1+y2, 1+x2, 40+y2);
      setcolor(ochre);
      line(2+x2, 1+y2, 2+x2, 40+y2);
      setcolor(saffron);
      line(3+x2, 1+y2, 3+x2, 40+y2);
    end;
  if(tileNum=6)or(tileNum=16)then
    begin    //right
      GetFillPattern(pattern);
      SetFillPattern(pattern, green);
      bar(1+x2,1+y2,40+x2,40+y2);
      setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon
      fillShape[1].X := 1+x2;
      fillShape[1].Y := 2+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 11+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 2+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 10+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 19+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 10+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 2+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      fillShape[1].X := 1+x2;
      fillShape[1].Y := 22+y2;
      fillShape[2].X := 20+x2;
      fillShape[2].Y := 31+y2;
      fillShape[3].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[3].Y := 22+y2;
      fillShape[4].X := 41+x2; //usually 40 but needs to link pattern tiles together
      fillShape[4].Y := 30+y2;
      fillShape[5].X := 20+x2;
      fillShape[5].Y := 39+y2;
      fillShape[6].X := 1+x2;
      fillShape[6].Y := 30+y2;
      fillShape[7].X := 1+x2;
      fillShape[7].Y := 22+y2;
      SetFillPattern(pattern, chartreuse);
      FillPoly(7, fillShape);

      setLineStyle(solidLn, UserBitLn,NormWidth);
      setcolor(sepia);
      line(40+x2, 1+y2, 40+x2, 40+y2);
      setcolor(ochre);
      line(39+x2, 1+y2, 39+x2, 40+y2);
      setcolor(saffron);
      line(38+x2, 1+y2, 38+x2, 40+y2);
    end;
end;

procedure DrawMountains;
var
  fillShape:Array[1..8] Of PointType;
  x4 : integer;
  pattern: FillPatternType;
begin
  x4 := round(tileX/10);
  //Mountain 1
  GetFillPattern(pattern);
  setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon
  fillShape[1].X := 100+x4;
  fillShape[1].Y := 360;
  fillShape[2].X := 180+x4;
  fillShape[2].Y := 150;
  fillShape[3].X := 220+x4; //usually 40 but needs to link pattern tiles together
  fillShape[3].Y := 150;
  fillShape[4].X := 300+x4;
  fillShape[4].Y := 360;
  fillShape[5].X := 100+x4;
  fillShape[5].Y := 360;
  SetFillPattern(pattern, lightgray);
  FillPoly(5, fillShape);

  fillShape[1].X := 180+x4;
  fillShape[1].Y := 150;
  fillShape[2].X := 200+x4;
  fillShape[2].Y := 100;
  fillShape[3].X := 220+x4; //usually 40 but needs to link pattern tiles together
  fillShape[3].Y := 150;
  fillShape[4].X := 180+x4;
  fillShape[4].Y := 150;
  SetFillPattern(pattern, white);
  FillPoly(4, fillShape);

  //Mountain2
  GetFillPattern(pattern);
  setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon
  fillShape[1].X := 300+x4;
  fillShape[1].Y := 360;
  fillShape[2].X := 380+x4;
  fillShape[2].Y := 150;
  fillShape[3].X := 420+x4; //usually 40 but needs to link pattern tiles together
  fillShape[3].Y := 150;
  fillShape[4].X := 500+x4;
  fillShape[4].Y := 360;
  fillShape[5].X := 300+x4;
  fillShape[5].Y := 360;
  SetFillPattern(pattern, lightgray);
  FillPoly(5, fillShape);

  fillShape[1].X := 380+x4;
  fillShape[1].Y := 150;
  fillShape[2].X := 400+x4;
  fillShape[2].Y := 100;
  fillShape[3].X := 420+x4; //usually 40 but needs to link pattern tiles together
  fillShape[3].Y := 150;
  fillShape[4].X := 380+x4;
  fillShape[4].Y := 150;
  SetFillPattern(pattern, white);
  FillPoly(4, fillShape);

  //Mountain 3
  GetFillPattern(pattern);
  setLineStyle(NullLn, UserBitLn,NormWidth);  //take away the border of the polygon
  fillShape[1].X := 700+x4;
  fillShape[1].Y := 360;
  fillShape[2].X := 780+x4;
  fillShape[2].Y := 150;
  fillShape[3].X := 820+x4; //usually 40 but needs to link pattern tiles together
  fillShape[3].Y := 150;
  fillShape[4].X := 900+x4;
  fillShape[4].Y := 360;
  fillShape[5].X := 700+x4;
  fillShape[5].Y := 360;
  SetFillPattern(pattern, lightgray);
  FillPoly(5, fillShape);

  fillShape[1].X := 780+x4;
  fillShape[1].Y := 150;
  fillShape[2].X := 800+x4;
  fillShape[2].Y := 100;
  fillShape[3].X := 820+x4; //usually 40 but needs to link pattern tiles together
  fillShape[3].Y := 150;
  fillShape[4].X := 780+x4;
  fillShape[4].Y := 150;
  SetFillPattern(pattern, white);
  FillPoly(4, fillShape);
end;

procedure CheckMouse;
var
  me:MouseEventType;
  tileXIncTemp : double;
begin
  if (PollMouseEvent(me)) then
    begin
      GetMouseEvent(me);
      with me do
        case action of
          MouseActionDown: begin //mouse button pressed
                             if(charYSpeed=0)then    //only jump if donkey is resting on a surface
                               charYSpeed := -10;
                           end;
        end;
    end;
  if(charYSpeed<-1)then  //if it is jumping then
    begin
      rightMovementDisabled := false;  //try hitting the wall again
      leftMovementDisabled := false;
    end;
  tileXIncTemp := (getMouseX-250)/30;
  if(tileXIncTemp<0)then
    begin
      goingLeft := true;
      if(leftMovementDisabled = true)then
        tileXIncTemp := 0;
      rightMovementDisabled := false; //going left so stop preventing moving right
  end;
  if(tileXIncTemp>0)then
    begin
      goingLeft := false;
      if(rightMovementDisabled = true)then
        tileXIncTemp := 0;
      leftMovementDisabled := false;    //going right so stop preventing moving left
  end;
  tileX := tileX - tileXIncTemp;
end;

begin
  SetWindowSize(500,360);
  gd:=9; gm:=13;
  InitGraph(gd,gm,'Adventures of a Donkey');
  updateGraph(updateOff);
  SetBkColor(skyblue);
  repeat
    chary := chary + charYSpeed;
    charYSpeed := charYSpeed + 0.5;
    DrawMountains;
    for y1 := 1 to 9 do
      begin
        for x1 := (round(-tileX+290+18) div 40)-7 to (round(-tileX+290+18) div 40)+7 do
          begin
            if(x1<172)then
              begin
                shiftR := (x1-1)*40 + round(tileX);
                shiftU := (y1-1)*40;
                if(allTiles[y1][x1] >0)then
                  loadTile(shiftR, shiftU, allTiles[y1][x1]);
              end;
          end;
      end;

    if(charY>520)then
      begin
        exitNow := true;
      end;

    if(charY>0)then   //above the top
      begin
        posValue := allTiles[round(charY+40) div 40][round(-tileX+290) div 40];
        posValueLeft := allTiles[round(charY+30) div 40][round(-tileX+250+20) div 40];   //+10

        if(allTiles[round(charY+20) div 40][round(-tileX+290) div 40]=40)then
          begin
            allTiles[round(charY+20) div 40][round(-tileX+290) div 40] := 0;
            posValue := 0;
          end;

        if(posValue >0)and(posValue <10)then
          begin
            charYSpeed := 0;
            charY := 40*(round(charY) div 40);
          end;
        while(posValueLeft >0)and(posValueLeft <10)do
          begin
            tileX := tileX - 3;
            posValueLeft := allTiles[round(charY+30) div 40][round(-tileX+250+20) div 40];  //+10
            leftMovementDisabled := true;
          end;
        if((posValue >11)and(posValue <15)and(charYSpeed>=0)and((round(charY+40) mod 40)<20))then
          begin
            charYSpeed := 0;
            charY := 40*(round(charY) div 40);
          end;
        if(posValue = 30)and(charYSpeed > 0)then
          charYSpeed := -20;
        posValueRight := allTiles[round(charY+30) div 40][round(-tileX+330-20) div 40];  //-20

        while(posValueRight >0)and(posValueRight <10)do
          begin
            tileX := tileX + 3;
            posValueRight := allTiles[round(charY+30) div 40][round(-tileX+330-20) div 40]; //20
            rightMovementDisabled := true;
          end;
      end;

    while(tilex>210)do
      begin
        tilex := 210;
      end;
    if(CloseGraphRequest)then
      exitNow := true;
    LoadDonkey;
    CheckMouse;
    updateGraph(updateNow);
    delay(3);
    clearDevice;
  until exitNow=true;
  CloseGraph;
end.

Remarks

Could you write a program using wincrt, wingraph and winmouse?

Programming - a skill for life!

Fourteen programs (with five web versions) including 3D-Driving, GASP and Knowledge by Peter Hearnshaw