Added new pages and docs
[sdlgit/SDL-Site.git] / pages / SDLx-Controller.html-inc
CommitLineData
807ae0cd 1<div class="pod">
2<!-- INDEX START -->
3<h3 id="TOP">Index</h3>
4
5<ul><li><a href="#NAME">NAME</a></li>
39c8ca1e 6<li><a href="#CATEGORY">CATEGORY</a></li>
807ae0cd 7<li><a href="#SYNOPSIS">SYNOPSIS</a>
8<ul><li><a href="#DESCRIPTION">DESCRIPTION</a></li>
9</ul>
10</li>
11<li><a href="#METHODS">METHODS</a>
12<ul><li><a href="#new">new</a></li>
807ae0cd 13<li><a href="#run">run</a></li>
7a14b086 14<li><a href="#stop">stop</a></li>
15<li><a href="#pause">pause</a></li>
fcf60e89 16<li><a href="#paused">paused</a></li>
807ae0cd 17<li><a href="#add_event_handler">add_event_handler</a></li>
18<li><a href="#add_move_handler">add_move_handler</a></li>
19<li><a href="#add_show_handler">add_show_handler</a></li>
807ae0cd 20<li><a href="#remove_move_handler_index">remove_move_handler( $index )</a></li>
21<li><a href="#remove_event_handler_index">remove_event_handler( $index )</a></li>
22<li><a href="#remove_show_handler_index">remove_show_handler( $index )</a></li>
23<li><a href="#remove_all_move_handlers">remove_all_move_handlers</a></li>
24<li><a href="#remove_all_event_handlers">remove_all_event_handlers</a></li>
25<li><a href="#remove_all_show_handlers">remove_all_show_handlers</a></li>
26<li><a href="#remove_all_handlers">remove_all_handlers</a></li>
7a14b086 27<li><a href="#dt">dt</a></li>
28<li><a href="#min_t">min_t</a></li>
29<li><a href="#current_time">current_time</a></li>
807ae0cd 30</ul>
31</li>
32<li><a href="#AUTHORS">AUTHORS</a>
33<ul><li><a href="#ACKNOWLEGDEMENTS">ACKNOWLEGDEMENTS</a>
34</li>
35</ul>
36</li>
37</ul><hr />
38<!-- INDEX END -->
39
40<h1 id="NAME">NAME</h1><p><a href="#TOP" class="toplink">Top</a></p>
41<div id="NAME_CONTENT">
7a14b086 42<p>SDLx::Controller - Handles the loops for events, movement and rendering</p>
807ae0cd 43
44</div>
39c8ca1e 45<h1 id="CATEGORY">CATEGORY</h1><p><a href="#TOP" class="toplink">Top</a></p>
46<div id="CATEGORY_CONTENT">
47<p>Extension, Controller</p>
48
49</div>
807ae0cd 50<h1 id="SYNOPSIS">SYNOPSIS</h1><p><a href="#TOP" class="toplink">Top</a></p>
51<div id="SYNOPSIS_CONTENT">
4769fd12 52<pre> use SDLx::Controller;
807ae0cd 53
4769fd12 54 # create our controller object
55 my $app = SDLx::Controller-&gt;new;
807ae0cd 56
4769fd12 57 # we could also do:
58 my $app = SDLx::App-&gt;new;
59 # because App is also a controller
807ae0cd 60
4769fd12 61 # register some callbacks
62 $app-&gt;add_event_handler( \&amp;on_event );
63 $app-&gt;add_move_handler( \&amp;on_move );
64 $app-&gt;add_show_handler( \&amp;on_show );
807ae0cd 65
4769fd12 66 # run our game loop
67 $app-&gt;run;
807ae0cd 68
69</pre>
70
71</div>
72<h2 id="DESCRIPTION">DESCRIPTION</h2>
73<div id="DESCRIPTION_CONTENT">
4769fd12 74<p>The core of an SDL application/game is the main loop, where you handle events
807ae0cd 75and display your elements on the screen until something signals the end of
76the program. This usually goes in the form of:</p>
77<pre> while (1) {
78 ...
79 }
80
81</pre>
82<p>The problem most developers face, besides the repetitive work, is to ensure
83the screen update is independent of the frame rate. Otherwise, your game will
84run at different speeds on different machines and this is never good (old
85MS-DOS games, anyone?).</p>
86<p>One way to circumveint this is by capping the frame rate so it's the same no
87matter what, but this is not the right way to do it as it penalizes better
88hardware.</p>
89<p>This module provides an industry-proven standard for frame independent
7a14b086 90movement. It calls the movement handlers based on time (hi-res seconds) rather
807ae0cd 91than frame rate. You can add/remove handlers and control your main loop with
92ease.</p>
93
94</div>
95<h1 id="METHODS">METHODS</h1><p><a href="#TOP" class="toplink">Top</a></p>
96<div id="METHODS_CONTENT">
97
98</div>
99<h2 id="new">new</h2>
100<div id="new_CONTENT">
7a14b086 101<pre> SDLx::Controller-&gt;new(
102 dt =&gt; 0.5,
103 min_t =&gt; 0,
104 event =&gt; $event_object,
105 );
807ae0cd 106
7a14b086 107</pre>
108<p>The <code>dt</code> parameter specifies the length, in seconds, of a full movement step, and defaults to 0.1.
109The <code>dt</code> can be anything and the game can still look the same.
110It is only when you change the <code>dt</code> without changing all the things in the movement step that are being multiplied by the first move argument that it will make a difference.
111If you lower the <code>dt</code>, everything will move faster than it did with it set higher, and vice-versa.
112This is useful to add slo-mo and fast-forward features to the game, all you would have to do is change the <code>dt</code>.</p>
113<p><code>min_t</code> specifies the minimum time, in seconds, that has to accumulate before any move or show handlers are called, and defaults to 1 / 60.
4769fd12 114Having the <code>min_t</code> at 1 / 60 ensures that the controller can update the screen at a maximum of 60 times per second.
7a14b086 115A &quot;V-Sync&quot; such as this is necessary to prevent video &quot;tear&quot;, which occurs when the app is updating faster than the monitor can display.
4769fd12 116Setting it to 0, as seen above, will let the app run as fast as it possibly can.</p>
fcf60e89 117<p><code>delay</code> specifies a loop delay in millisecs to place on the controller loop. <strong>NOTE:</strong> Picking a good delay based on the needs can help reduce CPU load and pressure.</p>
4769fd12 118<p><code>event</code> is a SDL::Event object that events going to the event callbacks are polled in to. It defaults to <code>SDL::Event-&gt;new()</code>.</p>
7a14b086 119<p>All parameters are optional.</p>
807ae0cd 120<p>Returns the new object.</p>
121
122</div>
123<h2 id="run">run</h2>
124<div id="run_CONTENT">
125<p>After creating and setting up your handlers (see below), call this method to
7a14b086 126activate the main loop. The main loop will run until <code>stop</code> is called.</p>
807ae0cd 127<p>All hooked functions will be called during the main loop, in this order:</p>
128<dl>
129 <dt>1. Events</dt>
130 <dt>2. Movements</dt>
131 <dt>3. Displaying</dt>
132</dl>
7a14b086 133<p>Please refer to each handler below for information on received arguments.
134Note that the second argument every callback recieves is the <code>SDLx::Controller</code> object.</p>
135
136</div>
137<h2 id="stop">stop</h2>
138<div id="stop_CONTENT">
139<p>Returns from the <code>run</code> loop.</p>
140
141</div>
142<h2 id="pause">pause</h2>
143<div id="pause_CONTENT">
144<p>Attempts to pause the application with a call to <code>SDL::Events::wait_event</code>. See <a href="SDL-Events.html">SDL::Events</a>.</p>
145<p>Takes 1 argument which is a callback. The application waits for the next event with <code>wait_event</code>.
146When one is recieved, it is passed to the callback as the first argument, along with the <code>SDLx::Controller</code> object as the second argument.
147If the callback then returns a true value, <code>pause</code> will return.
4769fd12 148If the callback returns a false value, <code>pause</code> will repeat the process.</p>
7a14b086 149<p>This can be used to easily implement a pause when the app loses focus:</p>
4769fd12 150<pre> sub window {
151 my ($e, $app) = @_;
152 if($e-&gt;type == SDL_QUIT) {
153 $app-&gt;stop;
154 # quit handling is here so that the app
155 # can be stopped while paused
156 }
157 elsif($e-&gt;type == SDL_ACTIVEEVENT) {
7a14b086 158 if($e-&gt;active_state &amp; SDL_APPINPUTFOCUS) {
159 if($e-&gt;active_gain) {
160 return 1;
161 }
162 else {
4769fd12 163 $app-&gt;pause(\&amp;window);
7a14b086 164 # recursive, but only once since the window
165 # can't lose focus again without gaining is first
166 }
167 }
168 }
169 return 0;
170 }
171
172</pre>
173<p>Note: if you implement your own pause function, remember to update <code>current_time</code> to the current time when the application unpauses.
174This should be done with <code>Time::HiRes::time</code>.
175Otherwise, time will accumulate while the application is paused, and many movement steps will be called all at once when it unpauses.</p>
176<p>Note 2: a pause will be potentially dangerous to the <code>run</code> cycle (even if you implement your own) unless called by an <code>event</code> callback.</p>
807ae0cd 177
178</div>
fcf60e89 179<h2 id="paused">paused</h2>
180<div id="paused_CONTENT">
181<p>Returns 1 if the app is paused, undef otherwise.
182This is only useful when used within code that will be run by <code>pause</code>:</p>
183<pre> sub pause {
184 # press P to toggle pause
185
186 my ($e, $app) = @_;
187 if($e-&gt;type == SDL_QUIT) {
188 $app-&gt;stop;
189 # quit handling is here so that the app
190 # can be stopped while paused
191 }
192 elsif($e-&gt;type == SDL_KEYDOWN) {
193 if($e-&gt;key_sym == SDLK_P) {
194 # We're paused, so end pause
195 return 1 if $app-&gt;paused;
196
197 # We're not paused, so pause
198 $app-&gt;pause(\&amp;pause);
199 }
200 }
201 return 0;
202 }
203
204
205
206
207</pre>
208
209</div>
807ae0cd 210<h2 id="add_event_handler">add_event_handler</h2>
211<div id="add_event_handler_CONTENT">
212<p>Register a callback to handle events. You can add as many subs as you need.
213Whenever a SDL::Event occurs, all registered callbacks will be triggered in
214order. Returns the order queue number of the added callback.</p>
7a14b086 215<p>The first argument passed to registered callbacks is the <a href="SDL-Event.html">SDL::Event</a> object.
216The second is the <code>SDLx::Controller</code> object.</p>
217<pre> sub stop {
218 my ($event, $app) = @_;
219 if($event-&gt;type == SDL_QUIT) {
4769fd12 220 $app-&gt;stop;
7a14b086 221 }
222 }
4769fd12 223 $app-&gt;add_event_handler(\&amp;stop);
807ae0cd 224
7a14b086 225</pre>
807ae0cd 226
227</div>
228<h2 id="add_move_handler">add_move_handler</h2>
229<div id="add_move_handler_CONTENT">
230<p>Register a callback to update your objects. You can add as many subs as
231you need. Returns the order queue number of the added callback.</p>
7a14b086 232<p>All registered callbacks will be triggered in order for as many <code>dt</code> as have happened between calls,
233and once more for any remaining time less than <code>dt</code>.
234The first argument passed to the callbacks is the portion of the step, which will be 1 for a full step, and less than 1 for a partial step.
235Movement values should be multiplied by this value.
236The full steps correspond to the amount of <code>dt</code> passed between calls, and the partial step corresponds to the call with the remaining time less than <code>dt</code>.
4769fd12 237The argument can be 0 if no time has passed since the last cycle. If you need to protect against this, set a <code>min_t</code>, or put a <code>return unless $_[0]</code> at the start of every move handler.</p>
7a14b086 238<p>The second argument passed to the callbacks is the <code>SDLx::Controller</code> object.
239The third is the total amount of time passed since the call of <code>run</code>.</p>
240<p>You should use these handlers to update your in-game objects, check collisions, etc.
807ae0cd 241so you can check and/or update it as necessary.</p>
7a14b086 242<pre> sub move_ball {
243 my ($step, $app, $t) = @_;
244 $ball-&gt;move_x( $ball-&gt;x_vel * $step );
245 $ball-&gt;move_y( $ball-&gt;y_vel * $step );
246 }
807ae0cd 247
7a14b086 248</pre>
807ae0cd 249
250</div>
251<h2 id="add_show_handler">add_show_handler</h2>
252<div id="add_show_handler_CONTENT">
253<p>Register a callback to render objects. You can add as many subs as you need.
7a14b086 254Returns the order queue number of the added callback.
255All registered callbacks will be triggered in order, once per run of the <code>run</code> loop.</p>
4769fd12 256<p>The first argument passed is the time, in seconds, since the previous call.
7a14b086 257The second is the <code>SDLx::Controller</code> object.</p>
258<pre> sub show_ball {
259 my ($delta, $app) = @_;
260 $app-&gt;draw_rect(
261 [ $ball-&gt;x, $ball-&gt;y, $ball-&gt;size, $ball-&gt;size ],
262 $ball-&gt;colour
263 );
264 }
807ae0cd 265
7a14b086 266</pre>
807ae0cd 267
268</div>
269<h2 id="remove_move_handler_index">remove_move_handler( $index )</h2>
270<div id="remove_move_handler_index_CONTENT">
271
272</div>
273<h2 id="remove_event_handler_index">remove_event_handler( $index )</h2>
274<div id="remove_event_handler_index_CONTENT">
275
276</div>
277<h2 id="remove_show_handler_index">remove_show_handler( $index )</h2>
278<div id="remove_show_handler_index_CONTENT">
279<p>Removes the handler with the given index from the respective calling queue.</p>
505f308d 280<p>You can also pass a coderef.
281The first coderef in the handler list that this matches will be removed.</p>
807ae0cd 282<p>Returns the removed handler.</p>
283
284</div>
285<h2 id="remove_all_move_handlers">remove_all_move_handlers</h2>
286<div id="remove_all_move_handlers_CONTENT">
287
288</div>
289<h2 id="remove_all_event_handlers">remove_all_event_handlers</h2>
290<div id="remove_all_event_handlers_CONTENT">
291
292</div>
293<h2 id="remove_all_show_handlers">remove_all_show_handlers</h2>
294<div id="remove_all_show_handlers_CONTENT">
295<p>Removes all handlers from the respective calling queue.</p>
296
297</div>
298<h2 id="remove_all_handlers">remove_all_handlers</h2>
299<div id="remove_all_handlers_CONTENT">
300<p>Quick access to removing all handlers at once.</p>
301
807ae0cd 302</div>
7a14b086 303<h2 id="dt">dt</h2>
304<div id="dt_CONTENT">
305
306</div>
307<h2 id="min_t">min_t</h2>
308<div id="min_t_CONTENT">
309
310</div>
311<h2 id="current_time">current_time</h2>
312<div id="current_time_CONTENT">
313<p>If an argument is passed, modifies the corresponding value to the argument.
314<code>dt</code> and <code>min_t</code> will keep their old value until the beginning of the next <code>run</code> cycle.</p>
315<p>Returns the corresponding value.</p>
316
317</div>
807ae0cd 318<h1 id="AUTHORS">AUTHORS</h1><p><a href="#TOP" class="toplink">Top</a></p>
319<div id="AUTHORS_CONTENT">
1dbe1697 320<p>See <a href="/SDL.html#AUTHORS">/SDL.html#AUTHORS</a>.</p>
807ae0cd 321
322</div>
323<h2 id="ACKNOWLEGDEMENTS">ACKNOWLEGDEMENTS</h2>
324<div id="ACKNOWLEGDEMENTS_CONTENT">
325<p>The idea and base for this module comes from Lazy Foo's <a href="http://www.lazyfoo.net/SDL_tutorials/lesson32/index.php">Frame Independent Movement</a> tutorial,
326and Glenn Fiedler's <a href="http://gafferongames.com/game-physics/fix-your-timestep/">Fix Your Timestep</a> article on timing.</p>
327
328
329
330
331
332
333
334
335
336
337
338</div>
339</div>