Commit | Line | Data |
8fde61e3 |
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. |