latest blog
[sdlgit/SDL-Site.git] / pages / SDL-Tutorial-Animation.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_A_RECTANGLE">ANIMATING A RECTANGLE</a>
8 <ul><li><a href="#Redrawing_the_Screen">Redrawing the Screen</a></li>
9 <li><a href="#Undrawing_the_Updated_Rectangle">Undrawing the Updated Rectangle</a></li>
10 </ul>
11 </li>
12 <li><a href="#SEE_ALSO">SEE ALSO</a></li>
13 <li><a href="#AUTHOR">AUTHOR</a></li>
14 <li><a href="#BUGS">BUGS</a></li>
15 <li><a href="#COPYRIGHT">COPYRIGHT</a>
16 </li>
17 </ul><hr />
18 <!-- INDEX END -->
19
20 <h1 id="NAME">NAME</h1><p><a href="#TOP" class="toplink">Top</a></p>
21 <div id="NAME_CONTENT">
22 <p>SDL::Tutorial::Animation</p>
23
24 </div>
25 <h1 id="SYNOPSIS">SYNOPSIS</h1><p><a href="#TOP" class="toplink">Top</a></p>
26 <div id="SYNOPSIS_CONTENT">
27 <pre>   # to read this tutorial
28         $ perldoc SDL::Tutorial::Animation
29
30         # to create a demo animation program based on this tutorial
31         $ perl -MSDL::Tutorial::Animation=sdl_anim.pl -e 1
32
33 </pre>
34
35 </div>
36 <h1 id="ANIMATING_A_RECTANGLE">ANIMATING A RECTANGLE</h1><p><a href="#TOP" class="toplink">Top</a></p>
37 <div id="ANIMATING_A_RECTANGLE_CONTENT">
38 <p>Now that you can display a rectangle on the screen, the next step is to animate
39 that rectangle.  As with movies, there's no actual motion.  Computer animations are just very very fast slideshows.  The hard work is creating nearly identical images in every slide (or frame, in graphics terms).</p>
40 <p>Okay, it's not that difficult.</p>
41 <p>There is one small difficulty to address, however.  Once you blit one surface
42 onto another, the destination is changed permanently.  There's no concept of
43 layers here unless you write it yourself.  If you fail to take this into
44 account (and just about everyone does at first), you'll end up with blurry
45 graphics moving around on the screen.</p>
46 <p>There are two approaches to solve this problem, redrawing the screen on every
47 frame and saving and restoring the background for every object drawn.</p>
48
49 </div>
50 <h2 id="Redrawing_the_Screen">Redrawing the Screen</h2>
51 <div id="Redrawing_the_Screen_CONTENT">
52 <p>Since you have to draw the screen in the right order once to start with it's
53 pretty easy to make this into a loop and redraw things in the right order for
54 every frame.  Given a <cite>SDL::App</cite> object <code>$app</code>, a <cite>SDL::Rect</cite> <code>$rect</code>, and
55 a <cite>SDL::Color</cite> <code>$color</code>, you only have to create a new SDL::Rect <code>$bg</code>,
56 representing the whole of the background surface and a new SDL::Color
57 <code>$bg_color</code>, representing the background color.  You can write a
58 <code>draw_frame()</code> function as follows:</p>
59 <p>&nbsp;</p>
60 <pre>   sub draw_frame
61         {
62                 my ($app, %args) = @_;
63
64                 $app-&gt;fill( $args{ bg }, $args{ bg_color } );
65                 $app-&gt;fill( $args{rect}, $args{rect_color} );
66                 $app-&gt;update( $args{bg} );
67         }
68
69 </pre>
70 <p>&nbsp;</p>
71 <p>Since you can change the <code>x</code> and <code>y</code> coordinates of a rect with the <code>x()</code>
72 and <code>y()</code> methods, you can move a rectangle across the screen with a loop like
73 this:</p>
74 <p>&nbsp;</p>
75 <pre>   for my $x (0 .. 640)
76         {
77                 $rect-&gt;x( $x );
78                 draw_frame( $app,
79                         bg   =&gt; $bg,   bg_color   =&gt; $bg_color,
80                         rect =&gt; $rect, rect_color =&gt; $color,
81                 );
82         }
83
84 </pre>
85 <p>&nbsp;</p>
86 <p>If <code>$rect</code>'s starting y position is 190 and its height and width are 100, the
87 rectangle (er, square) will move across the middle of the screen.</p>
88 <p>Provided you can keep track of the proper order in which to redraw rectangles
89 and provided you don't need the optimal speed necessary (since blitting every
90 object takes more work than just blitting the portions you need), this works
91 quite well.</p>
92
93 </div>
94 <h2 id="Undrawing_the_Updated_Rectangle">Undrawing the Updated Rectangle</h2>
95 <div id="Undrawing_the_Updated_Rectangle_CONT">
96 <p>If you need more speed or want to make a different complexity tradeoff, you can
97 take a snapshot of the destination rectangle <i>before</i> you blit onto it.  That
98 way, when you need to redraw, you can blit the old snapshot back before
99 blitting to the new position.</p>
100 <p><strong>Note:</strong>  I have no idea how this will work in the face of alpha blending,
101 which, admittedly, I haven't even mentioned yet.  If you don't know what this
102 means, forget it.  If you do know what this means and know why I'm waving my
103 hands here, feel free to explain what should and what does happen and why.  :)</p>
104 <p>With this technique, the frame-drawing subroutine has to be a little more
105 complicated.  Instead of the background rect, it needs a rect for the previous
106 position.  It also needs to do two updates (or must perform some scary math to
107 figure out the rectangle of the correct size to <code>update()</code>.  No thanks!).</p>
108 <p>&nbsp;</p>
109 <pre>   sub undraw_redraw_rect
110         {
111                 my ($app, %args) = @_;
112
113                 $app-&gt;fill(   $args{old_rect}, $args{bg_color}   );
114                 $app-&gt;fill(   $args{rect],     $args{rect_color} );
115                 $app-&gt;update( $args{old_rect}, $args{rect}       );
116         }
117
118 </pre>
119 <p>&nbsp;</p>
120 <p>We'll need to create a new SDL::Rect, <code>$old_rect</code>, that is a duplicate of
121 <code>$rect</code>, at the same position at first.  You should already know how to do
122 this.</p>
123 <p>As before, the loop to call <code>undraw_redraw_rect()</code> would look something like:</p>
124 <p>&nbsp;</p>
125 <pre>   for my $x (0 .. 640)
126         {
127                 $rect-&gt;x( $x );
128
129                 undraw_redraw_rect( $app,
130                         rect       =&gt; $rect,  old_rect =&gt; $old_rect,
131                         rect_color =&gt; $color, bg_color =&gt; $bgcolor,
132                 );
133
134                 $old_rect-&gt;x( $x );
135         }
136
137 </pre>
138 <p>&nbsp;</p>
139 <p>If you run this code, you'll probably notice that it's tremendously faster than
140 the previous version.  It may be too fast, where the alternate technique was
141 just fast enough.  There are a couple of good ways to set a fixed animation
142 speed regardless of the speed of the processor and graphics hardware (provided
143 they're good enough, which is increasingly often the case), and we'll get to
144 them soon.</p>
145
146 </div>
147 <h1 id="SEE_ALSO">SEE ALSO</h1><p><a href="#TOP" class="toplink">Top</a></p>
148 <div id="SEE_ALSO_CONTENT">
149 <dl>
150         <dt><cite>SDL::Tutorial::Drawing</cite></dt>
151         <dd>
152                 <p>basic drawing with SDL Perl</p>
153         </dd>
154         <dt><cite>SDL::Tutorial::Images</cite></dt>
155         <dd>
156                 <p>animating images</p>
157         </dd>
158 </dl>
159
160 </div>
161 <h1 id="AUTHOR">AUTHOR</h1><p><a href="#TOP" class="toplink">Top</a></p>
162 <div id="AUTHOR_CONTENT">
163 <p>chromatic, &lt;chromatic@wgz.org&gt;</p>
164 <p>Written for and maintained by the Perl SDL project, <a href="http://sdl.perl.org/">http://sdl.perl.org/</a>.</p>
165
166 </div>
167 <h1 id="BUGS">BUGS</h1><p><a href="#TOP" class="toplink">Top</a></p>
168 <div id="BUGS_CONTENT">
169 <p>No known bugs.</p>
170
171 </div>
172 <h1 id="COPYRIGHT">COPYRIGHT</h1><p><a href="#TOP" class="toplink">Top</a></p>
173 <div id="COPYRIGHT_CONTENT">
174 <p>Copyright (c) 2003 - 2004, chromatic.  All rights reserved.  This module is
175 distributed under the same terms as Perl itself, in the hope that it is useful
176 but certainly under no guarantee.
177 </p>
178
179 </div>
180 </div>