MathgeomGLS
422 строки · 8.6 Кб
1unit fConways;
2
3interface
4
5uses
6Winapi.Windows,
7Winapi.Messages,
8System.Types,
9System.SysUtils,
10System.Variants,
11System.Classes,
12Vcl.Graphics,
13Vcl.Forms,
14Vcl.Dialogs,
15Vcl.Menus,
16Vcl.ComCtrls,
17Vcl.ToolWin,
18Vcl.ExtDlgs,
19Vcl.ExtCtrls,
20Vcl.StdCtrls,
21Vcl.Buttons,
22Vcl.Samples.Spin,
23Vcl.Controls,
24
25
26GLS.VectorTypes,
27GLS.Graphics,
28GLS.Cadencer,
29GLS.Texture,
30GLS.SceneViewer,
31GLS.Scene,
32GLS.Objects,
33GLS.AsyncTimer,
34GLS.Utils,
35GLS.HUDObjects,
36GLS.Coordinates,
37GLS.BaseClasses;
38
39type
40TForm1 = class(TForm)
41GLScene: TGLScene;
42vp: TGLSceneViewer;
43cam: TGLCamera;
44hudMap: TGLHUDSprite;
45AsyncTimer: TGLAsyncTimer;
46OpenDlg: TOpenPictureDialog;
47SaveDlg: TSavePictureDialog;
48Panel2: TPanel;
49Panel5: TPanel;
50Label4: TLabel;
51Edit2: TEdit;
52UpDown2: TUpDown;
53Edit3: TEdit;
54UpDown3: TUpDown;
55Label5: TLabel;
56Panel7: TPanel;
57Panel8: TPanel;
58Label1: TLabel;
59Edit4: TEdit;
60UpDown4: TUpDown;
61Button3: TButton;
62but_run: TSpeedButton;
63cb: TCheckBox;
64MainMenu: TMainMenu;
65N1: TMenuItem;
66Open1: TMenuItem;
67Save1: TMenuItem;
68N2: TMenuItem;
69Exit1: TMenuItem;
70Help1: TMenuItem;
71About1: TMenuItem;
72New1: TMenuItem;
73procedure FormCreate(Sender: TObject);
74procedure vpMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
75procedure AsyncTimerTimer(Sender: TObject);
76procedure vpMouseDown(Sender: TObject; Button: TMouseButton;
77Shift: TShiftState; X, Y: Integer);
78procedure Button3Click(Sender: TObject);
79procedure UpDown2Click(Sender: TObject; Button: TUDBtnType);
80procedure UpDown3Click(Sender: TObject; Button: TUDBtnType);
81procedure FormClose(Sender: TObject; var Action: TCloseAction);
82procedure UpDown4Click(Sender: TObject; Button: TUDBtnType);
83procedure FormResize(Sender: TObject);
84procedure About1Click(Sender: TObject);
85procedure Open1Click(Sender: TObject);
86procedure Save1Click(Sender: TObject);
87public
88procedure Init(a_Width, a_Height: Integer);
89procedure SetPixel(a_Xpos, a_Ypos: Integer; a_Get: boolean);
90procedure resizeMap;
91end;
92
93var
94Form1: TForm1;
95mapsz: TPoint;
96br: boolean;
97ma: single;
98buf: array [0 .. 1] of TGLImage;
99bufi: Integer = 0;
100
101implementation
102
103{$R *.dfm}
104
105procedure TForm1.FormCreate;
106begin
107// create default map 32x32
108Init(32, 32);
109
110Opendlg.InitialDir := extractfilepath(paramStr(0)) + 'maps';
111Savedlg.InitialDir := opendlg.InitialDir;
112end;
113
114function RGBA(r, g, b: Byte): TGLPixel32;
115begin
116result.r := r;
117result.g := g;
118result.b := b;
119result.a := 255;
120end;
121
122procedure TForm1.Init(a_Width, a_Height: Integer);
123var
124a1, a2: Integer;
125bmp: TBitmap;
126
127begin
128bufi := 0;
129mapsz := point(a_Width, a_Height);
130
131// prepare buf's
132if assigned(buf[0]) then
133buf[0].Free;
134buf[0] := TGLImage.Create;
135if assigned(buf[1]) then
136buf[1].Free;
137buf[1] := TGLImage.Create;
138
139bmp := TBitmap.Create;
140bmp.Width := a_Width;
141bmp.Height := a_Height;
142
143// fill buf's
144for a1 := 0 to a_Width - 1 do
145for a2 := 0 to a_Height - 1 do
146if (a1 xor a2) and 1 > 0 then
147bmp.Canvas.Pixels[a1, a2] := $FFFFFF
148else
149bmp.Canvas.Pixels[a1, a2] := $E0E0E0;
150buf[0].Assign(bmp);
151buf[1].Assign(bmp);
152
153bmp.Free;
154
155hudMap.Width := a_Width;
156hudMap.Height := a_Height;
157hudMap.Material.Texture.Image.Assign(buf[0]);
158
159resizeMap;
160end;
161
162
163procedure TForm1.SetPixel(a_Xpos, a_Ypos: Integer; a_Get: boolean);
164var
165sx, sy, p, a: Integer;
166
167begin
168// convert coords
169sx := round((a_Xpos - hudMap.Position.X + hudMap.Width / 2 - ma / 2) / ma);
170sy := round((hudMap.Height / 2 + hudMap.Position.Y - a_Ypos - ma / 2) / ma);
171
172// correct coords
173if sx < 0 then
174sx := 0;
175if sx > mapsz.X - 1 then
176sx := mapsz.X - 1;
177if sy < 0 then
178sy := 0;
179if sy > mapsz.Y - 1 then
180sy := mapsz.Y - 1;
181
182p := sy * mapsz.X + sx;
183
184// get point state or draw
185if a_Get then
186br := buf[bufi].Data[p].r > 0;
187if br then
188buf[bufi].Data[p] := RGBA(0, 0, 0)
189else
190begin
191a := 255 - 31 * ((sx xor sy) and 1);
192buf[bufi].Data[p] := RGBA(a, a, a);
193end;
194
195hudMap.Material.Texture.Image.Assign(buf[bufi]);
196end;
197
198procedure TForm1.resizeMap;
199begin
200// find min size
201if vp.Width > vp.Height then
202ma := vp.Height
203else
204ma := vp.Width;
205
206// proportion
207if mapsz.X > mapsz.Y then
208ma := ma / mapsz.X
209else
210ma := ma / mapsz.Y;
211
212hudMap.Width := ma * mapsz.X;
213hudMap.Height := ma * mapsz.Y;
214end;
215
216procedure TForm1.About1Click(Sender: TObject);
217begin
218MessageDlg('ConwaysLife. @ GLScene Team', mtInformation,
219[mbOk], 0, mbOk);
220end;
221
222procedure TForm1.AsyncTimerTimer(Sender: TObject);
223var
224a1, a2, a3, a4, p: Integer;
225c: boolean;
226
227function GetN(X, Y: Integer): Integer;
228
229function Get(X, Y: Integer): boolean;
230begin
231
232// border check
233if not cb.Checked then
234begin
235if X < 0 then
236X := mapsz.X - 1;
237if X > mapsz.X - 1 then
238X := 0;
239if Y < 0 then
240Y := mapsz.Y - 1;
241if Y > mapsz.Y - 1 then
242Y := 0;
243result := buf[bufi].Data[Y * mapsz.X + X].r = 0;
244end
245else if (X >= 0) and (X < mapsz.X) and (Y >= 0) and (Y < mapsz.Y) then
246result := buf[bufi].Data[Y * mapsz.X + X].r = 0
247else
248result := false;
249end;
250
251begin
252result := 0;
253
254if Get(X - 1, Y - 1) then
255inc(result);
256if Get(X - 1, Y) then
257inc(result);
258if Get(X - 1, Y + 1) then
259inc(result);
260if Get(X, Y - 1) then
261inc(result);
262if Get(X, Y + 1) then
263inc(result);
264if Get(X + 1, Y - 1) then
265inc(result);
266if Get(X + 1, Y) then
267inc(result);
268if Get(X + 1, Y + 1) then
269inc(result);
270end;
271
272begin
273if not but_run.Down then
274exit;
275
276// main loop
277for a1 := 0 to mapsz.X - 1 do
278for a2 := 0 to mapsz.Y - 1 do
279begin
280
281a3 := GetN(a1, a2);
282a4 := 255 - 31 * ((a1 xor a2) and 1);
283
284p := a2 * mapsz.X + a1;
285
286// main algorithm
287if buf[bufi].Data[p].r = 0 then
288c := (a3 = 2) or (a3 = 3)
289else
290c := a3 = 3;
291
292if c then
293buf[1 - bufi].Data[p] := RGBA(0, 0, 0)
294else
295buf[1 - bufi].Data[p] := RGBA(a4, a4, a4);
296
297end;
298
299bufi := 1 - bufi;
300hudMap.Material.Texture.Image.Assign(buf[bufi]);
301end;
302
303// LoadMap
304
305procedure TForm1.Open1Click(Sender: TObject);
306var
307a1, a2, p: Integer;
308bmp: TBitmap;
309begin
310if not opendlg.Execute then
311exit;
312
313bufi := 0;
314bmp := TBitmap.Create;
315bmp.LoadFromFile(opendlg.FileName);
316
317mapsz := point(bmp.Width, bmp.Height);
318buf[0].Assign(bmp);
319buf[1].Assign(bmp);
320
321bmp.Free;
322hudMap.Width := mapsz.X;
323hudMap.Height := mapsz.Y;
324
325for a1 := 0 to mapsz.X - 1 do
326for a2 := 0 to mapsz.Y - 1 do
327begin
328p := a2 * mapsz.X + a1;
329with buf[bufi] do
330if (Data[p].r + Data[p].g + Data[p].b) < 192 then
331Data[p] := RGBA(0, 0, 0)
332else if (a1 xor a2) and 1 = 1 then
333Data[p] := RGBA(224, 224, 224)
334else
335Data[p] := RGBA(255, 255, 255);
336end;
337
338HudMap.Material.Texture.Image.Assign(buf[bufi]);
339
340ResizeMap;
341end;
342
343
344// Save Map
345
346procedure TForm1.Save1Click(Sender: TObject);
347var
348bmp: TBitmap;
349begin
350if not savedlg.Execute then
351exit;
352
353bmp := TBitmap.Create;
354bmp.PixelFormat := pf1bit;
355buf[bufi].AssignToBitmap(bmp);
356bmp.SaveToFile(savedlg.FileName);
357bmp.Free;
358end;
359
360
361
362// MouseDown to SetPixel
363procedure TForm1.vpMouseDown(Sender: TObject; Button: TMouseButton;
364Shift: TShiftState; X, Y: Integer);
365begin
366if Button = TMouseButton.mbLeft then
367SetPixel(X, Y, true);
368end;
369
370// MouseMove to SetPixel
371procedure TForm1.vpMouseMove(Sender: TObject; Shift: TShiftState;
372X, Y: Integer);
373begin
374if Shift = [ssleft] then
375SetPixel(X, Y, false);
376end;
377
378// newWidth
379procedure TForm1.UpDown2Click(Sender: TObject; Button: TUDBtnType);
380begin
381Edit2.Text := inttostr(32 shl UpDown2.Position);
382end;
383
384// newImage
385procedure TForm1.Button3Click(Sender: TObject);
386begin
387Init(StrToInt(Edit2.Text), StrToInt(Edit3.Text));
388end;
389
390
391// newHeight
392procedure TForm1.UpDown3Click(Sender: TObject; Button: TUDBtnType);
393begin
394Edit3.Text := IntToStr(32 shl UpDown3.Position);
395end;
396
397// newInterval
398procedure TForm1.UpDown4Click(Sender: TObject; Button: TUDBtnType);
399begin
400with UpDown4 do
401if Position <= 10 then
402AsyncTimer.Interval := 1000 div Position
403else
404AsyncTimer.Interval := (20 - Position) * 10 + 1;
405end;
406
407
408procedure TForm1.FormResize(Sender: TObject);
409begin
410hudMap.Position.SetPoint(vp.Width div 2, vp.Height div 2, 0);
411resizeMap;
412end;
413
414//
415procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
416begin
417AsyncTimer.Enabled := false;
418buf[0].Free;
419buf[1].Free;
420end;
421
422end.
423