Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4 | daniel-mar | 1 | { |
2 | SXMedia Components - Beta 1 |
||
3 | -------------------------------- |
||
4 | Copyright 1999 Dean Ellis |
||
5 | http://www.sillex.freeserve.co.uk |
||
6 | |||
7 | This unit is part of the SXMedia Component Set. This code is |
||
8 | supplied as is with no guarantees and must be used at your own |
||
9 | risk. |
||
10 | |||
11 | No modifications to this code must be made without the express |
||
12 | permission of the author. Please report any problems to |
||
13 | support@sillex.freeserve.co.uk |
||
14 | |||
15 | You may use these components to create any freeware/shareware |
||
16 | applications that you wish. If the components are to be used in |
||
17 | a commercail product then credit for developement of these components |
||
18 | should be given. |
||
19 | |||
20 | Credits : |
||
21 | |||
22 | Developer : Dean Ellis |
||
23 | Testers : Dominique Louis |
||
24 | Ivan Blecic |
||
25 | } |
||
26 | unit SXEngine; |
||
27 | |||
28 | interface |
||
29 | |||
30 | uses |
||
31 | Windows, Messages, SysUtils, Classes, MMSystem; |
||
32 | |||
33 | type |
||
34 | TFramesPerSecond = 1..100; |
||
35 | TFreeCyclesEvent = procedure (Sender: TObject; Count:Integer) of object; |
||
36 | |||
37 | TSXEngine = class(TComponent) |
||
38 | private |
||
39 | { Private Data Members } |
||
40 | FFramesPerSecond:TFramesPerSecond; |
||
41 | FEnabled:Boolean; |
||
42 | FThreadPriority:TThreadPriority; |
||
43 | FFPS:Integer; |
||
44 | FActivate:TNotifyEvent; |
||
45 | FDeActivate:TNotifyEvent; |
||
46 | FRender:TNotifyEvent; |
||
47 | FFreeCycles:TFreeCyclesEvent; |
||
48 | protected |
||
49 | { Property Accessors } |
||
50 | procedure SetTargetFPS(Value:TFramesPerSecond); |
||
51 | function GetTargetFPS:TFramesPerSecond; |
||
52 | procedure SetEnabled(Value:Boolean); |
||
53 | procedure SetThreadPriority(Value:TThreadPriority); |
||
54 | { Notification methods } |
||
55 | procedure DoRender; |
||
56 | procedure DoActivate; |
||
57 | procedure DoDeActivate; |
||
58 | procedure DoFreeCycles(Count: Integer); |
||
59 | { Class Helper methods } |
||
60 | public |
||
61 | { Public methods } |
||
62 | constructor Create(AOwner:TComponent);override; |
||
63 | destructor Destroy; override; |
||
64 | {Public Properties} |
||
65 | property FramesPerSecond : Integer read FFPS write FFPS; |
||
66 | published |
||
67 | { Published properties } |
||
68 | property TargetFPS : TFramesPerSecond read GetTargetFPS write SetTargetFPS default 30; |
||
69 | property Enabled : Boolean read FEnabled write SetEnabled default False; |
||
70 | property ThreadPriority : TThreadPriority read FThreadPriority write SetThreadPriority; |
||
71 | { Published Events} |
||
72 | property OnActivate : TNotifyEvent read FActivate write FActivate; |
||
73 | property OnDeActivate : TNotifyEvent read FDeActivate write FDeActivate; |
||
74 | property OnRender : TNotifyEvent read FRender write FRender; |
||
75 | property OnFreeCycles : TFreeCyclesEvent read FFreeCycles write FFreeCycles; |
||
76 | end; |
||
77 | |||
78 | implementation |
||
79 | {$J+} |
||
80 | const |
||
81 | FPS : Single = 33.3; |
||
82 | SECOND : Single = 1000.0; |
||
83 | |||
84 | type |
||
85 | TGameThread = class(TThread) |
||
86 | private |
||
87 | { Private declarations } |
||
88 | FThreadCallback:TThreadMethod; |
||
89 | protected |
||
90 | procedure Execute; override; |
||
91 | property ThreadCallback: TThreadMethod read FThreadCallback write FThreadCallback; |
||
92 | public |
||
93 | constructor Create(CreateSupsended:Boolean;Callback:TThreadMethod); |
||
94 | end; |
||
95 | |||
96 | var Thread:TGameThread; |
||
97 | { Important: Methods and properties of objects in VCL can only be used in a |
||
98 | method called using Synchronize, for example, |
||
99 | |||
100 | Synchronize(UpdateCaption); |
||
101 | |||
102 | and UpdateCaption could look like, |
||
103 | |||
104 | procedure TGameThread.UpdateCaption; |
||
105 | begin |
||
106 | Form1.Caption := 'Updated in a thread'; |
||
107 | end; } |
||
108 | |||
109 | { TGameThread } |
||
110 | |||
111 | procedure TGameThread.Execute; |
||
112 | begin |
||
113 | { Place thread code here } |
||
114 | while not Terminated do |
||
115 | begin |
||
116 | try |
||
117 | if Assigned(ThreadCallback) then Synchronize(ThreadCallback); |
||
118 | except |
||
119 | Terminate; |
||
120 | end; |
||
121 | end; |
||
122 | end; |
||
123 | constructor TGameThread.Create(CreateSupsended:Boolean;Callback:TThreadMethod); |
||
124 | begin |
||
125 | inherited Create(CreateSupsended); |
||
126 | ThreadCallback := Callback; |
||
127 | end; |
||
128 | |||
129 | { TSXEngine } |
||
130 | constructor TSXEngine.Create(AOwner:TComponent); |
||
131 | begin |
||
132 | inherited Create(AOwner); |
||
133 | if not (csDesigning in ComponentState) then |
||
134 | begin |
||
135 | if not Assigned(Thread) then |
||
136 | begin |
||
137 | Thread := TGameThread.Create(True,DoRender); |
||
138 | Thread.FreeOnTerminate := False; |
||
139 | Thread.Priority := ThreadPriority; |
||
140 | Thread.Suspended := not Enabled; |
||
141 | end; |
||
142 | DoActivate; |
||
143 | end; |
||
144 | Enabled := False; |
||
145 | TargetFPS := 30; |
||
146 | end; |
||
147 | destructor TSXEngine.Destroy; |
||
148 | begin |
||
149 | if not (csDesigning in ComponentState) then |
||
150 | begin |
||
151 | if Assigned(Thread) then |
||
152 | begin |
||
153 | Thread.Terminate; |
||
154 | Thread.Free; |
||
155 | end; |
||
156 | DoDeActivate; |
||
157 | end; |
||
158 | inherited Destroy; |
||
159 | end; |
||
160 | procedure TSXEngine.SetTargetFPS(Value:TFramesPerSecond); |
||
161 | begin |
||
162 | FFramesPerSecond := Value; |
||
163 | FPS := SECOND / Value; |
||
164 | end; |
||
165 | function TSXEngine.GetTargetFPS:TFramesPerSecond; |
||
166 | begin |
||
167 | Result := FFramesPerSecond; |
||
168 | end; |
||
169 | procedure TSXEngine.SetEnabled(Value:Boolean); |
||
170 | begin |
||
171 | FEnabled := Value; |
||
172 | if Thread <> nil then |
||
173 | Thread.Suspended := not Value; |
||
174 | end; |
||
175 | procedure TSXEngine.SetThreadPriority(Value:TThreadPriority); |
||
176 | begin |
||
177 | FThreadPriority := Value; |
||
178 | if Thread <> nil then |
||
179 | Thread.Priority := Value; |
||
180 | end; |
||
181 | procedure TSXEngine.DoRender; |
||
182 | const Start:DWord = 0; |
||
183 | OldStart:DWord = 0; |
||
184 | Count:Integer =0; |
||
185 | var FreeCycleCount:integer; |
||
186 | begin |
||
187 | try |
||
188 | Start := TimeGetTime; |
||
189 | FreeCycleCount := 0; |
||
190 | if Assigned(FRender) then FRender(Self); |
||
191 | if (Start - OldStart) < SECOND then |
||
192 | Inc(Count) |
||
193 | else |
||
194 | begin |
||
195 | FramesPerSecond := Count; |
||
196 | OldStart := Start; |
||
197 | Count := 0; |
||
198 | end; |
||
199 | repeat |
||
200 | DoFreeCycles(FreeCycleCount); |
||
201 | inc(FreeCycleCount); |
||
202 | until (TimeGetTime - Start) >= FPS; |
||
203 | except |
||
204 | Enabled := False; |
||
205 | Thread.Terminate; |
||
206 | end; |
||
207 | end; |
||
208 | procedure TSXEngine.DoActivate; |
||
209 | begin |
||
210 | if Assigned(FActivate) then FActivate(Self); |
||
211 | end; |
||
212 | procedure TSXEngine.DoDeActivate; |
||
213 | begin |
||
214 | if Assigned(FDeActivate) then FDeActivate(Self); |
||
215 | end; |
||
216 | procedure TSXEngine.DoFreeCycles(Count: Integer); |
||
217 | begin |
||
218 | if Assigned(FFreeCycles) then FFreeCycles(Self,Count); |
||
219 | end; |
||
220 | |||
221 | end. |