Added fake version becuase pause won't let me upload :(
[sdlgit/SDL_perl.git] / lib / SDL / Tutorial / Animation.pm
CommitLineData
bfd90409 1#!/usr/bin/env perl
2#
3# Animation.pm
4#
5# Copyright (C) 2005 David J. Goehrig <dgoehrig@cpan.org>
6#
7# ------------------------------------------------------------------------------
8#
9# This library is free software; you can redistribute it and/or
10# modify it under the terms of the GNU Lesser General Public
11# License as published by the Free Software Foundation; either
12# version 2.1 of the License, or (at your option) any later version.
13#
14# This library is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# Lesser General Public License for more details.
18#
19# You should have received a copy of the GNU Lesser General Public
20# License along with this library; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22#
23# ------------------------------------------------------------------------------
24#
25# Please feel free to send questions, suggestions or improvements to:
26#
27# David J. Goehrig
28# dgoehrig@cpan.org
29#
30
31package SDL::Tutorial::Animation;
32
33use strict;
87a6d0dc 34use warnings;
35
bfd90409 36use SDL;
37use SDL::App;
38use SDL::Rect;
39use SDL::Color;
40
41# change these values as necessary
42my $title = 'My SDL Animation';
43my ($width, $height, $depth) = ( 640, 480, 16 );
44my ($bg_r, $bg_g, $bg_b) = ( 0x00, 0x00, 0x00 );
45my ($rect_r, $rect_g, $rect_b) = ( 0x00, 0x00, 0xff );
46my ($rect_width, $rect_height, $rect_y) = ( 100, 100, 190 );
47
48my $app = SDL::App->new(
49 -width => $width,
50 -height => $height,
51 -depth => $depth,
52);
53
54my $color = SDL::Color->new(
55 -r => $rect_r,
56 -g => $rect_g,
57 -b => $rect_b,
58);
59
60my $bg_color = SDL::Color->new(
61 -r => $bg_r,
62 -g => $bg_g,
63 -b => $bg_b,
64);
65
66my $background = SDL::Rect->new(
67 -width => $width,
68 -height => $height,
69);
70
71my $rect = create_rect();
72
73# your code here, perhaps
74for my $x (0 .. 640)
75{
76 $rect->x( $x );
77 draw_frame( $app,
78 bg => $background, bg_color => $bg_color,
79 rect => $rect, rect_color => $color,
80 );
81}
82
83# remove this line
84sleep 2;
85
86# XXX - if you know why I need to create a new rect here, please tell me!
87$rect = create_rect();
88my $old_rect = create_rect();
89
90# your code also here, perhaps
91for my $x (0 .. 640)
92{
93 $rect->x( $x );
94 draw_undraw_rect( $app,
95 rect => $rect, old_rect => $old_rect,
96 rect_color => $color, bg_color => $bg_color,
97 );
98 $old_rect->x( $x );
99}
100
101# your code almost certainly follows; remove this line
102sleep 2;
103
104sub create_rect
105{
106 return SDL::Rect->new(
107 -height => $rect_height,
108 -width => $rect_width,
109 -x => 0,
110 -y => $rect_y,
111 );
112}
113
114sub draw_frame
115{
116 my ($app, %args) = @_;
117
118 $app->fill( $args{bg}, $args{bg_color} );
119 $app->fill( $args{rect}, $args{rect_color} );
120 $app->update( $args{bg} );
121}
122
123sub draw_undraw_rect
124{
125 my ($app, %args) = @_;
126
127 $app->fill( $args{old_rect}, $args{bg_color} );
128 $app->fill( $args{rect}, $args{rect_color} );
129 $app->update( $args{old_rect} );
130 $app->update( $args{rect} );
131}
bfd90409 132
1331;
134__END__
135
136=head1 NAME
137
138SDL::Tutorial::Animation
139
140=head1 SYNOPSIS
141
142 # to read this tutorial
143 $ perldoc SDL::Tutorial::Animation
144
145 # to create a demo animation program based on this tutorial
146 $ perl -MSDL::Tutorial::Animation=sdl_anim.pl -e 1
147
148=head1 ANIMATING A RECTANGLE
149
150Now that you can display a rectangle on the screen, the next step is to animate
151that 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).
152
153Okay, it's not that difficult.
154
155There is one small difficulty to address, however. Once you blit one surface
156onto another, the destination is changed permanently. There's no concept of
157layers here unless you write it yourself. If you fail to take this into
158account (and just about everyone does at first), you'll end up with blurry
159graphics moving around on the screen.
160
161There are two approaches to solve this problem, redrawing the screen on every
162frame and saving and restoring the background for every object drawn.
163
164=head2 Redrawing the Screen
165
166Since you have to draw the screen in the right order once to start with it's
167pretty easy to make this into a loop and redraw things in the right order for
168every frame. Given a L<SDL::App> object C<$app>, a L<SDL::Rect> C<$rect>, and
169a L<SDL::Color> C<$color>, you only have to create a new SDL::Rect C<$bg>,
170representing the whole of the background surface and a new SDL::Color
171C<$bg_color>, representing the background color. You can write a
172C<draw_frame()> function as follows:
173
174 sub draw_frame
175 {
176 my ($app, %args) = @_;
177
178 $app->fill( $args{ bg }, $args{ bg_color } );
179 $app->fill( $args{rect}, $args{rect_color} );
180 $app->update( $args{bg} );
181 }
182
183Since you can change the C<x> and C<y> coordinates of a rect with the C<x()>
184and C<y()> methods, you can move a rectangle across the screen with a loop like
185this:
186
187 for my $x (0 .. 640)
188 {
189 $rect->x( $x );
190 draw_frame( $app,
191 bg => $bg, bg_color => $bg_color,
192 rect => $rect, rect_color => $color,
193 );
194 }
195
196If C<$rect>'s starting y position is 190 and its height and width are 100, the
197rectangle (er, square) will move across the middle of the screen.
198
199Provided you can keep track of the proper order in which to redraw rectangles
200and provided you don't need the optimal speed necessary (since blitting every
201object takes more work than just blitting the portions you need), this works
202quite well.
203
204=head2 Undrawing the Updated Rectangle
205
206If you need more speed or want to make a different complexity tradeoff, you can
207take a snapshot of the destination rectangle I<before> you blit onto it. That
208way, when you need to redraw, you can blit the old snapshot back before
209blitting to the new position.
210
211B<Note:> I have no idea how this will work in the face of alpha blending,
212which, admittedly, I haven't even mentioned yet. If you don't know what this
213means, forget it. If you do know what this means and know why I'm waving my
214hands here, feel free to explain what should and what does happen and why. :)
215
216With this technique, the frame-drawing subroutine has to be a little more
217complicated. Instead of the background rect, it needs a rect for the previous
218position. It also needs to do two updates (or must perform some scary math to
219figure out the rectangle of the correct size to C<update()>. No thanks!).
220
221 sub undraw_redraw_rect
222 {
223 my ($app, %args) = @_;
224
225 $app->fill( $args{old_rect}, $args{bg_color} );
226 $app->fill( $args{rect], $args{rect_color} );
227 $app->update( $args{old_rect}, $args{rect} );
228 }
229
230We'll need to create a new SDL::Rect, C<$old_rect>, that is a duplicate of
231C<$rect>, at the same position at first. You should already know how to do
232this.
233
234As before, the loop to call C<undraw_redraw_rect()> would look something like:
235
236 for my $x (0 .. 640)
237 {
238 $rect->x( $x );
239
240 undraw_redraw_rect( $app,
241 rect => $rect, old_rect => $old_rect,
242 rect_color => $color, bg_color => $bgcolor,
243 );
244
245 $old_rect->x( $x );
246 }
247
248If you run this code, you'll probably notice that it's tremendously faster than
249the previous version. It may be too fast, where the alternate technique was
250just fast enough. There are a couple of good ways to set a fixed animation
251speed regardless of the speed of the processor and graphics hardware (provided
252they're good enough, which is increasingly often the case), and we'll get to
253them soon.
254
255=head1 SEE ALSO
256
257=over 4
258
259=item L<SDL::Tutorial::Drawing>
260
261basic drawing with SDL Perl
262
263=item L<SDL::Tutorial::Images>
264
265animating images
266
267=back
268
269=head1 AUTHOR
270
271chromatic, E<lt>chromatic@wgz.orgE<gt>
272
273Written for and maintained by the Perl SDL project, L<http://sdl.perl.org/>.
274
275=head1 BUGS
276
277No known bugs.
278
279=head1 COPYRIGHT
280
281Copyright (c) 2003 - 2004, chromatic. All rights reserved. This module is
282distributed under the same terms as Perl itself, in the hope that it is useful
283but certainly under no guarantee.