close Warning: Can't synchronize with repository "(default)" (No changeset 184 in the repository). Look in the Trac log for more information.

source: tags/1.2.0/UMap.pas

Last change on this file was 158, checked in by chronos, 6 years ago
  • Fixed: Show error message if not all players were placed to the map.
File size: 9.0 KB
Line 
1unit UMap;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, UGame, XMLRead, XMLWrite, DOM;
9
10type
11 { THexMap }
12
13 THexMap = class(TMap)
14 private
15 function IsCellsPosNeighbor(CellPos1, CellPos2: TPoint): Boolean;
16 procedure GetCellPosNeighbors(CellPos: TPoint; Neighbours: TCells);
17 function GetHexagonPolygon(Pos: TPoint; Size: TPoint): TPointArray;
18 public
19 procedure LoadFromFile(FileName: string); override;
20 procedure SaveToFile(FileName: string); override;
21 function IsValidIndex(Index: TPoint): Boolean; override;
22 procedure Generate; override;
23 end;
24
25 { TSquareMap }
26
27 TSquareMap = class(TMap)
28 private
29 function GetSquarePolygon(Pos: TPoint; Size: TPoint): TPointArray;
30 public
31 function IsValidIndex(Index: TPoint): Boolean; override;
32 procedure Generate; override;
33 end;
34
35 { TTriangleMap }
36
37 TTriangleMap = class(TMap)
38 private
39 function GetTrianglePolygon(Pos: TPoint; Size: TPoint; Reverse: Boolean): TPointArray;
40 public
41 function IsValidIndex(Index: TPoint): Boolean; override;
42 procedure Generate; override;
43 end;
44
45 { TVoronoiMap }
46
47 TVoronoiMap = class(TMap)
48 private
49 function GetTrianglePolygon(Pos: TPoint; Size: TPoint; Reverse: Boolean): TPointArray;
50 public
51 procedure Generate; override;
52 end;
53
54
55implementation
56
57{ THexMap }
58
59function THexMap.GetHexagonPolygon(Pos: TPoint; Size: TPoint): TPointArray;
60var
61 Shift: TFloatPoint;
62begin
63 Shift := FloatPoint(0.5 * cos(30 / 180 * Pi), 0.5 * sin(30 / 180 * Pi));
64 SetLength(Result, 6);
65 Result[0] := Point(Trunc(Pos.X + 0 * Size.X), Trunc(Pos.Y - 0.5 * Size.Y));
66 Result[1] := Point(Trunc(Pos.X + Shift.X * Size.X), Trunc(Pos.Y - Shift.Y * Size.Y));
67 Result[2] := Point(Trunc(Pos.X + Shift.X * Size.X), Trunc(Pos.Y + Shift.Y * Size.Y));
68 Result[3] := Point(Trunc(Pos.X + 0 * Size.X), Trunc(Pos.Y + 0.5 * Size.Y));
69 Result[4] := Point(Trunc(Pos.X - Shift.X * Size.X), Trunc(Pos.Y + Shift.Y * Size.Y));
70 Result[5] := Point(Trunc(Pos.X - Shift.X * Size.X), Trunc(Pos.Y - Shift.Y * Size.Y));
71end;
72
73function THexMap.IsCellsPosNeighbor(CellPos1, CellPos2: TPoint): Boolean;
74var
75 DX: Integer;
76 DY: Integer;
77 MinY: Integer;
78begin
79 if CellPos1.Y < CellPos2.Y then MinY:= CellPos1.Y
80 else MinY := CellPos2.Y;
81 DX := CellPos2.X - CellPos1.X;
82 DY := CellPos2.Y - CellPos1.Y;
83 Result := (Abs(DX) <= 1) and (Abs(DY) <= 1) and
84 ((((MinY mod 2) = 1) and
85 not ((DX = 1) and (DY = -1)) and
86 not ((DX = -1) and (DY = 1))) or
87 (((MinY mod 2) = 0) and
88 not ((DX = -1) and (DY = -1)) and
89 not ((DX = 1) and (DY = 1))));
90 Result := Result and not ((CellPos1.X = CellPos2.X) and (CellPos1.Y = CellPos2.Y));
91end;
92
93procedure THexMap.LoadFromFile(FileName: string);
94var
95 Doc: TXMLDocument;
96begin
97 try
98 ReadXMLFile(Doc, FileName);
99 if Doc.DocumentElement.TagName <> 'Map' then
100 raise Exception.Create('Invalid map format');
101 finally
102 Doc.Free;
103 end;
104 inherited LoadFromFile(FileName);
105end;
106
107procedure THexMap.SaveToFile(FileName: string);
108var
109 Doc: TXMLDocument;
110 RootNode: TDOMNode;
111begin
112 try
113 Doc := TXMLDocument.Create;
114 RootNode := Doc.CreateElement('Map');
115 Doc.Appendchild(RootNode);
116 WriteXMLFile(Doc, FileName);
117 finally
118 Doc.Free;
119 end;
120 inherited SaveToFile(FileName);
121end;
122
123function THexMap.IsValidIndex(Index: TPoint): Boolean;
124begin
125 Result := (Index.X >= 0) and (Index.X < Size.X) and
126 (Index.Y >= 0) and (Index.Y < Size.Y);
127end;
128
129procedure THexMap.GetCellPosNeighbors(CellPos: TPoint; Neighbours: TCells);
130var
131 X, Y: Integer;
132begin
133 Neighbours.Count := 0;
134 for Y := -1 to 1 do
135 for X := -1 to 1 do
136 if IsValidIndex(Point(CellPos.X + X, CellPos.Y + Y)) and
137 IsCellsPosNeighbor(CellPos, Point((CellPos.X + X), (CellPos.Y + Y))) then begin
138 Neighbours.Add(TCell(Cells[(CellPos.Y + Y) * Size.X + (CellPos.X + X)]));
139 end;
140end;
141
142procedure THexMap.Generate;
143var
144 X, Y: Integer;
145 NewCell: TCell;
146 PX, PY: Double;
147begin
148 Clear;
149
150 // Allocate and init new
151 Cells.Count := Size.Y * Size.X;
152 for Y := 0 to Size.Y - 1 do
153 for X := 0 to Size.X - 1 do begin
154 NewCell := TCell.Create;
155 NewCell.Map := Self;
156 PX := X;
157 PY := Y;
158 if (Y and 1) = 1 then begin
159 PX := PX + 0.5;
160 //Y := Y + 0.5;
161 end;
162 NewCell.PosPx := Point(Trunc(PX * DefaultCellSize.X / HexCellMulX),
163 Trunc(PY * DefaultCellSize.Y / HexCellMulY));
164 NewCell.Polygon := GetHexagonPolygon(NewCell.PosPx, DefaultCellSize);
165 NewCell.Id := GetNewCellId;
166 Cells[Y * Size.X + X] := NewCell;
167 end;
168
169 // Generate neightbours
170 for Y := 0 to Size.Y - 1 do
171 for X := 0 to Size.X - 1 do
172 with TCell(Cells[Y * Size.X + X]) do begin
173 GetCellPosNeighbors(Point(X, Y), Neighbors);
174 end;
175
176 FPixelRect := CalculatePixelRect;
177end;
178
179
180{ TSquareMap }
181
182procedure TSquareMap.Generate;
183var
184 X, Y: Integer;
185 NewCell: TCell;
186begin
187 Clear;
188
189 // Allocate and init new
190 Cells.Count := Size.Y * Size.X;
191 for Y := 0 to Size.Y - 1 do
192 for X := 0 to Size.X - 1 do begin
193 NewCell := TCell.Create;
194 NewCell.Map := Self;
195 NewCell.PosPx := Point(Trunc(X * DefaultCellSize.X * SquareCellMulX),
196 Trunc(Y * DefaultCellSize.Y * SquareCellMulY));
197 NewCell.Polygon := GetSquarePolygon(NewCell.PosPx, DefaultCellSize);
198 NewCell.Id := GetNewCellId;
199 Cells[Y * Size.X + X] := NewCell;
200 end;
201
202 // Generate neighbours
203 for Y := 0 to Size.Y - 1 do
204 for X := 0 to Size.X - 1 do
205 with TCell(Cells[Y * Size.X + X]) do begin
206 if IsValidIndex(Point(X + 1, Y + 0)) then
207 Neighbors.Add(TCell(Cells[(Y + 0) * Size.X + (X + 1)]));
208 if IsValidIndex(Point(X + 0, Y + 1)) then
209 Neighbors.Add(TCell(Cells[(Y + 1) * Size.X + (X + 0)]));
210 if IsValidIndex(Point(X - 1, Y + 0)) then
211 Neighbors.Add(TCell(Cells[(Y + 0) * Size.X + (X - 1)]));
212 if IsValidIndex(Point(X + 0, Y - 1)) then
213 Neighbors.Add(TCell(Cells[(Y - 1) * Size.X + (X + 0)]));
214 end;
215
216 FPixelRect := CalculatePixelRect;
217end;
218
219function TSquareMap.IsValidIndex(Index: TPoint): Boolean;
220begin
221 Result := (Index.X >= 0) and (Index.X < Size.X) and
222 (Index.Y >= 0) and (Index.Y < Size.Y);
223end;
224
225function TSquareMap.GetSquarePolygon(Pos: TPoint; Size: TPoint): TPointArray;
226begin
227 SetLength(Result, 4);
228 Result[0] := Point(Trunc(Pos.X - Size.X / 2), Trunc(Pos.Y - Size.Y / 2));
229 Result[1] := Point(Trunc(Pos.X + Size.X / 2), Trunc(Pos.Y - Size.Y / 2));
230 Result[2] := Point(Trunc(Pos.X + Size.X / 2), Trunc(Pos.Y + Size.Y / 2));
231 Result[3] := Point(Trunc(Pos.X - Size.X / 2), Trunc(Pos.Y + Size.Y / 2));
232end;
233
234{ TVoronoiMap }
235
236function TVoronoiMap.GetTrianglePolygon(Pos: TPoint; Size: TPoint;
237 Reverse: Boolean): TPointArray;
238begin
239 SetLength(Result, 0);
240end;
241
242procedure TVoronoiMap.Generate;
243var
244 X, Y: Integer;
245 NewCell: TCell;
246begin
247 Clear;
248
249 // Allocate and init new
250 Cells.Count := Size.Y * Size.X;
251 for Y := 0 to Size.Y - 1 do
252 for X := 0 to Size.X - 1 do begin
253 NewCell := TCell.Create;
254 NewCell.Map := Self;
255 NewCell.PosPx := Point(Trunc(Random * Size.X * DefaultCellSize.X),
256 Trunc(Random * Size.Y * DefaultCellSize.Y));
257 SetLength(NewCell.Polygon, 1);
258 NewCell.Polygon[0] := NewCell.PosPx;
259 NewCell.Id := GetNewCellId;
260 Cells[Y * Size.X + X] := NewCell;
261 end;
262
263 FPixelRect := CalculatePixelRect;
264end;
265
266{ TTriangleMap }
267
268function TTriangleMap.GetTrianglePolygon(Pos: TPoint; Size: TPoint;
269 Reverse: Boolean): TPointArray;
270var
271 Rev: Integer;
272begin
273 if Reverse then Rev := -1
274 else Rev := 1;
275 SetLength(Result, 3);
276 Result[0] := Point(Trunc(Pos.X - Size.X / 2), Trunc(Pos.Y - (Size.Y * 0.8) / 2 * Rev));
277 Result[1] := Point(Trunc(Pos.X + Size.X / 2), Trunc(Pos.Y - (Size.Y * 0.8) / 2 * Rev));
278 Result[2] := Point(Trunc(Pos.X), Trunc(Pos.Y + (Size.Y * 1.2) / 2 * Rev));
279end;
280
281function TTriangleMap.IsValidIndex(Index: TPoint): Boolean;
282begin
283 Result := (Index.X >= 0) and (Index.X < Size.X) and
284 (Index.Y >= 0) and (Index.Y < Size.Y);
285end;
286
287procedure TTriangleMap.Generate;
288var
289 X, Y: Integer;
290 Rev: Integer;
291 Reverse: Boolean;
292 NewCell: TCell;
293begin
294 Clear;
295
296 // Allocate and init new
297 Cells.Count := Size.Y * Size.X;
298 for Y := 0 to Size.Y - 1 do
299 for X := 0 to Size.X - 1 do begin
300 NewCell := TCell.Create;
301 NewCell.Map := Self;
302 Reverse := Boolean(X mod 2) xor Boolean(Y mod 2);
303 if Reverse then Rev := -1
304 else Rev := 1;
305 NewCell.PosPx := Point(Trunc(X * DefaultCellSize.X * TriangleCellMulX),
306 Trunc((Y * DefaultCellSize.Y * TriangleCellMulY) - (0.1 * Rev * DefaultCellSize.Y)));
307 NewCell.Polygon := GetTrianglePolygon(NewCell.PosPx, DefaultCellSize, Reverse);
308 NewCell.Id := GetNewCellId;
309 Cells[Y * Size.X + X] := NewCell;
310 end;
311
312 // Generate neighbours
313 for Y := 0 to Self.Size.Y - 1 do
314 for X := 0 to Size.X - 1 do
315 with TCell(Cells[Y * Size.X + X]) do begin
316 if Boolean(X mod 2) xor Boolean(Y mod 2) then Rev := -1
317 else Rev := 1;
318 if IsValidIndex(Point(X + 1, Y + 0)) then
319 Neighbors.Add(TCell(Cells[(Y + 0) * Size.X + (X + 1)]));
320 if IsValidIndex(Point(X + 0, Y - 1 * Rev)) then
321 Neighbors.Add(TCell(Cells[(Y - 1 * Rev) * Size.X + (X + 0)]));
322 if IsValidIndex(Point(X - 1, Y + 0)) then
323 Neighbors.Add(TCell(Cells[(Y + 0) * Size.X + (X - 1)]));
324 end;
325
326 FPixelRect := CalculatePixelRect;
327end;
328
329
330end.
331
Note: See TracBrowser for help on using the repository browser.