1SDLx::Controller(3)   User Contributed Perl Documentation  SDLx::Controller(3)
2
3
4

NAME

6       SDLx::Controller - Handles the loops for events, movement and rendering
7

CATEGORY

9       Extension, Controller
10

SYNOPSIS

12        use SDLx::Controller;
13
14        # create our controller object
15        my $app = SDLx::Controller->new;
16
17        # we could also do:
18        my $app = SDLx::App->new;
19        # because App is also a controller
20
21        # register some callbacks
22        $app->add_event_handler( \&on_event );
23        $app->add_move_handler( \&on_move );
24        $app->add_show_handler( \&on_show );
25
26        # run our game loop
27        $app->run;
28
29   DESCRIPTION
30       The core of an SDL application/game is the main loop, where you handle
31       events and display your elements on the screen until something signals
32       the end of the program. This usually goes in the form of:
33
34         while (1) {
35             ...
36         }
37
38       The problem most developers face, besides the repetitive work, is to
39       ensure the screen update is independent of the frame rate. Otherwise,
40       your game will run at different speeds on different machines and this
41       is never good (old MS-DOS games, anyone?).
42
43       One way to circumvent this is by capping the frame rate so it's the
44       same no matter what, but this is not the right way to do it as it
45       penalizes better hardware.
46
47       This module provides an industry-proven standard for frame independent
48       movement. It calls the movement handlers based on time (hi-res seconds)
49       rather than frame rate. You can add/remove handlers and control your
50       main loop with ease.
51

METHODS

