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