latest blog
[sdlgit/SDL-Site.git] / pages / SDL-Tutorial-Images.html-inc
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>&nbsp;</p>
54 <pre>   use SDL::Surface;
55
56         my $frame = SDL::Surface-&gt;new( -name =&gt; 'frame1.png' );
57
58 </pre>
59 <p>&nbsp;</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, &quot;blitting&quot; 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>&nbsp;</p>
74 <pre>   use SDL::Rect;
75
76         my $frame_rect = SDL::Rect-&gt;new(
77                 -height =&gt; $frame-&gt;height(),
78                 -width  =&gt; $frame-&gt;width(),
79                 -x      =&gt; 0,
80                 -y      =&gt; 0,
81         );
82
83         my $dest_rect  = SDL::Rect-&gt;new(
84                 -height =&gt; $frame-&gt;height(),
85                 -width  =&gt; $frame-&gt;width(),
86                 -x      =&gt; 0,
87                 -y      =&gt; 0,
88         );
89
90         $frame-&gt;blit( $frame_rect, $app, $dest_rect );
91         $app-&gt;update( $dest_rect );
92
93 </pre>
94 <p>&nbsp;</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>&nbsp;</p>
100 <pre>   $source_surface-&gt;blit(
101                 $area_of_source_to_blit,
102                 $destination_surface,
103                 $destination_area
104         );
105
106 </pre>
107 <p>&nbsp;</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>&nbsp;</p>
114 <pre>   for my $x ( 1 .. 100 )
115         {
116                 $dest_rect-&gt;x( $x );
117                 $frame-&gt;blit( $frame_rect, $app, $dest_rect );
118                 $app-&gt;update( $dest_rect );
119         }
120
121 </pre>
122 <p>&nbsp;</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>&nbsp;</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-&gt;new( -name =&gt; $_ ) } @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>&nbsp;</p>
157 <p>To use this class, instantiate an object:</p>
158 <p>&nbsp;</p>
159 <pre>   my $walker = Walker-&gt;new( 'frame1.png', 'frame2.png', 'frame3.png' );
160
161 </pre>
162 <p>&nbsp;</p>
163 <p>Then call <code>next_frame()</code> within the loop:</p>
164 <p>&nbsp;</p>
165 <pre>   for my $x ( 1 .. 100 )
166         {
167                 my $frame = $walker-&gt;next_frame();
168
169                 $dest_rect-&gt;x( $x );
170                 $frame-&gt;blit( $frame_rect, $app, $dest_rect );
171                 $app-&gt;update( $dest_rect );
172         }
173
174 </pre>
175 <p>&nbsp;</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, &lt;chromatic@wgz.org&gt;</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>