Commit | Line | Data |
6e0d970b |
1 | <div class="pod"> |
2 | <!-- INDEX START --> |
3 | <h3 id="TOP">Index</h3> |
4 | |
5 | <ul><li><a href="#NAME">NAME</a></li> |
6 | <li><a href="#SYNOPSIS">SYNOPSIS</a></li> |
7 | <li><a href="#ANIMATING_IMAGES">ANIMATING IMAGES</a> |
8 | <ul><li><a href="#Loading_Images">Loading Images</a></li> |
9 | <li><a href="#Displaying_Images">Displaying Images</a></li> |
10 | <li><a href="#Multi_Image_Animation">Multi-Image Animation</a></li> |
11 | </ul> |
12 | </li> |
13 | <li><a href="#SEE_ALSO">SEE ALSO</a></li> |
14 | <li><a href="#AUTHOR">AUTHOR</a></li> |
15 | <li><a href="#BUGS">BUGS</a></li> |
16 | <li><a href="#COPYRIGHT">COPYRIGHT</a> |
17 | </li> |
18 | </ul><hr /> |
19 | <!-- INDEX END --> |
20 | |
21 | <h1 id="NAME">NAME</h1><p><a href="#TOP" class="toplink">Top</a></p> |
22 | <div id="NAME_CONTENT"> |
23 | <p>SDL::Tutorial::Images</p> |
24 | |
25 | </div> |
26 | <h1 id="SYNOPSIS">SYNOPSIS</h1><p><a href="#TOP" class="toplink">Top</a></p> |
27 | <div id="SYNOPSIS_CONTENT"> |
28 | <pre> # to read this tutorial |
29 | $ perldoc SDL::Tutorial::Images |
30 | |
31 | # to create a demo animation program based on this tutorial |
32 | $ perl -MSDL::Tutorial::Images=sdl_images.pl -e 1 |
33 | |
34 | </pre> |
35 | |
36 | </div> |
37 | <h1 id="ANIMATING_IMAGES">ANIMATING IMAGES</h1><p><a href="#TOP" class="toplink">Top</a></p> |
38 | <div id="ANIMATING_IMAGES_CONTENT"> |
39 | <p>Since you're already familiar with the concepts behind animation, it's time to |
40 | learn how to work with images. As usual, the important point is that computer animation is just <i>simulating</i> motion by painting several slightly different frames to the screen every second.</p> |
41 | <p>There are two ways to vary an image on screen. One is to change its |
42 | coordinates so it's at a slightly different position. This is very easy to do; |
43 | it's just like animating a rectangle. The other way is to change the image |
44 | itself so it's slightly different. This is a little more difficult, as you'll |
45 | need to draw the alternate image beforehand somehow.</p> |
46 | |
47 | </div> |
48 | <h2 id="Loading_Images">Loading Images</h2> |
49 | <div id="Loading_Images_CONTENT"> |
50 | <p>As usual, start with an <cite>SDL::App</cite> object representing the image window. Then |
51 | preload the image file. This is easy; just pass the <code>name</code> parameter to the |
52 | <cite>SDL::Surface</cite> constructor:</p> |
53 | <p> </p> |
54 | <pre> use SDL::Surface; |
55 | |
56 | my $frame = SDL::Surface->new( -name => 'frame1.png' ); |
57 | |
58 | </pre> |
59 | <p> </p> |
60 | <p><strong>Note:</strong> you'll need to have compiled SDL Perl (and probably SDL) to support |
61 | JPEG and PNG files for this to work.</p> |
62 | <p>That's it; now you have an SDL::Surface object containing the image. You can |
63 | use the <code>height()</code>, <code>width()</code>, and <code>bpp()</code> methods to retrieve its height, |
64 | width, and bits per pixel, if you need them.</p> |
65 | |
66 | </div> |
67 | <h2 id="Displaying_Images">Displaying Images</h2> |
68 | <div id="Displaying_Images_CONTENT"> |
69 | <p>Drawing an image onto the screen requires blitting it from one surface to |
70 | another. (Remember, "blitting" means copying bits in memory.) The <code>blit()</code> |
71 | method of SDL::Surface objects comes in handy. Its arguments are a little odd, |
72 | though. Assuming <code>$app</code> is the SDL::App object, as usual:</p> |
73 | <p> </p> |
74 | <pre> use SDL::Rect; |
75 | |
76 | my $frame_rect = SDL::Rect->new( |
77 | -height => $frame->height(), |
78 | -width => $frame->width(), |
79 | -x => 0, |
80 | -y => 0, |
81 | ); |
82 | |
83 | my $dest_rect = SDL::Rect->new( |
84 | -height => $frame->height(), |
85 | -width => $frame->width(), |
86 | -x => 0, |
87 | -y => 0, |
88 | ); |
89 | |
90 | $frame->blit( $frame_rect, $app, $dest_rect ); |
91 | $app->update( $dest_rect ); |
92 | |
93 | </pre> |
94 | <p> </p> |
95 | <p>Here we have two <cite>SDL::Rect</cite> objects which represent rectangular regions of a |
96 | Surface. <code>$frame_rect</code> represents the entire area of <code>$frame</code>, while |
97 | <code>$dest_rect</code> represents the area of the main window in which to blit the |
98 | frame. This may be clearer with more descriptive variable names:</p> |
99 | <p> </p> |
100 | <pre> $source_surface->blit( |
101 | $area_of_source_to_blit, |
102 | $destination_surface, |
103 | $destination_area |
104 | ); |
105 | |
106 | </pre> |
107 | <p> </p> |
108 | <p>As usual, call <code>update()</code> on <code>$app</code> to see the change.</p> |
109 | <p>Requiring the source and destination Rect objects may seem tedious in this |
110 | simple example, but it's highly useful for copying only part of surface to part |
111 | of another. For example, animating this image is a matter of changing the <code>x</code> |
112 | and <code>y</code> coordinates of <code>$dest_rect</code>:</p> |
113 | <p> </p> |
114 | <pre> for my $x ( 1 .. 100 ) |
115 | { |
116 | $dest_rect->x( $x ); |
117 | $frame->blit( $frame_rect, $app, $dest_rect ); |
118 | $app->update( $dest_rect ); |
119 | } |
120 | |
121 | </pre> |
122 | <p> </p> |
123 | <p>Of course, you'll have to redraw all or part of the screen to avoid artifacts, |
124 | as discussed in the previous tutorial.</p> |
125 | |
126 | </div> |
127 | <h2 id="Multi_Image_Animation">Multi-Image Animation</h2> |
128 | <div id="Multi_Image_Animation_CONTENT"> |
129 | <p>That covers moving a single image around the screen. What if you want |
130 | something more? For example, what if you want to animate a stick figure |
131 | walking?</p> |
132 | <p>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 <code>Walker</code> class:</p> |
133 | <p> </p> |
134 | <pre> package Walker; |
135 | |
136 | use SDL::Surface; |
137 | |
138 | sub new |
139 | { |
140 | my ($class, @images) = @_; |
141 | my $self = [ map { SDL::Surface->new( -name => $_ ) } @images ]; |
142 | |
143 | bless $self, $class; |
144 | } |
145 | |
146 | sub next_frame |
147 | { |
148 | my $self = shift; |
149 | my $frame = shift @$self; |
150 | |
151 | push @$self, $frame; |
152 | return $frame; |
153 | } |
154 | |
155 | </pre> |
156 | <p> </p> |
157 | <p>To use this class, instantiate an object:</p> |
158 | <p> </p> |
159 | <pre> my $walker = Walker->new( 'frame1.png', 'frame2.png', 'frame3.png' ); |
160 | |
161 | </pre> |
162 | <p> </p> |
163 | <p>Then call <code>next_frame()</code> within the loop:</p> |
164 | <p> </p> |
165 | <pre> for my $x ( 1 .. 100 ) |
166 | { |
167 | my $frame = $walker->next_frame(); |
168 | |
169 | $dest_rect->x( $x ); |
170 | $frame->blit( $frame_rect, $app, $dest_rect ); |
171 | $app->update( $dest_rect ); |
172 | } |
173 | |
174 | </pre> |
175 | <p> </p> |
176 | <p>Again, the rest of the frame drawing is missing from this example so as not to |
177 | distract from this technique. You'll probably want to abstract the undrawing |
178 | and redrawing into a separate subroutine so you don't have to worry about it |
179 | every time.</p> |
180 | <p>It'd be easy to make <code>next_frame()</code> much smarter, selecting an image |
181 | appropriate to the direction of travel, using a bored animation when the |
182 | character is no longer moving, or adding other characteristics to the |
183 | character. As you can see, the hard part of this technique is generating the |
184 | images beforehand. That can add up to a tremendous amount of art and that's |
185 | one reason for the popularity of 3D models... but that's another tutorial much |
186 | further down the road.</p> |
187 | <p>More importantly, it's time to discuss how to make these animations run more |
188 | smoothly. More on that next time.</p> |
189 | |
190 | </div> |
191 | <h1 id="SEE_ALSO">SEE ALSO</h1><p><a href="#TOP" class="toplink">Top</a></p> |
192 | <div id="SEE_ALSO_CONTENT"> |
193 | <dl> |
194 | <dt><cite>SDL::Tutorial</cite></dt> |
195 | <dd> |
196 | <p>basic SDL tutorial</p> |
197 | </dd> |
198 | <dt><cite>SDL::Tutorial::Animation</cite></dt> |
199 | <dd> |
200 | <p>non-image animation</p> |
201 | </dd> |
202 | </dl> |
203 | |
204 | </div> |
205 | <h1 id="AUTHOR">AUTHOR</h1><p><a href="#TOP" class="toplink">Top</a></p> |
206 | <div id="AUTHOR_CONTENT"> |
207 | <p>chromatic, <chromatic@wgz.org></p> |
208 | <p>Written for and maintained by the Perl SDL project, <a href="http://sdl.perl.org/">http://sdl.perl.org/</a>.</p> |
209 | |
210 | </div> |
211 | <h1 id="BUGS">BUGS</h1><p><a href="#TOP" class="toplink">Top</a></p> |
212 | <div id="BUGS_CONTENT"> |
213 | <p>No known bugs.</p> |
214 | |
215 | </div> |
216 | <h1 id="COPYRIGHT">COPYRIGHT</h1><p><a href="#TOP" class="toplink">Top</a></p> |
217 | <div id="COPYRIGHT_CONTENT"> |
218 | <p>Copyright (c) 2004, chromatic. All rights reserved. This module is |
219 | distributed under the same terms as Perl itself, in the hope that it is useful |
220 | but certainly under no guarantee. |
221 | </p> |
222 | |
223 | </div> |
224 | </div> |