File Coverage

blib/lib/SDLx/Sprite.pm
Criterion Covered Total %
statement 102 134 76.1
branch 35 62 56.4
condition 8 21 38.1
subroutine 23 26 88.4
pod 0 15 0.0
total 168 258 65.1


line stmt bran cond sub pod time code
1             package SDLx::Sprite;
2 4     4   1241 use strict;
  4         5  
  4         101  
3 4     4   11 use warnings;
  4         5  
  4         73  
4              
5 4     4   12 use SDL;
  4         5  
  4         208  
6 4     4   14 use SDL::Video;
  4         5  
  4         468  
7 4     4   463 use SDL::Image;
  4         5  
  4         153  
8 4     4   1180 use SDLx::Rect;
  4         9  
  4         213  
9 4     4   23 use SDL::Surface;
  4         7  
  4         901  
10 4     4   724 use SDLx::Surface;
  4         6  
  4         109  
11 4     4   16 use SDLx::Validate;
  4         6  
  4         72  
12              
13 4     4   13 use Carp ();
  4         3  
  4         3285  
14              
15             sub new {
16 11     11 0 2080 my ( $class, %options ) = @_;
17              
18 11         50 my $self = bless {}, $class;
19 11 50 33     61 if ( exists $options{surface} ) {
    100          
    50          
20 0         0 $self->{surface} = SDLx::Surface->new( surface => $options{surface} );
21 0         0 $self->{orig_surface} = $options{surface};
22 0         0 $self->_init_rects(%options);
23 0         0 $self->handle_surface( $self->surface );
24             } elsif ( exists $options{image} ) {
25 9         60 my $surf = SDLx::Surface->load( $options{image} );
26 9         30 $self->{surface} = SDLx::Surface->new( surface => $surf );
27 9         34 $self->_init_rects(%options);
28 9         29 $self->handle_surface($surf);
29 9         22 $self->{orig_surface} = $self->{surface};
30             } elsif ( exists $options{width} && $options{height} ) {
31 2         14 $self->{surface} = SDLx::Surface->new(%options);
32 2         6 $self->{orig_surface} = $self->surface;
33 2         8 $self->_init_rects(%options);
34 2         4 $self->handle_surface( $self->surface );
35             } else {
36 0         0 Carp::confess "Need a surface => SDL::Surface, an image => name, or ( width => ... , height => ...)";
37             }
38              
39             # short-circuit
40 11 50       27 return $self unless %options;
41              
42 11 50 33     69 Carp::confess 'rect cannot be instantiated together with x or y'
      66        
43             if exists $options{rect} and ( exists $options{x} or exists $options{y} );
44              
45 11 50 66     60 Carp::confess 'image and surface cannot be instantiated together'
46             if exists $options{image} and exists $options{surface};
47              
48             # note: ordering here is somewhat important. If you change anything,
49             # please rerun the test suite to make sure everything still works :)
50              
51 11 50       25 $self->x( $options{x} ) if exists $options{x};
52 11 50       20 $self->y( $options{y} ) if exists $options{y};
53 11 50       23 $self->rotation( $options{rotation} ) if exists $options{rotation};
54 11 50       27 $self->alpha_key( $options{alpha_key} ) if exists $options{alpha_key};
55 11 50       21 $self->alpha( $options{alpha} ) if exists $options{alpha};
56              
57 11         35 return $self;
58             }
59              
60             sub _init_rects {
61 11     11   27 my ( $self, %options ) = @_;
62              
63             # create our two initial rects
64 11 100       60 $self->rect(
65             exists $options{rect}
66             ? $options{rect}
67             : SDLx::Rect->new( 0, 0, 0, 0 )
68             );
69 11 100       60 $self->clip(
70             exists $options{clip}
71             ? $options{clip}
72             : SDLx::Rect->new( 0, 0, 0, 0 )
73             );
74              
75             }
76              
77             sub load {
78 2     2 0 676 my ( $self, $filename ) = @_;
79              
80 2         10 my $surface = SDLx::Surface->load($filename);
81 2 50       10 $self->{orig_surface} = $surface unless $self->{orig_surface};
82 2         5 $self->handle_surface($surface);
83 2         5 return $self;
84             }
85              
86             sub handle_surface {
87 13     13 0 33 my ( $self, $surface ) = @_;
88              
89             # short-circuit
90 13 50       171 return $self->surface unless $surface;
91              
92 13         33 my $old_surface = $self->surface();
93 13         32 $self->surface($surface);
94              
95             # update our source and destination rects
96 13         27 $self->rect->w( $surface->w );
97 13         23 $self->rect->h( $surface->h );
98 13         21 $self->clip->w( $surface->w );
99 13         23 $self->clip->h( $surface->h );
100              
101 13         21 return $old_surface;
102             }
103              
104             sub rect {
105 71     71 0 5506 my ( $self, $rect ) = @_;
106              
107             # short-circuit
108 71 100       279 return $self->{rect} unless $rect;
109              
110 11         74 return $self->{rect} = SDLx::Validate::rect($rect);
111             }
112              
113             sub clip {
114 172     172 0 765 my ( $self, $clip ) = @_;
115              
116             # short-circuit
117 172 100       468 return $self->{clip} unless $clip;
118              
119 11         160 return $self->{clip} = SDLx::Validate::rect($clip);
120             }
121              
122             sub x {
123 2     2 0 3824 my ( $self, $x ) = @_;
124              
125 2 50       8 if ( defined $x ) {
126 0         0 $self->rect->x($x);
127             }
128              
129 2         6 return $self->rect->x;
130             }
131              
132             sub y {
133 2     2 0 3 my ( $self, $y ) = @_;
134              
135 2 50       7 if ( defined $y ) {
136 0         0 $self->rect->y($y);
137             }
138              
139 2         18 return $self->rect->y;
140             }
141              
142             sub draw {
143 0     0 0 0 my ( $self, $surface ) = @_;
144 0         0 SDLx::Validate::surface($surface);
145 0         0 $self->{surface}->blit( $surface, $self->clip, $self->rect );
146 0         0 return $self;
147             }
148              
149             sub draw_xy {
150 0     0 0 0 my ( $self, $surface, $x, $y ) = @_;
151 0         0 SDLx::Validate::surface($surface);
152 0         0 $self->x($x);
153 0         0 $self->y($y);
154 0         0 return $self->draw($surface);
155             }
156              
157             sub alpha_key {
158 3     3 0 4 my ( $self, $color ) = @_;
159              
160 3         10 $color = SDLx::Validate::color($color);
161 3 50       15 Carp::confess 'SDL::Video::set_video_mode must be called first'
162             unless ref SDL::Video::get_video_surface();
163 3 100       20 $self->{alpha_key} = $color
164             unless $self->{alpha_key}; # keep a copy just in case
165 3         7 $self->surface( SDL::Video::display_format( $self->surface ) );
166              
167 3 50       9 if ( SDL::Video::set_color_key( $self->surface, SDL_SRCCOLORKEY, $color ) < 0 ) {
168 0         0 Carp::confess ' alpha_key died :' . SDL::get_error;
169             }
170              
171 3         8 return $self;
172             }
173              
174             sub alpha {
175 4     4 0 6 my ( $self, $value ) = @_;
176              
177 4 100 66     19 $value = int( $value * 0xff ) if $value < 1 and $value > 0;
178              
179 4 50       8 $value = 0 if $value < 0;
180 4 50       8 $value = 0xff if $value > 0xff;
181 4         4 $self->{alpha} = $value; # keep a copy just in case
182 4         6 $self->surface( SDL::Video::display_format( $self->surface ) );
183 4         9 my $flags = SDL_SRCALPHA | SDL_RLEACCEL; #this should be predictive
184 4 50       7 if ( SDL::Video::set_alpha( $self->surface, $flags, $value ) < 0 ) {
185 0         0 Carp::confess 'alpha died :' . SDL::get_error;
186             }
187              
188 4         11 return $self;
189             }
190              
191             sub rotation {
192 0     0 0 0 my ( $self, $angle, $smooth ) = @_;
193              
194 0 0 0     0 if ( $angle && $self->{orig_surface} ) {
195              
196 0         0 require SDL::GFX::Rotozoom;
197              
198 0 0 0     0 my $rotated = SDL::GFX::Rotozoom::surface(
199             $self->{orig_surface}, #prevents rotting of the surface
200             $angle,
201             1, # zoom
202             ( defined $smooth && $smooth != 0 )
203             ) or Carp::confess 'rotation error: ' . SDL::get_error;
204              
205             #After rotation the surface is on a undefined background.
206             #This causes problems with alpha. So we create a surface with a fill of the src_color.
207             #This insures less artifacts.
208 0 0       0 if ( $self->{alpha_key} ) {
209 0         0 my $background = SDLx::Surface::duplicate($rotated);
210 0         0 $background->draw_rect(
211             [ 0, 0, $background->w, $background->h ],
212             $self->{alpha_key}
213             );
214 0         0 SDLx::Surface->new( surface => $rotated )->blit($background);
215              
216 0         0 $self->handle_surface( $background->surface );
217 0         0 $self->alpha_key( $self->{alpha_key} );
218             } else {
219 0         0 $self->handle_surface($rotated);
220             }
221              
222 0 0       0 $self->alpha( $self->{alpha} ) if $self->{alpha};
223 0         0 $self->{angle} = $angle;
224             }
225 0         0 return $self->{angle};
226             }
227              
228             sub surface {
229 71     71 0 63 my ( $self, $surface ) = @_;
230              
231 71 100       105 if ($surface) {
232 20         60 $self->{surface} = SDLx::Validate::surfacex($surface);
233             }
234 71         1066 return $self->{surface};
235             }
236              
237             sub w {
238 2     2 0 1505 return $_[0]->{surface}->w;
239             }
240              
241             sub h {
242 2     2 0 8 return $_[0]->{surface}->h;
243             }
244              
245             1;