source: trunk/Forms/FormMain.pas

Last change on this file was 125, checked in by chronos, 7 months ago
  • Fixed: Wrong game board height on some platforms.
File size: 8.2 KB
Line 
1unit FormMain;
2
3interface
4
5uses
6 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Menus, Math,
7 ActnList, ExtCtrls, Game, PersistentForm, LCLType, Syncobjs, DateUtils, FormEx,
8 Board;
9
10type
11 TFormMain = class;
12
13 { TMoveThread }
14
15 TMoveThread = class(TThread)
16 FormMain: TFormMain;
17 procedure Execute; override;
18 end;
19
20 { TFormMain }
21
22 TFormMain = class(TFormEx)
23 MainMenu1: TMainMenu;
24 MenuItem1: TMenuItem;
25 MenuItem2: TMenuItem;
26 MenuItem3: TMenuItem;
27 MenuItem4: TMenuItem;
28 MenuItem5: TMenuItem;
29 MenuItem6: TMenuItem;
30 MenuItem7: TMenuItem;
31 MenuItemColorPalette: TMenuItem;
32 MenuItemTileSkin: TMenuItem;
33 MenuItemFullScreen: TMenuItem;
34 MenuItemMovesHistory: TMenuItem;
35 MenuItemTools: TMenuItem;
36 MenuItemNew: TMenuItem;
37 MenuItemExit: TMenuItem;
38 MenuItemHelp: TMenuItem;
39 MenuItemAbout: TMenuItem;
40 MenuItemGame: TMenuItem;
41 TimerDraw: TTimer;
42 procedure FormActivate(Sender: TObject);
43 procedure FormCreate(Sender: TObject);
44 procedure FormDestroy(Sender: TObject);
45 procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
46 procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
47 Shift: TShiftState; X, Y: Integer);
48 procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
49 procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
50 Shift: TShiftState; X, Y: Integer);
51 procedure FormPaint(Sender: TObject);
52 procedure FormShow(Sender: TObject);
53 procedure MenuItemFullScreenClick(Sender: TObject);
54 procedure TimerDrawTimer(Sender: TObject);
55 procedure EraseBackground(DC: HDC); override;
56 private
57 DrawDuration: TDateTime;
58 MouseStart: TPoint;
59 MouseDown: Boolean;
60 RedrawPending: Boolean;
61 MoveBuffer: array of TMoveDirection;
62 MoveBufferLock: TCriticalSection;
63 procedure MenuItemTileSkinClick(Sender: TObject);
64 procedure MenuItemColorPaletteClick(Sender: TObject);
65 procedure AddToMoveBuffer(Direction: TMoveDirection);
66 procedure ProcessMoveBuffer;
67 procedure ToggleFullscreen;
68 public
69 MoveThread: TMoveThread;
70 procedure Redraw;
71 procedure UpdateInterface;
72 end;
73
74var
75 FormMain: TFormMain;
76
77
78implementation
79
80{$R *.lfm}
81
82uses
83 Core;
84
85{ TMoveThread }
86
87procedure TMoveThread.Execute;
88begin
89 while not Terminated do begin
90 FormMain.ProcessMoveBuffer;
91 Sleep(10);
92 end;
93end;
94
95{ TFormMain }
96
97procedure TFormMain.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
98const
99 KeyLeft = 37;
100 KeyUp = 38;
101 KeyRight = 39;
102 KeyDown = 40;
103 KeyNumPadLeft = 100;
104 KeyNumPadUp = 104;
105 KeyNumPadRight = 102;
106 KeyNumPadDown = 98;
107begin
108 if Core.Core.Game.Running then begin
109 case Key of
110 KeyLeft, KeyNumPadLeft: AddToMoveBuffer(drLeft);
111 KeyUp, KeyNumPadUp: AddToMoveBuffer(drUp);
112 KeyRight, KeyNumPadRight: AddToMoveBuffer(drRight);
113 KeyDown, KeyNumPadDown: AddToMoveBuffer(drDown);
114 end;
115 //ProcessMoveBuffer;
116 end;
117end;
118
119procedure TFormMain.FormMouseDown(Sender: TObject; Button: TMouseButton;
120 Shift: TShiftState; X, Y: Integer);
121begin
122 MouseStart := Point(X, Y);
123 MouseDown := True;
124end;
125
126function AngleOfLine(const P1, P2: TPoint): Double;
127begin
128 if P2.X = P1.X then
129 if P2.Y > P1.Y then
130 Result := 90
131 else
132 Result := 270
133 else
134 Result := RadToDeg(ArcTan2(P2.Y - P1.Y, P2.X - P1.X));
135 if Result < 0 then
136 Result := Result + 360;
137end;
138
139procedure TFormMain.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
140 Y: Integer);
141var
142 D: Real;
143 Angle: Real;
144const
145 SwipeMinDistance = 50;
146begin
147 if MouseDown then begin;
148 D := MouseStart.Distance(Point(X, Y));
149 if D > ScaleX(SwipeMinDistance, 96) then begin
150 MouseDown := False;
151 Angle := AngleOfLine(MouseStart, Point(X, Y));
152 if (Angle > 315) or (Angle <= 45) then AddToMoveBuffer(drRight)
153 else if (Angle > 45) and (Angle <= 135) then AddToMoveBuffer(drDown)
154 else if (Angle > 135) and (Angle <= 225) then AddToMoveBuffer(drLeft)
155 else if (Angle > 225) and (Angle <= 315) then AddToMoveBuffer(drUp);
156 //ProcessMoveBuffer;
157 end;
158 end;
159end;
160
161procedure TFormMain.FormMouseUp(Sender: TObject; Button: TMouseButton;
162 Shift: TShiftState; X, Y: Integer);
163begin
164 MouseDown := False;
165end;
166
167procedure TFormMain.FormPaint(Sender: TObject);
168var
169 TimeStart: TDateTime;
170begin
171 {$IFDEF DEBUG}
172 TimeStart := Now;
173 {$ENDIF}
174 Core.Core.Game.Render(Canvas, Point(ClientWidth, ClientHeight));
175 {$IFDEF DEBUG}
176 DrawDuration := Now - TimeStart;
177 {$ENDIF}
178end;
179
180procedure TFormMain.FormActivate(Sender: TObject);
181begin
182 FullScreen := Core.Core.PersistentForm1.FormFullScreen;
183end;
184
185procedure TFormMain.FormCreate(Sender: TObject);
186var
187 TileSkin: TTileSkin;
188 ColorPalette: TColorPalette;
189 MenuItem: TMenuItem;
190begin
191 MoveBufferLock := TCriticalSection.Create;
192 MoveThread := TMoveThread.Create(True);
193 MoveThread.FormMain := Self;
194 MoveThread.FreeOnTerminate := False;
195 MoveThread.Start;
196 ControlStyle := ControlStyle + [csOpaque];
197
198 for TileSkin := Low(SkinText) to High(SkinText) do begin
199 MenuItem := TMenuItem.Create(MenuItemTileSkin);
200 MenuItem.RadioItem := True;
201 MenuItem.AutoCheck := True;
202 MenuItem.Tag := Integer(TileSkin);
203 MenuItem.Caption := SkinText[TileSkin];
204 MenuItem.OnClick := MenuItemTileSkinClick;
205 MenuItemTileSkin.Add(MenuItem);
206 end;
207
208 for ColorPalette := Low(ColorPaletteText) to High(ColorPaletteText) do begin
209 MenuItem := TMenuItem.Create(MenuItemColorPalette);
210 MenuItem.RadioItem := True;
211 MenuItem.AutoCheck := True;
212 MenuItem.Tag := Integer(ColorPalette);
213 MenuItem.Caption := ColorPaletteText[ColorPalette];
214 MenuItem.OnClick := MenuItemColorPaletteClick;
215 MenuItemColorPalette.Add(MenuItem);
216 end;
217end;
218
219procedure TFormMain.FormDestroy(Sender: TObject);
220begin
221 FreeAndNil(MoveThread);
222 FreeAndNil(MoveBufferLock);
223end;
224
225procedure TFormMain.FormShow(Sender: TObject);
226begin
227 UpdateInterface;
228 if Core.Core.Game.Board.GetEmptyTilesCount > Core.Core.Game.Board.Size.X *
229 Core.Core.Game.Board.Size.Y - InitialTileCount then
230 Core.Core.Game.New;
231end;
232
233procedure TFormMain.MenuItemFullScreenClick(Sender: TObject);
234begin
235 ToggleFullscreen;
236end;
237
238procedure TFormMain.TimerDrawTimer(Sender: TObject);
239begin
240 if RedrawPending then begin
241 RedrawPending := False;
242 Repaint;
243{$IFDEF DEBUG}
244 //Caption := FloatToStr(Round(DrawDuration / OneMillisecond));
245{$ENDIF}
246 end;
247end;
248
249procedure TFormMain.EraseBackground(DC: HDC);
250begin
251 // Do nothing
252end;
253
254procedure TFormMain.MenuItemTileSkinClick(Sender: TObject);
255begin
256 Core.Core.Game.Skin := TTileSkin(TMenuItem(Sender).Tag);
257end;
258
259procedure TFormMain.MenuItemColorPaletteClick(Sender: TObject);
260begin
261 Core.Core.Game.ColorPalette := TColorPalette(TMenuItem(Sender).Tag);
262end;
263
264procedure TFormMain.AddToMoveBuffer(Direction: TMoveDirection);
265begin
266 MoveBufferLock.Acquire;
267 try
268 SetLength(MoveBuffer, Length(MoveBuffer) + 1);
269 MoveBuffer[Length(MoveBuffer) - 1] := Direction;
270 finally
271 MoveBufferLock.Release;
272 end;
273end;
274
275procedure TFormMain.ProcessMoveBuffer;
276begin
277 if not Core.Core.Game.Moving then begin
278 MoveBufferLock.Acquire;
279 while Length(MoveBuffer) > 0 do begin
280 MoveBufferLock.Release;
281 Core.Core.Game.MoveAllAndUpdate(MoveBuffer[0], Core.Core.Game.AnimationDuration > 0);
282 MoveBufferLock.Acquire;
283 if Length(MoveBuffer) > 1 then
284 Move(MoveBuffer[1], MoveBuffer[0], (Length(MoveBuffer) - 1) * SizeOf(TMoveDirection));
285 if Length(MoveBuffer) > 0 then
286 SetLength(MoveBuffer, Length(MoveBuffer) - 1);
287 end;
288 MoveBufferLock.Release;
289 end;
290end;
291
292procedure TFormMain.ToggleFullscreen;
293begin
294 FullScreen := not FullScreen;
295 TFormEx.PersistentForm.Save(Self);
296 TFormEx.PersistentForm.SetFullScreen(FormMain.FullScreen);
297 UpdateInterface;
298end;
299
300procedure TFormMain.Redraw;
301begin
302 RedrawPending := True;
303end;
304
305procedure TFormMain.UpdateInterface;
306var
307 I: Integer;
308 ToolsVisible: Boolean;
309begin
310 MenuItemFullScreen.Checked := FullScreen;
311 ToolsVisible := False;
312 for I := 0 to MenuItemTools.Count - 1 do
313 if MenuItemTools.Items[I].Visible then begin
314 ToolsVisible := True;
315 Break;
316 end;
317 MenuItemTools.Visible := ToolsVisible;
318 MenuItemTileSkin.Items[Integer(Core.Core.Game.Skin)].Checked := True;
319 MenuItemColorPalette.Items[Integer(Core.Core.Game.ColorPalette)].Checked := True;
320end;
321
322end.
323
Note: See TracBrowser for help on using the repository browser.