Commit | Line | Data |
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->new; |
807ae0cd |
55 | |
4769fd12 |
56 | # we could also do: |
57 | my $app = SDLx::App->new; |
58 | # because App is also a controller |
807ae0cd |
59 | |
4769fd12 |
60 | # register some callbacks |
61 | $app->add_event_handler( \&on_event ); |
62 | $app->add_move_handler( \&on_move ); |
63 | $app->add_show_handler( \&on_show ); |
807ae0cd |
64 | |
4769fd12 |
65 | # run our game loop |
66 | $app->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 |
74 | and display your elements on the screen until something signals the end of |
75 | the 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 |
82 | the screen update is independent of the frame rate. Otherwise, your game will |
83 | run at different speeds on different machines and this is never good (old |
84 | MS-DOS games, anyone?).</p> |
85 | <p>One way to circumveint this is by capping the frame rate so it's the same no |
86 | matter what, but this is not the right way to do it as it penalizes better |
87 | hardware.</p> |
88 | <p>This module provides an industry-proven standard for frame independent |
7a14b086 |
89 | movement. It calls the movement handlers based on time (hi-res seconds) rather |
807ae0cd |
90 | than frame rate. You can add/remove handlers and control your main loop with |
91 | ease.</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->new( |
101 | dt => 0.5, |
102 | min_t => 0, |
103 | event => $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. |
108 | The <code>dt</code> can be anything and the game can still look the same. |
109 | It 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. |
110 | If you lower the <code>dt</code>, everything will move faster than it did with it set higher, and vice-versa. |
111 | This 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 |
113 | Having 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 |
114 | A "V-Sync" such as this is necessary to prevent video "tear", which occurs when the app is updating faster than the monitor can display. |
4769fd12 |
115 | Setting 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->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 |
124 | activate 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. |
132 | Note 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>. |
144 | When 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. |
145 | If the callback then returns a true value, <code>pause</code> will return. |
4769fd12 |
146 | If 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->type == SDL_QUIT) { |
151 | $app->stop; |
152 | # quit handling is here so that the app |
153 | # can be stopped while paused |
154 | } |
155 | elsif($e->type == SDL_ACTIVEEVENT) { |
7a14b086 |
156 | if($e->active_state & SDL_APPINPUTFOCUS) { |
157 | if($e->active_gain) { |
158 | return 1; |
159 | } |
160 | else { |
4769fd12 |
161 | $app->pause(\&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. |
172 | This should be done with <code>Time::HiRes::time</code>. |
173 | Otherwise, 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. |
180 | Whenever a SDL::Event occurs, all registered callbacks will be triggered in |
181 | order. 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. |
183 | The second is the <code>SDLx::Controller</code> object.</p> |
184 | <pre> sub stop { |
185 | my ($event, $app) = @_; |
186 | if($event->type == SDL_QUIT) { |
4769fd12 |
187 | $app->stop; |
7a14b086 |
188 | } |
189 | } |
4769fd12 |
190 | $app->add_event_handler(\&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 |
198 | you 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, |
200 | and once more for any remaining time less than <code>dt</code>. |
201 | The 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. |
202 | Movement values should be multiplied by this value. |
203 | The 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 |
204 | The 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. |
206 | The 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 |
208 | so you can check and/or update it as necessary.</p> |
7a14b086 |
209 | <pre> sub move_ball { |
210 | my ($step, $app, $t) = @_; |
211 | $ball->move_x( $ball->x_vel * $step ); |
212 | $ball->move_y( $ball->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 |
221 | Returns the order queue number of the added callback. |
222 | All 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 |
224 | The second is the <code>SDLx::Controller</code> object.</p> |
225 | <pre> sub show_ball { |
226 | my ($delta, $app) = @_; |
227 | $app->draw_rect( |
228 | [ $ball->x, $ball->y, $ball->size, $ball->size ], |
229 | $ball->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. |
248 | The 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, |
293 | and 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> |