source: branches/zoom/MiniMap.pas

Last change on this file was 704, checked in by chronos, 2 weeks ago
  • Fixed: Enable map move keys also in editor mode.
File size: 13.1 KB
Line 
1{$INCLUDE Switches.inc}
2unit MiniMap;
3
4interface
5
6uses
7 Classes, SysUtils, Protocol, ClientTools, Map,
8 {$IFDEF DPI}Dpi.Graphics, Dpi.Common{$ELSE}Graphics{$ENDIF};
9
10type
11 TMiniMode = (mmNone, mmPicture, mmMultiPlayer);
12 TMapArray = array [0 .. lxmax * lymax - 1] of Byte;
13
14 { TMiniMap }
15
16 TMiniMap = class
17 const
18 MaxWidthMapLogo = 96;
19 MaxHeightMapLogo = 96;
20 var
21 Bitmap: TBitmap; { game world sample preview }
22 Size: TPoint;
23 Colors: array [0..31, 0..1] of TColor;
24 Mode: TMiniMode;
25 MapOptions: TMapOptions;
26 procedure LoadFromLogFile(FileName: string; var LastTurn: Integer; DefaultSize: TPoint);
27 procedure LoadFromMapFile(FileName: string; var nMapLandTiles, nMapStartPositions: Integer);
28 procedure PaintMap(Map: TMap);
29 procedure PaintRandom(Brightness, StartLandMass: Integer; WorldSize: TPoint);
30 procedure PaintFile(SaveMap: TMapArray);
31 procedure Paint(MyMap: PTileList; MapWidth: Integer; ClientMode: Integer;
32 xxt, xwMini: Integer);
33 constructor Create;
34 destructor Destroy; override;
35 end;
36
37
38implementation
39
40uses
41 {$IFDEF DPI}Dpi.PixelPointer,{$ELSE}PixelPointer,{$ENDIF}
42 ScreenTools, Global, GameServer, IsoEngine, Tribes;
43
44const
45 // save map tile flags
46 smOwned = $20;
47 smUnit = $40;
48 smCity = $80;
49
50{ TMiniMap }
51
52constructor TMiniMap.Create;
53var
54 X, Y: Integer;
55begin
56 Bitmap := TBitmap.Create;
57
58 for X := 0 to 11 do
59 for Y := 0 to 1 do
60 Colors[X, Y] := HGrSystem.Data.Canvas.Pixels[66 + X, 67 + Y];
61end;
62
63destructor TMiniMap.Destroy;
64begin
65 FreeAndNil(Bitmap);
66 inherited;
67end;
68
69procedure TMiniMap.LoadFromLogFile(FileName: string; var LastTurn: Integer; DefaultSize: TPoint);
70var
71 SaveMap: TMapArray;
72 Version: Cardinal;
73 FileLandMass: Integer;
74 LogFile: TFileStream;
75 ReadFileId: string;
76 ExeInfoTime: LongInt;
77 RNG: Integer;
78 MaxTurn: Integer;
79const
80 FileId = 'cEvoBook';
81begin
82 Version := 0;
83 ExeInfoTime := 0;
84 FileLandMass := 0;
85 MaxTurn := 0;
86 RNG := 0;
87
88 LogFile := TFileStream.Create(FileName, fmOpenRead or fmShareExclusive);
89 try
90 ReadFileId := default(string);
91 SetLength(ReadFileId, 8);
92 LogFile.Read(ReadFileId[1], 8); { file id }
93 if ReadFileId <> FileId then
94 raise Exception.Create('Incorrect game file id. Expected ''' + Trim(FileId) +
95 ''' but ''' + Trim(ReadFileId) + ''' read.');
96 LogFile.Read(Version, 4); { format id }
97 if Version >= $000E01 then
98 LogFile.Read(ExeInfoTime, 4); { item stored since 0.14.1 }
99 LogFile.Read(Size.X, 4);
100 LogFile.Read(Size.Y, 4);
101 LogFile.Read(FileLandMass, 4);
102
103 if FileLandMass = 0 then
104 LogFile.Seek(Size.Y * Size.X * 4, soCurrent);
105 LogFile.Read(MaxTurn, 4);
106 LogFile.Read(RNG, 4);
107 LogFile.Read(LastTurn, 4);
108 LogFile.Read(SaveMap, 4);
109 if SaveMap[0] = $80 then
110 Mode := mmMultiPlayer
111 else
112 Mode := mmPicture;
113 if Mode = mmPicture then
114 if Size.X * Size.Y <= Length(SaveMap) then
115 LogFile.Read(SaveMap[4], Size.X * Size.Y - 4)
116 else raise Exception.Create('Saved map data too big [' + IntToStr(Size.X) + 'x' + IntToStr(Size.Y) + ']');
117 LogFile.Free;
118 except
119 LogFile.Free;
120 LastTurn := 0;
121 Size := DefaultSize;
122 Mode := mmNone;
123 end;
124 PaintFile(SaveMap);
125end;
126
127procedure TMiniMap.LoadFromMapFile(FileName: string; var nMapLandTiles, nMapStartPositions: Integer);
128var
129 X, Y: Integer;
130 ImageFileName: string;
131 Map: TMap;
132 Tile: Cardinal;
133 PaintMapEnabled: Boolean;
134begin
135 ImageFileName := Copy(FileName, 1, Length(FileName) - Length(CevoMapExt)) + CevoMapPictureExt;
136 Mode := mmPicture;
137 if LoadGraphicFile(Bitmap, ImageFileName, [gfNoError]) then
138 begin
139 if Bitmap.Width div 2 > MaxWidthMapLogo then
140 Bitmap.Width := MaxWidthMapLogo * 2;
141 if Bitmap.Height > MaxHeightMapLogo then
142 Bitmap.Height := MaxHeightMapLogo;
143 Size := Point(Bitmap.Width div 2, Bitmap.Height);
144 PaintMapEnabled := False;
145 end else begin
146 Mode := mmPicture;
147 Size := Point(MaxWidthMapLogo, MaxHeightMapLogo);
148 PaintMapEnabled := True;
149 end;
150
151 Map := TMap.Create;
152 try
153 Map.LoadFromFile(FileName);
154 nMapLandTiles := 0;
155 nMapStartPositions := 0;
156 for Y := 0 to Map.Size.Y - 1 do begin
157 for X := 0 to Map.Size.X - 1 do begin
158 Tile := Map.Tiles[Y * Map.Size.X + X];
159 if (Tile and fTerrain) in [fGrass, fPrairie, fTundra, fSwamp,
160 fForest, fHills] then
161 Inc(nMapLandTiles);
162 if Tile and (fPrefStartPos or fStartPos) <> 0 then
163 Inc(nMapStartPositions);
164 end;
165 end;
166 if nMapStartPositions > nPl then
167 nMapStartPositions := nPl;
168
169 if PaintMapEnabled then begin
170 Size := Map.Size;
171 PaintMap(Map);
172 end;
173 finally
174 FreeAndNil(Map);
175 end;
176end;
177
178procedure TMiniMap.PaintMap(Map: TMap);
179var
180 I, X, Y, XM, CM, Tile: Integer;
181 MiniPixel: TPixelPointer;
182 PrevMiniPixel: TPixelPointer;
183 XX, YY: Integer;
184begin
185 Bitmap.PixelFormat := TPixelFormat.pf24bit;
186 Bitmap.SetSize(Size.X * 2, Size.Y);
187 if Mode = mmPicture then begin
188 Bitmap.BeginUpdate;
189 MiniPixel := TPixelPointer.Create(Bitmap);
190 PrevMiniPixel := TPixelPointer.Create(Bitmap);
191 XX := ScaleToNative(Size.X);
192 YY := ScaleToNative(Size.Y);
193 for Y := 0 to YY - 1 do begin
194 for X := 0 to XX - 1 do begin
195 for I := 0 to 1 do begin
196 XM := (X * 2 + I + Y and 1) mod (XX * 2);
197 MiniPixel.SetX(XM);
198 Tile := Map.Tiles[ScaleFromNative(X) + Size.X * ScaleFromNative(Y)];
199 if Tile and fTerrain = fUNKNOWN then CM := $000000
200 else CM := Colors[Tile and fTerrain, I];
201 if (PByte(MiniPixel.Pixel) >= Bitmap.RawImage.Data) and
202 (PByte(MiniPixel.Pixel) < (Bitmap.RawImage.Data + YY * MiniPixel.BytesPerLine)) then begin
203 MiniPixel.PixelB := (CM shr 16) and $ff;
204 MiniPixel.PixelG := (CM shr 8) and $ff;
205 MiniPixel.PixelR := (CM shr 0) and $ff;
206 end;
207 end;
208 end;
209 MiniPixel.NextLine;
210 if Y > 0 then PrevMiniPixel.NextLine;
211 end;
212 Bitmap.EndUpdate;
213 end;
214end;
215
216procedure TMiniMap.PaintRandom(Brightness, StartLandMass: Integer; WorldSize: TPoint);
217var
218 I, X, Y, XM, CM: Integer;
219 MiniPixel: TPixelPointer;
220 Map: ^TTileList;
221 XX, YY: Integer;
222begin
223 Map := PreviewMap(StartLandMass);
224 Size := WorldSize;
225
226 Bitmap.PixelFormat := TPixelFormat.pf24bit;
227 Bitmap.SetSize(Size.X * 2, Size.Y);
228 Bitmap.BeginUpdate;
229 MiniPixel := TPixelPointer.Create(Bitmap);
230 XX := ScaleToNative(Size.X);
231 YY := ScaleToNative(Size.Y);
232 for Y := 0 to YY - 1 do begin
233 for X := 0 to XX - 1 do begin
234 for I := 0 to 1 do begin
235 XM := (X * 2 + I + Y and 1) mod (XX * 2);
236 MiniPixel.SetX(XM);
237 CM := Colors[Map[ScaleFromNative(X) * lxmax div Size.X + lxmax *
238 ((ScaleFromNative(Y) * (lymax - 1) + Size.Y div 2) div (Size.Y - 1))] and
239 fTerrain, I];
240 if (PByte(MiniPixel.Pixel) >= Bitmap.RawImage.Data) and
241 (PByte(MiniPixel.Pixel) < (Bitmap.RawImage.Data + YY * MiniPixel.BytesPerLine)) then begin
242 MiniPixel.PixelB := ((CM shr 16) and $FF) * Brightness div 3;
243 MiniPixel.PixelG := ((CM shr 8) and $FF) * Brightness div 3;
244 MiniPixel.PixelR := ((CM shr 0) and $FF) * Brightness div 3;
245 end;
246 end;
247 end;
248 MiniPixel.NextLine;
249 end;
250 Bitmap.EndUpdate;
251end;
252
253procedure TMiniMap.PaintFile(SaveMap: TMapArray);
254var
255 I, X, Y, XM, CM, Tile, OwnColor, EnemyColor: Integer;
256 MiniPixel: TPixelPointer;
257 PrevMiniPixel: TPixelPointer;
258 XX, YY: Integer;
259begin
260 OwnColor := HGrSystem.Data.Canvas.Pixels[95, 67];
261 EnemyColor := HGrSystem.Data.Canvas.Pixels[96, 67];
262 Bitmap.PixelFormat := TPixelFormat.pf24bit;
263 Bitmap.SetSize(Size.X * 2, Size.Y);
264 if Mode = mmPicture then begin
265 Bitmap.BeginUpdate;
266 MiniPixel := TPixelPointer.Create(Bitmap);
267 PrevMiniPixel := TPixelPointer.Create(Bitmap);
268 XX := ScaleToNative(Size.X);
269 YY := ScaleToNative(Size.Y);
270 for Y := 0 to YY - 1 do begin
271 for X := 0 to XX - 1 do begin
272 for I := 0 to 1 do begin
273 XM := (X * 2 + I + Y and 1) mod (XX * 2);
274 MiniPixel.SetX(XM);
275 Tile := SaveMap[ScaleFromNative(X) + Size.X * ScaleFromNative(Y)];
276 if Tile and fTerrain = fUNKNOWN then
277 CM := $000000
278 else if Tile and smCity <> 0 then begin
279 if Tile and smOwned <> 0 then CM := OwnColor
280 else CM := EnemyColor;
281 if Y > 0 then begin
282 // 2x2 city dot covers two lines
283 PrevMiniPixel.SetX(XM);
284 if (PByte(PrevMiniPixel.Pixel) >= Bitmap.RawImage.Data) and
285 (PByte(PrevMiniPixel.Pixel) < (Bitmap.RawImage.Data + YY * PrevMiniPixel.BytesPerLine)) then begin
286 PrevMiniPixel.PixelB := CM shr 16;
287 PrevMiniPixel.PixelG:= CM shr 8 and $FF;
288 PrevMiniPixel.PixelR := CM and $FF;
289 end;
290 end;
291 end
292 else if (I = 0) and (Tile and smUnit <> 0) then begin
293 if Tile and smOwned <> 0 then CM := OwnColor
294 else CM := EnemyColor;
295 end else
296 CM := Colors[Tile and fTerrain, I];
297 if (PByte(MiniPixel.Pixel) >= Bitmap.RawImage.Data) and
298 (PByte(MiniPixel.Pixel) < (Bitmap.RawImage.Data + YY * MiniPixel.BytesPerLine)) then begin
299 MiniPixel.PixelB := (CM shr 16) and $ff;
300 MiniPixel.PixelG := (CM shr 8) and $ff;
301 MiniPixel.PixelR := (CM shr 0) and $ff;
302 end;
303 end;
304 end;
305 MiniPixel.NextLine;
306 if Y > 0 then PrevMiniPixel.NextLine;
307 end;
308 Bitmap.EndUpdate;
309 end;
310end;
311
312procedure TMiniMap.Paint(MyMap: PTileList; MapWidth: Integer; ClientMode: Integer;
313 xxt, xwMini: Integer);
314var
315 X, Y, Loc, I, HW, XM, CM, cmPolOcean, cmPolNone: integer;
316 PrevMiniPixel: TPixelPointer;
317 MiniPixel: TPixelPointer;
318 TerrainTile: Cardinal;
319 MyCity: PCity;
320 EnemyCity: PCityInfo;
321 MyUnit: PUn;
322 EnemyUnit: PUnitInfo;
323 XX, YY: Integer;
324begin
325 if not Assigned(MyMap) then Exit;
326 cmPolOcean := HGrSystem.Data.Canvas.Pixels[101, 67];
327 cmPolNone := HGrSystem.Data.Canvas.Pixels[102, 67];
328 HW := MapWidth div (xxt * 2);
329 with Bitmap.Canvas do begin
330 Brush.Color := $000000;
331 FillRect(Rect(0, 0, Bitmap.Width, Bitmap.Height));
332 end;
333 Bitmap.PixelFormat := TPixelFormat.pf24bit;
334 Bitmap.SetSize(Size.X * 2, Size.Y);
335 Bitmap.BeginUpdate;
336 MiniPixel := TPixelPointer.Create(Bitmap);
337 PrevMiniPixel := TPixelPointer.Create(Bitmap);
338
339 XX := ScaleToNative(Size.X);
340 YY := ScaleToNative(Size.Y);
341 for Y := 0 to YY - 1 do begin
342 for X := 0 to XX - 1 do begin
343 Loc := ScaleFromNative(X) + Size.X * ScaleFromNative(Y);
344 if (MyMap[Loc] and fTerrain) <> fUNKNOWN then begin
345 for I := 0 to 1 do begin
346 XM := ((X - ScaleToNative(xwMini)) * 2 + I + Y and 1 - ScaleToNative(HW) +
347 XX * 5) mod (XX * 2);
348 MiniPixel.SetX(XM);
349 TerrainTile := MyMap[Loc] and fTerrain;
350 if TerrainTile > 11 then TerrainTile := 0;
351 CM := Colors[TerrainTile, I];
352 if ClientMode = cEditMap then begin
353 if MyMap[Loc] and (fPrefStartPos or fStartPos) <> 0 then
354 CM := $FFFFFF;
355 end
356 else if MyMap[Loc] and fCity <> 0 then begin
357 // City
358 MyCity := GetMyCityByLoc(Loc);
359 if Assigned(MyCity) then CM := Tribe[me].Color
360 else begin
361 EnemyCity := GetEnemyCityByLoc(Loc);
362 if Assigned(EnemyCity) then
363 CM := Tribe[EnemyCity^.Owner].Color;
364 end;
365 CM := $808080 or CM shr 1; { increase brightness }
366 if Y > 0 then begin
367 // 2x2 city dot covers two lines
368 PrevMiniPixel.SetX(XM);
369 if (PByte(PrevMiniPixel.Pixel) >= Bitmap.RawImage.Data) and
370 (PByte(PrevMiniPixel.Pixel) < (Bitmap.RawImage.Data + YY * PrevMiniPixel.BytesPerLine)) then begin
371 PrevMiniPixel.PixelB := (CM shr 16) and $ff;
372 PrevMiniPixel.PixelG := (CM shr 8) and $ff;
373 PrevMiniPixel.PixelR := (CM shr 0) and $ff;
374 end;
375 end;
376 end
377 else if (I = 0) and (MyMap[Loc] and fUnit <> 0) then begin
378 // Unit
379 MyUnit := GetMyUnitByLoc(Loc);
380 if Assigned(MyUnit) then CM := Tribe[me].Color
381 else begin
382 EnemyUnit := GetEnemyUnitByLoc(Loc);
383 if Assigned(EnemyUnit) then
384 CM := Tribe[EnemyUnit.Owner].Color;
385 end;
386 CM := $808080 or CM shr 1; { increase brightness }
387 end
388 else if moPolitical in MapOptions then begin
389 // Political
390 if MyMap[Loc] and fTerrain < fGrass then CM := cmPolOcean
391 else if MyRO.Territory[Loc] < 0 then CM := cmPolNone
392 else CM := Tribe[MyRO.Territory[Loc]].Color;
393 end;
394 if (PByte(MiniPixel.Pixel) >= Bitmap.RawImage.Data) and
395 (PByte(MiniPixel.Pixel) < (Bitmap.RawImage.Data + YY * MiniPixel.BytesPerLine)) then begin
396 MiniPixel.PixelB := (CM shr 16) and $ff;
397 MiniPixel.PixelG := (CM shr 8) and $ff;
398 MiniPixel.PixelR := (CM shr 0) and $ff;
399 end;
400 end;
401 end;
402 end;
403 MiniPixel.NextLine;
404 if Y > 0 then PrevMiniPixel.NextLine;
405 end;
406 Bitmap.EndUpdate;
407end;
408
409end.
410
411
Note: See TracBrowser for help on using the repository browser.