| 1 | {
|
|---|
| 2 | Maze painter class of the Lazarus Mazes program
|
|---|
| 3 |
|
|---|
| 4 | Copyright (C) 2012 G.A. Nijland (eny @ lazarus forum http://www.lazarus.freepascal.org/)
|
|---|
| 5 |
|
|---|
| 6 | This source is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
|
|---|
| 7 | License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
|
|---|
| 8 | version.
|
|---|
| 9 |
|
|---|
| 10 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|---|
| 11 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|---|
| 12 | details.
|
|---|
| 13 |
|
|---|
| 14 | A copy of the GNU General Public License is available on the World Wide Web at
|
|---|
| 15 | <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing to the Free Software Foundation, Inc., 59
|
|---|
| 16 | Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|---|
| 17 | }
|
|---|
| 18 | unit MazePainter;
|
|---|
| 19 |
|
|---|
| 20 | {$mode objfpc}{$H+}
|
|---|
| 21 |
|
|---|
| 22 | interface
|
|---|
| 23 |
|
|---|
| 24 | uses
|
|---|
| 25 | Maze,
|
|---|
| 26 | Graphics, Classes, SysUtils;
|
|---|
| 27 |
|
|---|
| 28 | type
|
|---|
| 29 |
|
|---|
| 30 | { TMazePainter }
|
|---|
| 31 | TMazePainter = class
|
|---|
| 32 | private
|
|---|
| 33 | FCellDrawWidth: integer;
|
|---|
| 34 | FCellDrawHeight: integer;
|
|---|
| 35 | FisDirty: boolean;
|
|---|
| 36 | Maze: TMaze;
|
|---|
| 37 | FCanvas: TCanvas;
|
|---|
| 38 | bmp: TBitMap;
|
|---|
| 39 |
|
|---|
| 40 | FWallColor: TColor;
|
|---|
| 41 | FWallShadowColor: TColor;
|
|---|
| 42 | FCellColors: array[TCellState] of TColor;
|
|---|
| 43 |
|
|---|
| 44 | function GetCellColor(const pState: TCellState): TColor;
|
|---|
| 45 | procedure SetCellColor(const pState: TCellState; pColor: TColor);
|
|---|
| 46 | procedure Grow(var pRect: TRect; const pdx, pdy: integer);
|
|---|
| 47 |
|
|---|
| 48 | public
|
|---|
| 49 | constructor Create(const pMaze: TMaze; pCanvas: TCanvas);
|
|---|
| 50 | destructor Destroy; override;
|
|---|
| 51 |
|
|---|
| 52 | procedure Paint(const pOffsetX: integer = 0; const pOffsetY: integer = 0);
|
|---|
| 53 |
|
|---|
| 54 | function Width : integer;
|
|---|
| 55 | function Height: integer;
|
|---|
| 56 |
|
|---|
| 57 | property CellDrawWidth: integer read FCellDrawWidth write FCellDrawWidth;
|
|---|
| 58 | property CellDrawHeight: integer read FCellDrawHeight write FCellDrawHeight;
|
|---|
| 59 |
|
|---|
| 60 | property CellColor[const pState: TCellState]: TColor read GetCellColor write SetCellColor;
|
|---|
| 61 | property WallColor: TColor read FWallColor write FWallColor;
|
|---|
| 62 | property WallShadowColor: TColor read FWallShadowColor write FWallShadowColor;
|
|---|
| 63 | property IsDirty: boolean read FisDirty write FisDirty;
|
|---|
| 64 | end;
|
|---|
| 65 |
|
|---|
| 66 | implementation
|
|---|
| 67 |
|
|---|
| 68 | { TMazePainter }
|
|---|
| 69 |
|
|---|
| 70 | constructor TMazePainter.Create(const pMaze: TMaze; pCanvas: TCanvas);
|
|---|
| 71 | begin
|
|---|
| 72 | Bmp := TBitMap.Create;
|
|---|
| 73 |
|
|---|
| 74 | // Init the default drawing width and height
|
|---|
| 75 | FCellDrawWidth := 15;
|
|---|
| 76 | FCellDrawHeight := 15;
|
|---|
| 77 |
|
|---|
| 78 | // Set default colors
|
|---|
| 79 | WallColor := clBlue;
|
|---|
| 80 | CellColor[csEmpty] := clSkyBlue;
|
|---|
| 81 | CellColor[csStart] := clYellow;
|
|---|
| 82 | CellColor[csVisited] := clMaroon;
|
|---|
| 83 | CellColor[csExit] := clGreen;
|
|---|
| 84 |
|
|---|
| 85 | // Store maze and canvas for future reference
|
|---|
| 86 | Maze := pMaze;
|
|---|
| 87 | FCanvas := pCanvas;
|
|---|
| 88 |
|
|---|
| 89 | // Refresh on the next draw
|
|---|
| 90 | isDirty := true;
|
|---|
| 91 | end;
|
|---|
| 92 |
|
|---|
| 93 | destructor TMazePainter.Destroy;
|
|---|
| 94 | begin
|
|---|
| 95 | FreeAndNil(Bmp);
|
|---|
| 96 | inherited Destroy;
|
|---|
| 97 | end;
|
|---|
| 98 |
|
|---|
| 99 | function TMazePainter.GetCellColor(const pState: TCellState): TColor;
|
|---|
| 100 | begin
|
|---|
| 101 | result := FCellColors[pState];
|
|---|
| 102 | end;
|
|---|
| 103 |
|
|---|
| 104 | procedure TMazePainter.SetCellColor(const pState: TCellState; pColor: TColor);
|
|---|
| 105 | begin
|
|---|
| 106 | FCellColors[pState] := pColor
|
|---|
| 107 | end;
|
|---|
| 108 |
|
|---|
| 109 | procedure TMazePainter.Grow(var pRect: TRect; const pdx, pdy: integer);
|
|---|
| 110 | begin
|
|---|
| 111 | dec(pRect.Left, pdx);
|
|---|
| 112 | dec(pRect.Top, pdy);
|
|---|
| 113 | inc(pRect.Right, pdx);
|
|---|
| 114 | inc(pRect.Bottom, pdy);
|
|---|
| 115 | end;
|
|---|
| 116 |
|
|---|
| 117 | procedure TMazePainter.Paint(const pOffsetX: integer; const pOffsetY: integer);
|
|---|
| 118 | const C_LINE_THICK = 1;
|
|---|
| 119 | var row,col: integer;
|
|---|
| 120 | square : TRect;
|
|---|
| 121 | Canvas : TCanvas;
|
|---|
| 122 | dx,dy : integer;
|
|---|
| 123 | begin
|
|---|
| 124 | if isDirty then
|
|---|
| 125 | begin
|
|---|
| 126 | bmp.SetSize(Width + 1, Height + 1);
|
|---|
| 127 | Canvas := bmp.Canvas;
|
|---|
| 128 | try
|
|---|
| 129 | Bmp.BeginUpdate(True);
|
|---|
| 130 | for row := 0 to Maze.Height-1 do
|
|---|
| 131 | for col := 0 to Maze.Width-1 do
|
|---|
| 132 | begin
|
|---|
| 133 | // Draw the empty cell frame
|
|---|
| 134 | Canvas.Brush.Color := CellColor[csEmpty];
|
|---|
| 135 | Canvas.Pen.Color := Canvas.Brush.Color;
|
|---|
| 136 |
|
|---|
| 137 | square.Top := row * CellDrawHeight;
|
|---|
| 138 | square.Left := col * CellDrawWidth;
|
|---|
| 139 | square.Right := square.Left + CellDrawWidth;
|
|---|
| 140 | square.Bottom := square.Top + CellDrawHeight;
|
|---|
| 141 | Canvas.Rectangle(square);
|
|---|
| 142 |
|
|---|
| 143 | // draw walls
|
|---|
| 144 | Canvas.Pen.color := FWallColor;
|
|---|
| 145 | Canvas.Pen.Width := C_LINE_THICK;
|
|---|
| 146 | Canvas.Pen.JoinStyle := pjsBevel;
|
|---|
| 147 | with Maze[row,col] do
|
|---|
| 148 | begin
|
|---|
| 149 | if not CanGo[dirNorth] then
|
|---|
| 150 | begin
|
|---|
| 151 | Canvas.Line(square.Left, Square.Top, square.right, square.Top);
|
|---|
| 152 | Canvas.Pen.color := clMoneyGreen;
|
|---|
| 153 | Canvas.Line(square.Left+1, Square.Top+1, square.right-1, square.Top+1);
|
|---|
| 154 | Canvas.Pen.color := clBlue;
|
|---|
| 155 | end;
|
|---|
| 156 | if not CanGo[dirSouth] then Canvas.Line(square.Left, Square.Bottom, square.right, square.Bottom);
|
|---|
| 157 | if not CanGo[dirWest] then
|
|---|
| 158 | begin
|
|---|
| 159 | Canvas.Line(square.Left, Square.Top, square.Left, square.Bottom);
|
|---|
| 160 | Canvas.Pen.color := clMoneyGreen;
|
|---|
| 161 | Canvas.Line(square.Left+1, Square.Top+1, square.Left+1, square.Bottom-1);
|
|---|
| 162 | Canvas.Pen.color := clBlue;
|
|---|
| 163 | end;
|
|---|
| 164 | if not CanGo[dirEast] then Canvas.Line(square.Right, Square.Top, square.Right, square.Bottom);
|
|---|
| 165 | end;
|
|---|
| 166 |
|
|---|
| 167 | // Draw inside when the cell is not empty
|
|---|
| 168 | if Maze[row,col].State <> csEmpty then
|
|---|
| 169 | begin
|
|---|
| 170 | // Determine a visibly pleasing margin with the walls
|
|---|
| 171 | if FCellDrawWidth < 13 then dx := -1 else dx := -3;
|
|---|
| 172 | if FCellDrawHeight < 13 then dy := -1 else dy := -3;
|
|---|
| 173 | // Shring by this margin and draw the cell's inside
|
|---|
| 174 | Grow(square, dx, dy);
|
|---|
| 175 | Canvas.Brush.Color := CellColor[Maze[row,col].State];
|
|---|
| 176 | Canvas.Pen.Color := CellColor[Maze[row,col].State];
|
|---|
| 177 | Canvas.Rectangle(square);
|
|---|
| 178 | end;
|
|---|
| 179 | end;
|
|---|
| 180 |
|
|---|
| 181 | finally
|
|---|
| 182 | Bmp.EndUpdate;
|
|---|
| 183 | end;
|
|---|
| 184 | // Fully refreshed
|
|---|
| 185 | isDirty := false;
|
|---|
| 186 | end;
|
|---|
| 187 |
|
|---|
| 188 | // Draw bitmap
|
|---|
| 189 | FCanvas.Draw(pOffsetX, pOffsetY, Bmp); // Stretch draw should be faster
|
|---|
| 190 | //FCanvas.CopyRect(Rect(pOffsetX,pOffsetY,pOffsetX+Width+1,pOffsetY+Height+1), bmp.Canvas, Rect(0,0,Width+1,Height+1));
|
|---|
| 191 | end;
|
|---|
| 192 |
|
|---|
| 193 | function TMazePainter.Width: integer;
|
|---|
| 194 | begin
|
|---|
| 195 | result := Maze.Width * CellDrawWidth;
|
|---|
| 196 | end;
|
|---|
| 197 |
|
|---|
| 198 | function TMazePainter.Height: integer;
|
|---|
| 199 | begin
|
|---|
| 200 | result := Maze.Height * CellDrawHeight;
|
|---|
| 201 | end;
|
|---|
| 202 |
|
|---|
| 203 | end.
|
|---|
| 204 |
|
|---|