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