53   new
54        SDLx::Controller->new(
55            dt    => 0.5,
56            min_t => 0,
57            event => $event_object,
58        );
59
60       The "dt" parameter specifies the length, in seconds, of a full movement
61       step, and defaults to 0.1.  The "dt" can  be anything and the game can
62       still look the same.  It is only when you change the "dt" without
63       changing all the things in the movement step that are being multiplied
64       by the first move argument that it will make a difference.  If you
65       lower the "dt", everything will move faster than it did with it set
66       higher, and vice-versa.  This is useful to add slo-mo and fast-forward
67       features to the game, all you would have to do is change the "dt".
68
69       "min_t" specifies the minimum time, in seconds, that has to accumulate
70       before any move or show handlers are called, and defaults to 1 / 60.
71       Having the "min_t" at 1 / 60 ensures that the controller can update the
72       screen at a maximum of 60 times per second.  A "V-Sync" such as this is
73       necessary to prevent video "tear", which occurs when the app is
74       updating faster than the monitor can display.  Setting it to 0, as seen
75       above, will let the app run as fast as it possibly can.
76
77       "delay" specifies a loop delay in millisecs to place on the controller
78       loop. NOTE: Picking a good delay based on the needs can help reduce CPU
79       load and pressure.
80
81       "event" is a SDL::Event object that events going to the event callbacks
82       are polled in to. It defaults to "SDL::Event->new()".
83
84       All parameters are optional.
85
86       Returns the new object.
87
88   run
89       After creating and setting up your handlers (see below), call this
90       method to activate the main loop. The main loop will run until "stop"
91       is called.
92
93       All hooked functions will be called during the main loop, in this
94       order:
95
96       1. Events
97       2. Movements
98       3. Displaying
99
100       Please refer to each handler below for information on received
101       arguments.  Note that the second argument every callback receives is
102       the "SDLx::Controller" object.
103
104   stop
105       Returns from the "run" loop.
106
107   pause
108       Attempts to pause the application with a call to
109       "SDL::Events::wait_event". See SDL::Events.
110
111       Takes 1 argument which is a callback. The application waits for the
112       next event with "wait_event".  When one is received, it is passed to
113       the callback as the first argument, along with the "SDLx::Controller"
114       object as the second argument.  If the callback then returns a true
115       value, "pause" will return.  If the callback returns a false value,
116       "pause" will repeat the process.
117
118       This can be used to easily implement a pause when the app loses focus:
119
120        sub window {
121            my ($e, $app) = @_;
122            if($e->type == SDL_QUIT) {
123                $app->stop;
124                # quit handling is here so that the app
125                # can be stopped while paused
126            }
127            elsif($e->type == SDL_ACTIVEEVENT) {
128                if($e->active_state & SDL_APPINPUTFOCUS) {
129                    if($e->active_gain) {
130                        return 1;
131                    }
132                    else {
133                        $app->pause(\&window);
134                        # recursive, but only once since the window
135                        # can't lose focus again without gaining it first
136                    }
137                }
138            }
139            return 0;
140        }
141
142       Note: if you implement your own pause function, remember to update
143       "current_time" to the current time when the application unpauses.  This
144       should be done with "Time::HiRes::time".  Otherwise, time will
145       accumulate while the application is paused, and many movement steps
146       will be called all at once when it unpauses.
147
148       Note 2: a pause will be potentially dangerous to the "run" cycle (even
149       if you implement your own) unless called by an "event" callback.
150
151   paused
152       Returns 1 if the app is paused, undef otherwise.  This is only useful
153       when used within code that will be run by "pause":
154
155        sub pause {
156            # press P to toggle pause
157
158            my ($e, $app) = @_;
159            if($e->type == SDL_QUIT) {
160                $app->stop;
161                # quit handling is here so that the app
162                # can be stopped while paused
163            }
164            elsif($e->type == SDL_KEYDOWN) {
165                if($e->key_sym == SDLK_p) {
166                    # We're paused, so end pause
167                    return 1 if $app->paused;
168
169                    # We're not paused, so pause
170                    $app->pause(\&pause);
171                }
172            }
173            return 0;
174        }
175
176   add_event_handler
177       Register a callback to handle events. You can add as many subs as you
178       need.  Whenever a SDL::Event occurs, all registered callbacks will be
179       triggered in order. Returns the order queue number of the added
180       callback.
181
182       The first argument passed to registered callbacks is the SDL::Event
183       object.  The second is the "SDLx::Controller" object.
184
185        sub stop {
186           my ($event, $app) = @_;
187           if($event->type == SDL_QUIT) {
188               $app->stop;
189           }
190        }
191        $app->add_event_handler(\&stop);
192
193   add_move_handler
194       Register a callback to update your objects. You can add as many subs as
195       you need. Returns the order queue number of the added callback.
196
197       All registered callbacks will be triggered in order for as many "dt" as
198       have happened between calls, and once more for any remaining time less
199       than "dt".  The first argument passed to the callbacks is the portion
200       of the step, which will be 1 for a full step, and less than 1 for a
201       partial step.  Movement values should be multiplied by this value.  The
202       full steps correspond to the amount of "dt" passed between calls, and
203       the partial step corresponds to the call with the remaining time less
204       than "dt".  The argument can be 0 if no time has passed since the last
205       cycle. If you need to protect against this, set a "min_t", or put a
206       "return unless $_[0]" at the start of every move handler.
207
208       The second argument passed to the callbacks is the "SDLx::Controller"
209       object.  The third is the total amount of time passed since the call of
210       "run".
211
212       You should use these handlers to update your in-game objects, check
213       collisions, etc.  so you can check and/or update it as necessary.
214
215        sub move_ball {
216            my ($step, $app, $t) = @_;
217            $ball->move_x( $ball->x_vel * $step );
218            $ball->move_y( $ball->y_vel * $step );
219        }
220
221   add_show_handler
222       Register a callback to render objects. You can add as many subs as you
223       need.  Returns the order queue number of the added callback.  All
224       registered callbacks will be triggered in order, once per run of the
225       "run" loop.
226
227       The first argument passed is the time, in seconds, since the previous
228       call.  The second is the "SDLx::Controller" object.
229
230        sub show_ball {
231            my ($delta, $app) = @_;
232            $app->draw_rect(
233                [ $ball->x, $ball->y, $ball->size, $ball->size ],
234                $ball->colour
235            );
236        }
237
238   remove_move_handler( $index )
239   remove_event_handler( $index )
240   remove_show_handler( $index )
241       Removes the handler with the given index from the respective calling
242       queue.
243
244       You can also pass a coderef.  The first coderef in the handler list
245       that this matches will be removed.
246
247       Returns the removed handler.
248
249   remove_all_move_handlers
250   remove_all_event_handlers
251   remove_all_show_handlers
252       Removes all handlers from the respective calling queue.
253
254   remove_all_handlers
255       Quick access to removing all handlers at once.
256
257   dt
258   min_t
259   current_time
260       If an argument is passed, modifies the corresponding value to the
261       argument.  "dt" and "min_t" will keep their old value until the
262       beginning of the next "run" cycle.
263
264       Returns the corresponding value.
265

AUTHORS

267       See "AUTHORS" in SDL.
268
269   ACKNOWLEDGEMENTS
270       The idea and base for this module comes from Lazy Foo's Frame
271       Independent Movement
272       <http://www.lazyfoo.net/SDL_tutorials/lesson32/index.php> tutorial, and
273       Glenn Fiedler's Fix Your Timestep <http://gafferongames.com/game-
274       physics/fix-your-timestep/> article on timing.
275
276
277
278perl v5.36.0                      2023-03-10               SDLx::Controller(3)
Impressum