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