First commit of SDL_Perl-2.1.3
[sdlgit/SDL_perl.git] / lib / SDL / Tutorial / Images.pm
1 package SDL::Tutorial::Images;
2
3 use strict;
4 use warnings;
5
6 my %images;
7 BEGIN
8 {
9         %images = (
10         left => [qw(
11                 47 49 46 38 37 61 10 00 10 00 E7 00 00 00 00 00 01 01 01 02 02 02 03 03
12                 03 04 04 04 05 05 05 06 06 06 07 07 07 08 08 08 09 09 09 0A 0A 0A 0B 0B
13                 0B 0C 0C 0C 0D 0D 0D 0E 0E 0E 0F 0F 0F 10 10 10 11 11 11 12 12 12 13 13
14                 13 14 14 14 15 15 15 16 16 16 17 17 17 18 18 18 19 19 19 1A 1A 1A 1B 1B
15                 1B 1C 1C 1C 1D 1D 1D 1E 1E 1E 1F 1F 1F 20 20 20 21 21 21 22 22 22 23 23
16                 23 24 24 24 25 25 25 26 26 26 27 27 27 28 28 28 29 29 29 2A 2A 2A 2B 2B
17                 2B 2C 2C 2C 2D 2D 2D 2E 2E 2E 2F 2F 2F 30 30 30 31 31 31 32 32 32 33 33
18                 33 34 34 34 35 35 35 36 36 36 37 37 37 38 38 38 39 39 39 3A 3A 3A 3B 3B
19                 3B 3C 3C 3C 3D 3D 3D 3E 3E 3E 3F 3F 3F 40 40 40 41 41 41 42 42 42 43 43
20                 43 44 44 44 45 45 45 46 46 46 47 47 47 48 48 48 49 49 49 4A 4A 4A 4B 4B
21                 4B 4C 4C 4C 4D 4D 4D 4E 4E 4E 4F 4F 4F 50 50 50 51 51 51 52 52 52 53 53
22                 53 54 54 54 55 55 55 56 56 56 57 57 57 58 58 58 59 59 59 5A 5A 5A 5B 5B
23                 5B 5C 5C 5C 5D 5D 5D 5E 5E 5E 5F 5F 5F 60 60 60 61 61 61 62 62 62 63 63
24                 63 64 64 64 65 65 65 66 66 66 67 67 67 68 68 68 69 69 69 6A 6A 6A 6B 6B
25                 6B 6C 6C 6C 6D 6D 6D 6E 6E 6E 6F 6F 6F 70 70 70 71 71 71 72 72 72 73 73
26                 73 74 74 74 75 75 75 76 76 76 77 77 77 78 78 78 79 79 79 7A 7A 7A 7B 7B
27                 7B 7C 7C 7C 7D 7D 7D 7E 7E 7E 7F 7F 7F 80 80 80 81 81 81 82 82 82 83 83
28                 83 84 84 84 85 85 85 86 86 86 87 87 87 88 88 88 89 89 89 8A 8A 8A 8B 8B
29                 8B 8C 8C 8C 8D 8D 8D 8E 8E 8E 8F 8F 8F 90 90 90 91 91 91 92 92 92 93 93
30                 93 94 94 94 95 95 95 96 96 96 97 97 97 98 98 98 99 99 99 9A 9A 9A 9B 9B
31                 9B 9C 9C 9C 9D 9D 9D 9E 9E 9E 9F 9F 9F A0 A0 A0 A1 A1 A1 A2 A2 A2 A3 A3
32                 A3 A4 A4 A4 A5 A5 A5 A6 A6 A6 A7 A7 A7 A8 A8 A8 A9 A9 A9 AA AA AA AB AB
33                 AB AC AC AC AD AD AD AE AE AE AF AF AF B0 B0 B0 B1 B1 B1 B2 B2 B2 B3 B3
34                 B3 B4 B4 B4 B5 B5 B5 B6 B6 B6 B7 B7 B7 B8 B8 B8 B9 B9 B9 BA BA BA BB BB
35                 BB BC BC BC BD BD BD BE BE BE BF BF BF C0 C0 C0 C1 C1 C1 C2 C2 C2 C3 C3
36                 C3 C4 C4 C4 C5 C5 C5 C6 C6 C6 C7 C7 C7 C8 C8 C8 C9 C9 C9 CA CA CA CB CB
37                 CB CC CC CC CD CD CD CE CE CE CF CF CF D0 D0 D0 D1 D1 D1 D2 D2 D2 D3 D3
38                 D3 D4 D4 D4 D5 D5 D5 D6 D6 D6 D7 D7 D7 D8 D8 D8 D9 D9 D9 DA DA DA DB DB
39                 DB DC DC DC DD DD DD DE DE DE DF DF DF E0 E0 E0 E1 E1 E1 E2 E2 E2 E3 E3
40                 E3 E4 E4 E4 E5 E5 E5 E6 E6 E6 E7 E7 E7 E8 E8 E8 E9 E9 E9 EA EA EA EB EB
41                 EB EC EC EC ED ED ED EE EE EE EF EF EF F0 F0 F0 F1 F1 F1 F2 F2 F2 F3 F3
42                 F3 F4 F4 F4 F5 F5 F5 F6 F6 F6 F7 F7 F7 F8 F8 F8 F9 F9 F9 FA FA FA FB FB
43                 FB FC FC FC FD FD FD FE FE FE FF FF FF 2C 00 00 00 00 10 00 10 00 00 08
44                 36 00 FF 09 1C 48 B0 A0 C1 83 08 13 22 04 C0 10 80 C2 7F 0C 05 46 4C E8
45                 70 60 C5 85 15 27 52 6C A8 30 E3 45 8C 0D 39 76 FC 38 F2 A1 44 91 1B 4F
46                 82 24 88 D2 64 C1 80 00 3B
47         )],
48         center => [qw(
49                 47 49 46 38 37 61 10 00 10 00 E7 00 00 00 00 00 01 01 01 02 02 02 03 03
50                 03 04 04 04 05 05 05 06 06 06 07 07 07 08 08 08 09 09 09 0A 0A 0A 0B 0B
51                 0B 0C 0C 0C 0D 0D 0D 0E 0E 0E 0F 0F 0F 10 10 10 11 11 11 12 12 12 13 13
52                 13 14 14 14 15 15 15 16 16 16 17 17 17 18 18 18 19 19 19 1A 1A 1A 1B 1B
53                 1B 1C 1C 1C 1D 1D 1D 1E 1E 1E 1F 1F 1F 20 20 20 21 21 21 22 22 22 23 23
54                 23 24 24 24 25 25 25 26 26 26 27 27 27 28 28 28 29 29 29 2A 2A 2A 2B 2B
55                 2B 2C 2C 2C 2D 2D 2D 2E 2E 2E 2F 2F 2F 30 30 30 31 31 31 32 32 32 33 33
56                 33 34 34 34 35 35 35 36 36 36 37 37 37 38 38 38 39 39 39 3A 3A 3A 3B 3B
57                 3B 3C 3C 3C 3D 3D 3D 3E 3E 3E 3F 3F 3F 40 40 40 41 41 41 42 42 42 43 43
58                 43 44 44 44 45 45 45 46 46 46 47 47 47 48 48 48 49 49 49 4A 4A 4A 4B 4B
59                 4B 4C 4C 4C 4D 4D 4D 4E 4E 4E 4F 4F 4F 50 50 50 51 51 51 52 52 52 53 53
60                 53 54 54 54 55 55 55 56 56 56 57 57 57 58 58 58 59 59 59 5A 5A 5A 5B 5B
61                 5B 5C 5C 5C 5D 5D 5D 5E 5E 5E 5F 5F 5F 60 60 60 61 61 61 62 62 62 63 63
62                 63 64 64 64 65 65 65 66 66 66 67 67 67 68 68 68 69 69 69 6A 6A 6A 6B 6B
63                 6B 6C 6C 6C 6D 6D 6D 6E 6E 6E 6F 6F 6F 70 70 70 71 71 71 72 72 72 73 73
64                 73 74 74 74 75 75 75 76 76 76 77 77 77 78 78 78 79 79 79 7A 7A 7A 7B 7B
65                 7B 7C 7C 7C 7D 7D 7D 7E 7E 7E 7F 7F 7F 80 80 80 81 81 81 82 82 82 83 83
66                 83 84 84 84 85 85 85 86 86 86 87 87 87 88 88 88 89 89 89 8A 8A 8A 8B 8B
67                 8B 8C 8C 8C 8D 8D 8D 8E 8E 8E 8F 8F 8F 90 90 90 91 91 91 92 92 92 93 93
68                 93 94 94 94 95 95 95 96 96 96 97 97 97 98 98 98 99 99 99 9A 9A 9A 9B 9B
69                 9B 9C 9C 9C 9D 9D 9D 9E 9E 9E 9F 9F 9F A0 A0 A0 A1 A1 A1 A2 A2 A2 A3 A3
70                 A3 A4 A4 A4 A5 A5 A5 A6 A6 A6 A7 A7 A7 A8 A8 A8 A9 A9 A9 AA AA AA AB AB
71                 AB AC AC AC AD AD AD AE AE AE AF AF AF B0 B0 B0 B1 B1 B1 B2 B2 B2 B3 B3
72                 B3 B4 B4 B4 B5 B5 B5 B6 B6 B6 B7 B7 B7 B8 B8 B8 B9 B9 B9 BA BA BA BB BB
73                 BB BC BC BC BD BD BD BE BE BE BF BF BF C0 C0 C0 C1 C1 C1 C2 C2 C2 C3 C3
74                 C3 C4 C4 C4 C5 C5 C5 C6 C6 C6 C7 C7 C7 C8 C8 C8 C9 C9 C9 CA CA CA CB CB
75                 CB CC CC CC CD CD CD CE CE CE CF CF CF D0 D0 D0 D1 D1 D1 D2 D2 D2 D3 D3
76                 D3 D4 D4 D4 D5 D5 D5 D6 D6 D6 D7 D7 D7 D8 D8 D8 D9 D9 D9 DA DA DA DB DB
77                 DB DC DC DC DD DD DD DE DE DE DF DF DF E0 E0 E0 E1 E1 E1 E2 E2 E2 E3 E3
78                 E3 E4 E4 E4 E5 E5 E5 E6 E6 E6 E7 E7 E7 E8 E8 E8 E9 E9 E9 EA EA EA EB EB
79                 EB EC EC EC ED ED ED EE EE EE EF EF EF F0 F0 F0 F1 F1 F1 F2 F2 F2 F3 F3
80                 F3 F4 F4 F4 F5 F5 F5 F6 F6 F6 F7 F7 F7 F8 F8 F8 F9 F9 F9 FA FA FA FB FB
81                 FB FC FC FC FD FD FD FE FE FE FF FF FF 2C 00 00 00 00 10 00 10 00 00 08
82                 36 00 FF 09 1C 48 B0 A0 C1 83 08 13 26 04 C0 10 80 C2 7F 0C 05 46 5C 48
83                 D0 E1 42 8B 13 2F 66 54 B8 F1 60 C3 8F 16 2F 3E 1C D8 11 E1 C7 87 13 4B
84                 4A DC D8 70 E4 C1 80 00 3B
85         )],
86         right => [qw(
87                 47 49 46 38 37 61 10 00 10 00 E7 00 00 00 00 00 01 01 01 02 02 02 03 03
88                 03 04 04 04 05 05 05 06 06 06 07 07 07 08 08 08 09 09 09 0A 0A 0A 0B 0B
89                 0B 0C 0C 0C 0D 0D 0D 0E 0E 0E 0F 0F 0F 10 10 10 11 11 11 12 12 12 13 13
90                 13 14 14 14 15 15 15 16 16 16 17 17 17 18 18 18 19 19 19 1A 1A 1A 1B 1B
91                 1B 1C 1C 1C 1D 1D 1D 1E 1E 1E 1F 1F 1F 20 20 20 21 21 21 22 22 22 23 23
92                 23 24 24 24 25 25 25 26 26 26 27 27 27 28 28 28 29 29 29 2A 2A 2A 2B 2B
93                 2B 2C 2C 2C 2D 2D 2D 2E 2E 2E 2F 2F 2F 30 30 30 31 31 31 32 32 32 33 33
94                 33 34 34 34 35 35 35 36 36 36 37 37 37 38 38 38 39 39 39 3A 3A 3A 3B 3B
95                 3B 3C 3C 3C 3D 3D 3D 3E 3E 3E 3F 3F 3F 40 40 40 41 41 41 42 42 42 43 43
96                 43 44 44 44 45 45 45 46 46 46 47 47 47 48 48 48 49 49 49 4A 4A 4A 4B 4B
97                 4B 4C 4C 4C 4D 4D 4D 4E 4E 4E 4F 4F 4F 50 50 50 51 51 51 52 52 52 53 53
98                 53 54 54 54 55 55 55 56 56 56 57 57 57 58 58 58 59 59 59 5A 5A 5A 5B 5B
99                 5B 5C 5C 5C 5D 5D 5D 5E 5E 5E 5F 5F 5F 60 60 60 61 61 61 62 62 62 63 63
100                 63 64 64 64 65 65 65 66 66 66 67 67 67 68 68 68 69 69 69 6A 6A 6A 6B 6B
101                 6B 6C 6C 6C 6D 6D 6D 6E 6E 6E 6F 6F 6F 70 70 70 71 71 71 72 72 72 73 73
102                 73 74 74 74 75 75 75 76 76 76 77 77 77 78 78 78 79 79 79 7A 7A 7A 7B 7B
103                 7B 7C 7C 7C 7D 7D 7D 7E 7E 7E 7F 7F 7F 80 80 80 81 81 81 82 82 82 83 83
104                 83 84 84 84 85 85 85 86 86 86 87 87 87 88 88 88 89 89 89 8A 8A 8A 8B 8B
105                 8B 8C 8C 8C 8D 8D 8D 8E 8E 8E 8F 8F 8F 90 90 90 91 91 91 92 92 92 93 93
106                 93 94 94 94 95 95 95 96 96 96 97 97 97 98 98 98 99 99 99 9A 9A 9A 9B 9B
107                 9B 9C 9C 9C 9D 9D 9D 9E 9E 9E 9F 9F 9F A0 A0 A0 A1 A1 A1 A2 A2 A2 A3 A3
108                 A3 A4 A4 A4 A5 A5 A5 A6 A6 A6 A7 A7 A7 A8 A8 A8 A9 A9 A9 AA AA AA AB AB
109                 AB AC AC AC AD AD AD AE AE AE AF AF AF B0 B0 B0 B1 B1 B1 B2 B2 B2 B3 B3
110                 B3 B4 B4 B4 B5 B5 B5 B6 B6 B6 B7 B7 B7 B8 B8 B8 B9 B9 B9 BA BA BA BB BB
111                 BB BC BC BC BD BD BD BE BE BE BF BF BF C0 C0 C0 C1 C1 C1 C2 C2 C2 C3 C3
112                 C3 C4 C4 C4 C5 C5 C5 C6 C6 C6 C7 C7 C7 C8 C8 C8 C9 C9 C9 CA CA CA CB CB
113                 CB CC CC CC CD CD CD CE CE CE CF CF CF D0 D0 D0 D1 D1 D1 D2 D2 D2 D3 D3
114                 D3 D4 D4 D4 D5 D5 D5 D6 D6 D6 D7 D7 D7 D8 D8 D8 D9 D9 D9 DA DA DA DB DB
115                 DB DC DC DC DD DD DD DE DE DE DF DF DF E0 E0 E0 E1 E1 E1 E2 E2 E2 E3 E3
116                 E3 E4 E4 E4 E5 E5 E5 E6 E6 E6 E7 E7 E7 E8 E8 E8 E9 E9 E9 EA EA EA EB EB
117                 EB EC EC EC ED ED ED EE EE EE EF EF EF F0 F0 F0 F1 F1 F1 F2 F2 F2 F3 F3
118                 F3 F4 F4 F4 F5 F5 F5 F6 F6 F6 F7 F7 F7 F8 F8 F8 F9 F9 F9 FA FA FA FB FB
119                 FB FC FC FC FD FD FD FE FE FE FF FF FF 2C 00 00 00 00 10 00 10 00 00 08
120                 3A 00 FF 09 1C 48 B0 A0 C1 83 08 13 2A 04 C0 10 80 C2 7F 0C 05 46 4C E8
121                 70 60 45 84 13 27 52 6C F8 50 62 C5 8B 05 1B 8A 04 79 50 E3 43 93 1B 51
122                 1A CC 48 D2 A2 49 8E 1D 0B 06 04 00 3B
123         )],
124 );
125 }
126
127 use Pod::ToDemo sub
128 {
129         (undef, my $filename) = @_;
130         (my $imagebase        = $filename) =~ s/\.\w+$//;
131         my @img_files         = map { $imagebase . "_$_.gif" }
132                 qw( left center right );
133         my $demo_source       = <<'END_HERE';
134 package Walker;
135
136 sub new
137 {
138         my ($class, @images) = @_;
139         my @frames           = map { SDL::Surface->new( -name => $_ ) } @images;
140         my $frame_rect       = SDL::Rect->new(
141                 -height => $frames[0]->height(),
142                 -width  => $frames[0]->width(),
143                 -x      => 0,
144                 -y      => 0,
145         );
146         my $self             = 
147         {
148                 frames      => \@frames,
149                 frame_rect  => $frame_rect,
150         };
151         bless $self, $class;
152 }
153
154 sub frames
155 {
156         my $self        = shift;
157         $self->{frames} = shift if @_;
158         $self->{frames};
159 }
160
161 sub frame_rect
162 {
163         my $self            = shift;
164         $self->{frame_rect} = shift if @_;
165         $self->{frame_rect};
166 }
167
168 sub next_frame
169 {
170         my $self   = shift;
171         my $frames = $self->frames();
172         my $frame  = shift @$frames;
173
174         push @$frames, $frame;
175         $self->frames( $frames );
176
177         return $frame;
178 }
179
180 package main;
181
182 use strict;
183
184 use SDL;
185 use SDL::App;
186 use SDL::Surface;
187 use SDL::Color;
188
189 # change these values as necessary
190 my $title                                = 'My SDL Animation';
191 my ($width,      $height,      $depth)   = (  640,  480,   16 );
192 my ($bg_r,       $bg_g,        $bg_b)    = ( 0xff, 0xff, 0xff );
193 my ($start_x,    $end_x)                 = (   20,  600       );
194 my $sleep_msec                           = 0.05;
195
196 my $app = SDL::App->new(
197         -width  => $width,
198         -height => $height,
199         -depth  => $depth,
200 );
201
202 my $bg_color = SDL::Color->new(
203         -r => $bg_r,
204         -g => $bg_g,
205         -b => $bg_b,
206 );
207
208 my $background = SDL::Rect->new(
209         -width  => $width,
210         -height => $height,
211 );
212
213 my $pos = SDL::Rect->new(
214         -width  => 16,
215         -height => 16,
216         -x      => 0,
217         -y      => 240,
218 );
219
220 my $walker = Walker->new(qw(
221 END_HERE
222
223 $demo_source .= join( ' ', @img_files ) . "));" . <<'END_HERE';
224
225 for my $x ( $start_x .. $end_x )
226 {
227         draw_background( $app, $background, $bg_color );
228         $pos->x( $x );
229         draw_walker( $walker, $app, $pos );
230         $app->update( $background );
231         select( undef, undef, undef, $sleep_msec );
232 }
233
234 # you'll want to remove this
235 sleep 2;
236
237 sub draw_background
238 {
239         my ($app, $background, $bg_color) = @_;
240         $app->fill( $background, $bg_color );
241 }
242
243 sub draw_walker
244 {
245         my ($walker, $app, $pos) = @_;
246         my $frame                = $walker->next_frame();
247         my $frame_rect           = $walker->frame_rect();
248         $frame->blit( $frame_rect, $app, $pos );
249 }
250 END_HERE
251
252         Pod::ToDemo::write_demo( $filename, "#$^X\n$demo_source" );
253         write_files( $imagebase );
254 };
255                 
256 sub write_files
257 {
258         my $imagebase = shift;
259
260         for my $image (qw( left center right ))
261         {
262                 my $file = join('', map { chr( hex( $_ ) ) } @{ $images{ $image } });
263                 write_file( $imagebase . "_$image" . '.gif', $file );
264         }
265 }
266
267 sub write_file
268 {
269     my ($file, $contents) = @_;
270
271         die "Cowardly refusing to overwrite '$file'\n" if -e $file;
272         open my $out, '>', $file or die "Cannot write '$file': $!\n";
273         binmode $out;
274         print $out $contents;
275 }
276
277 __END__
278
279 =head1 NAME
280
281 SDL::Tutorial::Images
282
283 =head1 SYNOPSIS
284
285         # to read this tutorial
286         $ perldoc SDL::Tutorial::Images
287
288         # to create a demo animation program based on this tutorial
289         $ perl -MSDL::Tutorial::Images=sdl_images.pl -e 1
290
291 =head1 ANIMATING IMAGES
292
293 Since you're already familiar with the concepts behind animation, it's time to
294 learn how to work with images.  As usual, the important point is that computer animation is just I<simulating> motion by painting several slightly different frames to the screen every second.
295
296 There are two ways to vary an image on screen.  One is to change its
297 coordinates so it's at a slightly different position.  This is very easy to do;
298 it's just like animating a rectangle.  The other way is to change the image
299 itself so it's slightly different.  This is a little more difficult, as you'll
300 need to draw the alternate image beforehand somehow.
301
302 =head2 Loading Images
303
304 As usual, start with an L<SDL::App> object representing the image window.  Then
305 preload the image file.  This is easy; just pass the C<name> parameter to the
306 L<SDL::Surface> constructor:
307
308         use SDL::Surface;
309
310         my $frame = SDL::Surface->new( -name => 'frame1.png' );
311
312 B<Note:> you'll need to have compiled SDL Perl (and probably SDL) to support
313 JPEG and PNG files for this to work.
314
315 That's it; now you have an SDL::Surface object containing the image.  You can
316 use the C<height()>, C<width()>, and C<bpp()> methods to retrieve its height,
317 width, and bits per pixel, if you need them.
318
319 =head2 Displaying Images
320
321 Drawing an image onto the screen requires blitting it from one surface to
322 another.  (Remember, "blitting" means copying bits in memory.)  The C<blit()>
323 method of SDL::Surface objects comes in handy.  Its arguments are a little odd,
324 though.  Assuming C<$app> is the SDL::App object, as usual:
325
326         use SDL::Rect;
327
328         my $frame_rect = SDL::Rect->new(
329                 -height => $frame->height(),
330                 -width  => $frame->width(),
331                 -x      => 0,
332                 -y      => 0,
333         );
334
335         my $dest_rect  = SDL::Rect->new(
336                 -height => $frame->height(),
337                 -width  => $frame->width(),
338                 -x      => 0,
339                 -y      => 0,
340         );
341
342         $frame->blit( $frame_rect, $app, $dest_rect );
343         $app->update( $dest_rect );
344
345 Here we have two L<SDL::Rect> objects which represent rectangular regions of a
346 Surface.  C<$frame_rect> represents the entire area of C<$frame>, while
347 C<$dest_rect> represents the area of the main window in which to blit the
348 frame.  This may be clearer with more descriptive variable names:
349
350         $source_surface->blit(
351                 $area_of_source_to_blit,
352                 $destination_surface,
353                 $destination_area
354         );
355
356 As usual, call C<update()> on C<$app> to see the change.
357
358 Requiring the source and destination Rect objects may seem tedious in this
359 simple example, but it's highly useful for copying only part of surface to part
360 of another.  For example, animating this image is a matter of changing the C<x>
361 and C<y> coordinates of C<$dest_rect>:
362
363         for my $x ( 1 .. 100 )
364         {
365                 $dest_rect->x( $x );
366                 $frame->blit( $frame_rect, $app, $dest_rect );
367                 $app->update( $dest_rect );
368         }
369
370 Of course, you'll have to redraw all or part of the screen to avoid artifacts,
371 as discussed in the previous tutorial.
372
373 =head2 Multi-Image Animation
374
375 That covers moving a single image around the screen.  What if you want
376 something more?  For example, what if you want to animate a stick figure
377 walking?
378
379 You'll need several frames, just as in a flip-book.  Each frame should be slightly different than the one before it.  It's probably handy to encapsulate all of this in a C<Walker> class:
380
381         package Walker;
382
383         use SDL::Surface;
384
385         sub new
386         {
387                 my ($class, @images) = @_;
388                 my $self = [ map { SDL::Surface->new( -name => $_ ) } @images ];
389
390                 bless $self, $class;
391         }
392
393         sub next_frame
394         {
395                 my $self  = shift;
396                 my $frame = shift @$self;
397
398                 push @$self, $frame;
399                 return $frame;
400         }
401
402 To use this class, instantiate an object:
403
404         my $walker = Walker->new( 'frame1.png', 'frame2.png', 'frame3.png' );
405
406 Then call C<next_frame()> within the loop:
407
408         for my $x ( 1 .. 100 )
409         {
410                 my $frame = $walker->next_frame();
411
412                 $dest_rect->x( $x );
413                 $frame->blit( $frame_rect, $app, $dest_rect );
414                 $app->update( $dest_rect );
415         }
416
417 Again, the rest of the frame drawing is missing from this example so as not to
418 distract from this technique.  You'll probably want to abstract the undrawing
419 and redrawing into a separate subroutine so you don't have to worry about it
420 every time.
421
422 It'd be easy to make C<next_frame()> much smarter, selecting an image
423 appropriate to the direction of travel, using a bored animation when the
424 character is no longer moving, or adding other characteristics to the
425 character.  As you can see, the hard part of this technique is generating the
426 images beforehand.  That can add up to a tremendous amount of art and that's
427 one reason for the popularity of 3D models... but that's another tutorial much
428 further down the road.
429
430 More importantly, it's time to discuss how to make these animations run more
431 smoothly.  More on that next time.
432
433 =head1 SEE ALSO
434
435 =over 4
436
437 =item L<SDL::Tutorial>
438
439 basic SDL tutorial
440
441 =item L<SDL::Tutorial::Animation>
442
443 non-image animation
444
445 =back
446
447 =head1 AUTHOR
448
449 chromatic, E<lt>chromatic@wgz.orgE<gt>
450
451 Written for and maintained by the Perl SDL project, L<http://sdl.perl.org/>.
452
453 =head1 BUGS
454
455 No known bugs.
456
457 =head1 COPYRIGHT
458
459 Copyright (c) 2004, chromatic.  All rights reserved.  This module is
460 distributed under the same terms as Perl itself, in the hope that it is useful
461 but certainly under no guarantee.