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   2549 use strict;
  4         9  
  4         141  
3 4     4   22 use warnings;
  4         8  
  4         108  
4              
5 4     4   23 use SDL;
  4         8  
  4         379  
6 4     4   22 use SDL::Video;
  4         8  
  4         828  
7 4     4   945 use SDL::Image;
  4         9  
  4         254  
8 4     4   2583 use SDLx::Rect;
  4         12  
  4         287  
9 4     4   35 use SDL::Surface;
  4         7  
  4         1666  
10 4     4   1210 use SDLx::Surface;
  4         12  
  4         164  
11 4     4   23 use SDLx::Validate;
  4         9  
  4         112  
12              
13 4     4   23 use Carp ();
  4         10  
  4         5928  
14              
15             sub new {
16 11     11 0 1900 my ( $class, %options ) = @_;
17              
18 11         54 my $self = bless {}, $class;
19 11 50 33     83 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         64 my $surf = SDLx::Surface->load( $options{image} );
26 9         43 $self->{surface} = SDLx::Surface->new( surface => $surf );
27 9         59 $self->_init_rects(%options);
28 9         39 $self->handle_surface($surf);
29 9         27 $self->{orig_surface} = $self->{surface};
30             } elsif ( exists $options{width} && $options{height} ) {
31 2         20 $self->{surface} = SDLx::Surface->new(%options);
32 2         10 $self->{orig_surface} = $self->surface;
33 2         14 $self->_init_rects(%options);
34 2         8 $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       33 return $self unless %options;
41              
42 11 50 33     109 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     63 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       30 $self->x( $options{x} ) if exists $options{x};
52 11 50       29 $self->y( $options{y} ) if exists $options{y};
53 11 50       29 $self->rotation( $options{rotation} ) if exists $options{rotation};
54 11 50       25 $self->alpha_key( $options{alpha_key} ) if exists $options{alpha_key};
55 11 50       26 $self->alpha( $options{alpha} ) if exists $options{alpha};
56              
57 11         45 return $self;
58             }
59              
60             sub _init_rects {
61 11     11   39 my ( $self, %options ) = @_;
62              
63             # create our two initial rects
64 11 100       86 $self->rect(
65             exists $options{rect}
66             ? $options{rect}
67             : SDLx::Rect->new( 0, 0, 0, 0 )
68             );
69 11 100       78 $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 629 my ( $self, $filename ) = @_;
79              
80 2         15 my $surface = SDLx::Surface->load($filename);
81 2 50       19 $self->{orig_surface} = $surface unless $self->{orig_surface};
82 2         96 $self->handle_surface($surface);
83 2         11 return $self;
84             }
85              
86             sub handle_surface {
87 13     13 0 29 my ( $self, $surface ) = @_;
88              
89             # short-circuit
90 13 50       271 return $self->surface unless $surface;
91              
92 13         45 my $old_surface = $self->surface();
93 13         37 $self->surface($surface);
94              
95             # update our source and destination rects
96 13         39 $self->rect->w( $surface->w );
97 13         46 $self->rect->h( $surface->h );
98 13         34 $self->clip->w( $surface->w );
99 13         39 $self->clip->h( $surface->h );
100              
101 13         26 return $old_surface;
102             }
103              
104             sub rect {
105 71     71 0 7334 my ( $self, $rect ) = @_;
106              
107             # short-circuit
108 71 100       1036 return $self->{rect} unless $rect;
109              
110 11         112 return $self->{rect} = SDLx::Validate::rect($rect);
111             }
112              
113             sub clip {
114 172     172 0 1479 my ( $self, $clip ) = @_;
115              
116             # short-circuit
117 172 100       1890 return $self->{clip} unless $clip;
118              
119 11         72 return $self->{clip} = SDLx::Validate::rect($clip);
120             }
121              
122             sub x {
123 2     2 0 4246 my ( $self, $x ) = @_;
124              
125 2 50       12 if ( defined $x ) {
126 0         0 $self->rect->x($x);
127             }
128              
129 2         7 return $self->rect->x;
130             }
131              
132             sub y {
133 2     2 0 7 my ( $self, $y ) = @_;
134              
135 2 50       8 if ( defined $y ) {
136 0         0 $self->rect->y($y);
137             }
138              
139 2         7 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 8 my ( $self, $color ) = @_;
159              
160 3         16 $color = SDLx::Validate::color($color);
161 3 50       26 Carp::confess 'SDL::Video::set_video_mode must be called first'
162             unless ref SDL::Video::get_video_surface();
163 3 100       43 $self->{alpha_key} = $color
164             unless $self->{alpha_key}; # keep a copy just in case
165 3         12 $self->surface( SDL::Video::display_format( $self->surface ) );
166              
167 3 50       18 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         17 return $self;
172             }
173              
174             sub alpha {
175 4     4 0 13 my ( $self, $value ) = @_;
176              
177 4 100 66     117 $value = int( $value * 0xff ) if $value < 1 and $value > 0;
178              
179 4 50       15 $value = 0 if $value < 0;
180 4 50       16 $value = 0xff if $value > 0xff;
181 4         9 $self->{alpha} = $value; # keep a copy just in case
182 4         15 $self->surface( SDL::Video::display_format( $self->surface ) );
183 4         16 my $flags = SDL_SRCALPHA | SDL_RLEACCEL; #this should be predictive
184 4 50       15 if ( SDL::Video::set_alpha( $self->surface, $flags, $value ) < 0 ) {
185 0         0 Carp::confess 'alpha died :' . SDL::get_error;
186             }
187              
188 4         26 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 110 my ( $self, $surface ) = @_;
230              
231 71 100       161 if ($surface) {
232 20         85 $self->{surface} = SDLx::Validate::surfacex($surface);
233             }
234 71         2766 return $self->{surface};
235             }
236              
237             sub w {
238 2     2 0 1698 return $_[0]->{surface}->w;
239             }
240              
241             sub h {
242 2     2 0 11 return $_[0]->{surface}->h;
243             }
244              
245             1;