File Coverage

blib/lib/SDLx/Controller.pm
Criterion Covered Total %
statement 144 177 81.3
branch 23 42 54.7
condition 5 13 38.4
subroutine 33 42 78.5
pod 0 23 0.0
total 205 297 69.0


line stmt bran cond sub pod time code
1             package SDLx::Controller;
2 6     6   668 use strict;
  6         15  
  6         174  
3 6     6   30 use warnings;
  6         13  
  6         161  
4 6     6   30 use Carp;
  6         12  
  6         289  
5 6     6   34 use Time::HiRes;
  6         12  
  6         45  
6 6     6   501 use SDL;
  6         14  
  6         456  
7 6     6   353 use SDL::Event;
  6         14  
  6         4834  
8 6     6   372 use SDL::Events;
  6         15  
  6         13553  
9 6     6   48 use SDL::Video;
  6         14  
  6         1043  
10 6     6   4318 use SDLx::Controller::Interface;
  6         19  
  6         250  
11 6     6   2378 use SDLx::Controller::State;
  6         19  
  6         270  
12 6     6   43 use Scalar::Util 'refaddr';
  6         14  
  6         11671  
13              
14             our $VERSION = 2.548;
15              
16             # inside out, so this can work as the superclass of another
17             # SDL::Surface subclass
18             my %_dt;
19             my %_min_t;
20             my %_current_time;
21             my %_stop;
22             my %_event;
23             my %_event_handlers;
24             my %_move_handlers;
25             my %_show_handlers;
26             my %_sleep_cycle;
27             my %_eoq;
28             my %_paused;
29              
30             sub new {
31 6     6 0 2720 my ($self, %args) = @_;
32 6 100       21 if(ref $self) {
33 3         7 bless $self, ref $self;
34             }
35             else {
36 3         6 my $a;
37 3         7 $self = bless \$a, $self;
38             }
39              
40 6         20 my $ref = refaddr $self;
41              
42 6 100       33 $_dt{ $ref } = defined $args{dt} ? $args{dt} : 0.1;
43 6 100       23 $_min_t{ $ref } = defined $args{min_t} ? $args{min_t} : 1 / 60;
44             # $_current_time{ $ref } = $args{current_time} || 0; #no point
45 6         13 $_stop{ $ref } = $args{stop};
46 6   33     132 $_event{ $ref } = $args{event} || SDL::Event->new();
47 6   50     34 $_event_handlers{ $ref } = $args{event_handlers} || [];
48 6   50     27 $_move_handlers{ $ref } = $args{move_handlers} || [];
49 6   50     30 $_show_handlers{ $ref } = $args{show_handlers} || [];
50 6         13 $_sleep_cycle{ $ref } = $args{delay};
51 6   50     48 $_eoq{$ref} = $args{exit_on_quit} || $args{eoq} || 0;
52             # $_paused{ $ref } = $args{paused}; #read only
53              
54 6         22 return $self;
55             }
56              
57              
58             sub delay {
59 0     0 0 0 my $self = shift;
60 0         0 my $delay = shift;
61 0         0 my $ref = refaddr $self;
62            
63 0 0       0 $_sleep_cycle{ $ref } = $delay if $delay;
64 0         0 return $self;
65             }
66              
67             sub DESTROY {
68 1     1   6 my $self = shift;
69 1         3 my $ref = refaddr $self;
70              
71 1         3 delete $_dt{ $ref};
72 1         2 delete $_min_t{ $ref};
73 1         2 delete $_current_time{ $ref};
74 1         1 delete $_stop{ $ref};
75 1         5 delete $_event{ $ref};
76 1         2 delete $_event_handlers{ $ref};
77 1         2 delete $_move_handlers{ $ref};
78 1         1 delete $_show_handlers{ $ref};
79 1         2 delete $_sleep_cycle { $ref };
80 1         2 delete $_eoq{$ref};
81 1         6 delete $_paused{$ref};
82             }
83              
84             sub run {
85 2     2 0 11 my ($self) = @_;
86 2         6 my $ref = refaddr $self;
87 2         4 my $dt = $_dt{ $ref };
88 2         5 my $min_t = $_min_t{ $ref };
89 2         3 my $t = 0.0;
90              
91             #Allows us to do stop and run
92 2         5 $_stop{ $ref } = 0;
93              
94 2         8 $_current_time{ $ref } = Time::HiRes::time;
95 2         7 while ( !$_stop{ $ref } ) {
96 1426795         2422257 $self->_event($ref);
97              
98 1426795         2166237 my $new_time = Time::HiRes::time;
99 1426795         1850693 my $delta_time = $new_time - $_current_time{ $ref };
100 1426795 100       2863902 next if $delta_time < $min_t;
101 32         70 $_current_time{ $ref} = $new_time;
102 32         67 my $delta_copy = $delta_time;
103              
104 32         94 while ( $delta_copy > $dt ) {
105 150         473 $self->_move( $ref, 1, $t ); #a full move
106 150         422822 $delta_copy -= $dt;
107 150         590 $t += $dt;
108             }
109 32         103 my $step = $delta_copy / $dt;
110 32         118 $self->_move( $ref, $step, $t ); #a partial move
111 32         85782 $t += $dt * $step;
112              
113 32         146 $self->_show( $ref, $delta_time );
114              
115 32         71907 $dt = $_dt{ $ref}; #these can change
116 32         90 $min_t = $_min_t{ $ref}; #during the cycle
117 32 100       400452 SDL::delay( $_sleep_cycle{ $ref } ) if $_sleep_cycle{ $ref };
118             }
119              
120             }
121              
122             sub exit_on_quit {
123 12     12 0 26 my ($self, $value) = @_;
124              
125 12         38 my $ref = refaddr $self;
126 12 100       31 if (defined $value) {
127 2         3 $_eoq{$ref} = $value;
128             }
129              
130 12         38 return $_eoq{$ref};
131             }
132             *eoq = \&exit_on_quit; # alias
133              
134             sub pause {
135 0     0 0 0 my ($self, $callback) = @_;
136 0         0 my $ref = refaddr $self;
137 0   0 0   0 $callback ||= sub {1};
  0         0  
138 0         0 my $event = SDL::Event->new();
139 0         0 $_paused{ $ref} = 1;
140 0         0 while(1) {
141 0 0       0 SDL::Events::wait_event($event) or Carp::confess("pause failed waiting for an event");
142 0 0       0 if($callback->($event, $self)) {
143 0         0 $_current_time{ $ref} = Time::HiRes::time; #so run doesn't catch up with the time paused
144 0         0 last;
145             }
146             }
147 0         0 delete $_paused{ $ref};
148             }
149              
150             sub _event {
151 1426795     1426795   1917057 my ($self, $ref) = @_;
152 1426795         3101175 while ( SDL::Events::poll_event( $_event{ $ref} ) ) {
153 1 50       3 $self->_exit_on_quit( $_event{ $ref} ) if $_eoq{$ref};
154 1         2 foreach my $event_handler ( @{ $_event_handlers{ $ref} } ) {
  1         3  
155 1 50       3 next unless $event_handler;
156 1         3 $event_handler->( $_event{ $ref}, $self );
157             }
158             }
159             }
160              
161             sub _move {
162 182     182   441 my ($self, $ref, $move_portion, $t) = @_;
163 182         281 foreach my $move_handler ( @{ $_move_handlers{ $ref} } ) {
  182         499  
164 362 50       112424 next unless $move_handler;
165 362         981 $move_handler->( $move_portion, $self, $t );
166             }
167             }
168              
169             sub _show {
170 32     32   96 my ($self, $ref, $delta_ticks) = @_;
171 32         64 foreach my $show_handler ( @{ $_show_handlers{ $ref} } ) {
  32         97  
172 62 50       17433 next unless $show_handler;
173 62         199 $show_handler->( $delta_ticks, $self );
174             }
175             }
176              
177 5     5 0 3040 sub stop { $_stop{ refaddr $_[0] } = 1 }
178              
179             sub _add_handler {
180 13     13   17 my ( $arr_ref, $handler ) = @_;
181 13         17 push @{$arr_ref}, $handler;
  13         19  
182 13         13 return $#{$arr_ref};
  13         38  
183             }
184              
185             sub add_move_handler {
186 5     5 0 531 my $ref = refaddr $_[0];
187 5         14 return _add_handler( $_move_handlers{ $ref}, $_[1] );
188             }
189              
190             sub add_event_handler {
191 3     3 0 550 my $ref = refaddr $_[0];
192 3 50       15 Carp::confess 'SDLx::App or a Display (SDL::Video::get_video_mode) must be made'
193             unless SDL::Video::get_video_surface();
194 3         29 return _add_handler( $_event_handlers{ $ref}, $_[1] );
195             }
196              
197             sub add_show_handler {
198 5     5 0 537 my $ref = refaddr $_[0];
199 5         11 return _add_handler( $_show_handlers{ $ref}, $_[1] );
200             }
201              
202             sub _remove_handler {
203 8     8   16 my ( $arr_ref, $id ) = @_;
204 8 100       24 if ( ref $id ) {
    50          
205             ($id) = grep {
206 6         17 $id eq $arr_ref->[$_]
207 3         5 } 0..$#{$arr_ref};
  3         7  
208              
209 3 50       11 if ( !defined $id ) {
210 0         0 Carp::cluck("$id is not currently a handler of this type");
211 0         0 return;
212             }
213             }
214             elsif(!defined $arr_ref->[$id]) {
215 0         0 Carp::cluck("$id is not currently a handler of this type");
216 0         0 return;
217             }
218 8         28 return delete( $arr_ref->[$id] );
219             }
220              
221             sub remove_move_handler {
222 3     3 0 16 return _remove_handler( $_move_handlers{ refaddr $_[0] }, $_[1] );
223             }
224              
225             sub remove_event_handler {
226 2     2 0 8 return _remove_handler( $_event_handlers{ refaddr $_[0] }, $_[1] );
227             }
228              
229             sub remove_show_handler {
230 3     3 0 14 return _remove_handler( $_show_handlers{ refaddr $_[0] }, $_[1] );
231             }
232              
233             sub remove_all_handlers {
234 0     0 0 0 $_[0]->remove_all_move_handlers;
235 0         0 $_[0]->remove_all_event_handlers;
236 0         0 $_[0]->remove_all_show_handlers;
237             }
238              
239             sub remove_all_move_handlers {
240 0     0 0 0 $_move_handlers{ refaddr $_[0] } = [];
241             }
242              
243             sub remove_all_event_handlers {
244 1     1 0 5 $_event_handlers{ refaddr $_[0] } = [];
245             }
246              
247             sub remove_all_show_handlers {
248 0     0 0 0 $_show_handlers{ refaddr $_[0] } = [];
249             }
250              
251 5     5 0 1236 sub move_handlers { $_move_handlers{ refaddr $_[0] } }
252 6     6 0 1070 sub event_handlers { $_event_handlers{ refaddr $_[0] } }
253 5     5 0 1094 sub show_handlers { $_show_handlers{ refaddr $_[0] } }
254              
255             sub dt {
256 4     4 0 442 my ($self, $arg) = @_;
257 4         14 my $ref = refaddr $self;
258 4 50       14 $_dt{ $ref} = $arg if defined $arg;
259              
260 4         36 $_dt{ $ref};
261             }
262              
263             sub min_t {
264 2     2 0 5 my ($self, $arg) = @_;
265 2         6 my $ref = refaddr $self;
266 2 50       6 $_min_t{ $ref} = $arg if defined $arg;
267              
268 2         9 $_min_t{ $ref};
269             }
270              
271             sub current_time {
272 0     0 0   my ($self, $arg) = @_;
273 0           my $ref = refaddr $self;
274 0 0         $_current_time{ $ref} = $arg if defined $arg;
275              
276 0           $_current_time{ $ref};
277             }
278              
279             sub paused {
280 0     0 0   $_paused{ refaddr $_[0]};
281             }
282              
283             sub _exit_on_quit {
284 0     0     my ($self, $event) = @_;
285              
286 0 0         $self->stop() if $event->type == SDL_QUIT;
287             }
288              
289             1;
290              
291             __END__