source: tags/1.4.0/Forms/FormMain.pas

Last change on this file was 91, checked in by chronos, 3 months ago
  • Added: Flatpak build files.
  • Added: Game menu restart action to start a new game without showing options dialog.
  • Fixed: Fullscreen error after another window was opened.
File size: 6.9 KB
Line 
1unit FormMain;
2
3interface
4
5uses
6 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Menus, Math,
7 ActnList, ExtCtrls, StdCtrls, Game, PersistentForm, ApplicationInfo,
8 LCLType, Syncobjs, DateUtils, FormEx;
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 MenuItemFullScreen: TMenuItem;
31 MenuItemMovesHistory: TMenuItem;
32 MenuItemTools: TMenuItem;
33 MenuItemNew: TMenuItem;
34 MenuItemExit: TMenuItem;
35 MenuItemHelp: TMenuItem;
36 MenuItemAbout: TMenuItem;
37 MenuItemGame: TMenuItem;
38 TimerDraw: TTimer;
39 procedure FormActivate(Sender: TObject);
40 procedure FormCreate(Sender: TObject);
41 procedure FormDestroy(Sender: TObject);
42 procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
43 procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
44 Shift: TShiftState; X, Y: Integer);
45 procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
46 procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
47 Shift: TShiftState; X, Y: Integer);
48 procedure FormPaint(Sender: TObject);
49 procedure FormShow(Sender: TObject);
50 procedure MenuItemFullScreenClick(Sender: TObject);
51 procedure TimerDrawTimer(Sender: TObject);
52 procedure EraseBackground(DC: HDC); override;
53 private
54 DrawDuration: TDateTime;
55 MouseStart: TPoint;
56 MouseDown: Boolean;
57 RedrawPending: Boolean;
58 MoveBuffer: array of TMoveDirection;
59 MoveBufferLock: TCriticalSection;
60 FullScreen: Boolean;
61 procedure AddToMoveBuffer(Direction: TMoveDirection);
62 procedure ProcessMoveBuffer;
63 procedure ToggleFullscreen;
64 public
65 MoveThread: TMoveThread;
66 procedure Redraw;
67 procedure UpdateInterface;
68 end;
69
70var
71 FormMain: TFormMain;
72
73
74implementation
75
76{$R *.lfm}
77
78uses
79 Core;
80
81{ TMoveThread }
82
83procedure TMoveThread.Execute;
84begin
85 while not Terminated do begin
86 FormMain.ProcessMoveBuffer;
87 Sleep(10);
88 end;
89end;
90
91{ TFormMain }
92
93procedure TFormMain.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
94const
95 KeyLeft = 37;
96 KeyUp = 38;
97 KeyRight = 39;
98 KeyDown = 40;
99 KeyNumPadLeft = 100;
100 KeyNumPadUp = 104;
101 KeyNumPadRight = 102;
102 KeyNumPadDown = 98;
103begin
104 if Core.Core.Game.Running then begin
105 case Key of
106 KeyLeft, KeyNumPadLeft: AddToMoveBuffer(drLeft);
107 KeyUp, KeyNumPadUp: AddToMoveBuffer(drUp);
108 KeyRight, KeyNumPadRight: AddToMoveBuffer(drRight);
109 KeyDown, KeyNumPadDown: AddToMoveBuffer(drDown);
110 end;
111 //ProcessMoveBuffer;
112 end;
113end;
114
115procedure TFormMain.FormMouseDown(Sender: TObject; Button: TMouseButton;
116 Shift: TShiftState; X, Y: Integer);
117begin
118 MouseStart := Point(X, Y);
119 MouseDown := True;
120end;
121
122function AngleOfLine(const P1, P2: TPoint): Double;
123begin
124 if P2.X = P1.X then
125 if P2.Y > P1.Y then
126 Result := 90
127 else
128 Result := 270
129 else
130 Result := RadToDeg(ArcTan2(P2.Y - P1.Y, P2.X - P1.X));
131 if Result < 0 then
132 Result := Result + 360;
133end;
134
135procedure TFormMain.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
136 Y: Integer);
137var
138 D: Real;
139 Angle: Real;
140begin
141 if MouseDown then begin;
142 D := MouseStart.Distance(Point(X, Y));
143 if D > ScaleX(100, 96) then begin
144 MouseDown := False;
145 Angle := AngleOfLine(MouseStart, Point(X, Y));
146 if (Angle > 315) or (Angle <= 45) then AddToMoveBuffer(drRight)
147 else if (Angle > 45) and (Angle <= 135) then AddToMoveBuffer(drDown)
148 else if (Angle > 135) and (Angle <= 225) then AddToMoveBuffer(drLeft)
149 else if (Angle > 225) and (Angle <= 315) then AddToMoveBuffer(drUp);
150 //ProcessMoveBuffer;
151 end;
152 end;
153end;
154
155procedure TFormMain.FormMouseUp(Sender: TObject; Button: TMouseButton;
156 Shift: TShiftState; X, Y: Integer);
157begin
158 MouseDown := False;
159end;
160
161procedure TFormMain.FormPaint(Sender: TObject);
162var
163 TimeStart: TDateTime;
164begin
165 {$IFDEF DEBUG}
166 TimeStart := Now;
167 {$ENDIF}
168 Core.Core.Game.Render(Canvas, Point(Width, Height - MainMenu1.Height));
169 {$IFDEF DEBUG}
170 DrawDuration := Now - TimeStart;
171 {$ENDIF}
172end;
173
174procedure TFormMain.FormActivate(Sender: TObject);
175begin
176 FullScreen := Core.Core.PersistentForm1.FormFullScreen;
177end;
178
179procedure TFormMain.FormCreate(Sender: TObject);
180begin
181 MoveBufferLock := TCriticalSection.Create;
182 MoveThread := TMoveThread.Create(True);
183 MoveThread.FormMain := Self;
184 MoveThread.FreeOnTerminate := False;
185 MoveThread.Start;
186 ControlStyle := ControlStyle + [csOpaque];
187end;
188
189procedure TFormMain.FormDestroy(Sender: TObject);
190begin
191 FreeAndNil(MoveThread);
192 FreeAndNil(MoveBufferLock);
193end;
194
195procedure TFormMain.FormShow(Sender: TObject);
196begin
197 UpdateInterface;
198 if Core.Core.Game.Board.GetEmptyTilesCount > Core.Core.Game.Board.Size.X *
199 Core.Core.Game.Board.Size.Y - InitialTileCount then
200 Core.Core.Game.New;
201end;
202
203procedure TFormMain.MenuItemFullScreenClick(Sender: TObject);
204begin
205 ToggleFullscreen;
206end;
207
208procedure TFormMain.TimerDrawTimer(Sender: TObject);
209begin
210 if RedrawPending then begin
211 RedrawPending := False;
212 Repaint;
213{$IFDEF DEBUG}
214 //Caption := FloatToStr(Round(DrawDuration / OneMillisecond));
215{$ENDIF}
216 end;
217end;
218
219procedure TFormMain.EraseBackground(DC: HDC);
220begin
221 // Do nothing
222end;
223
224procedure TFormMain.AddToMoveBuffer(Direction: TMoveDirection);
225begin
226 MoveBufferLock.Acquire;
227 try
228 SetLength(MoveBuffer, Length(MoveBuffer) + 1);
229 MoveBuffer[Length(MoveBuffer) - 1] := Direction;
230 finally
231 MoveBufferLock.Release;
232 end;
233end;
234
235procedure TFormMain.ProcessMoveBuffer;
236begin
237 if not Core.Core.Game.Moving then begin
238 MoveBufferLock.Acquire;
239 while Length(MoveBuffer) > 0 do begin
240 MoveBufferLock.Release;
241 Core.Core.Game.MoveAllAndUpdate(MoveBuffer[0], Core.Core.Game.AnimationDuration > 0);
242 MoveBufferLock.Acquire;
243 if Length(MoveBuffer) > 1 then
244 Move(MoveBuffer[1], MoveBuffer[0], (Length(MoveBuffer) - 1) * SizeOf(TMoveDirection));
245 if Length(MoveBuffer) > 0 then
246 SetLength(MoveBuffer, Length(MoveBuffer) - 1);
247 end;
248 MoveBufferLock.Release;
249 end;
250end;
251
252procedure TFormMain.ToggleFullscreen;
253begin
254 FullScreen := not FullScreen;
255 Core.Core.PersistentForm1.Save(Self);
256 Core.Core.PersistentForm1.SetFullScreen(FormMain.FullScreen);
257 UpdateInterface;
258end;
259
260procedure TFormMain.Redraw;
261begin
262 RedrawPending := True;
263end;
264
265procedure TFormMain.UpdateInterface;
266var
267 I: Integer;
268 ToolsVisible: Boolean;
269begin
270 MenuItemFullScreen.Checked := FullScreen;
271 MenuItemMovesHistory.Visible := Core.Core.Game.RecordHistory;
272 ToolsVisible := False;
273 for I := 0 to MenuItemTools.Count - 1 do
274 if MenuItemTools.Items[I].Visible then begin
275 ToolsVisible := True;
276 Break;
277 end;
278 MenuItemTools.Visible := ToolsVisible;
279end;
280
281end.
282
Note: See TracBrowser for help on using the repository browser.