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