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