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