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