oracular (3) SDL::Tutorial::Animation.3pm.gz

Provided by: libsdl-perl_2.548-5build1_amd64 bug

NAME

       SDL::Tutorial::Animation - Creating animations with SDL

   CATEGORY
       Tutorials

SYNOPSIS

               # to read this tutorial
               $ perldoc SDL::Tutorial::Animation

               # to create a demo animation program based on this tutorial
               $ perl -MSDL::Tutorial::Animation=sdl_anim.pl -e 1

ANIMATING A RECTANGLE

       Now that you can display a rectangle on the screen, the next step is to animate 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).

       Okay, it's not that difficult.

       There is one small difficulty to address, however.  Once you blit one surface onto another, the
       destination is changed permanently.  There's no concept of layers here unless you write it yourself.  If
       you fail to take this into account (and just about everyone does at first), you'll end up with blurry
       graphics moving around on the screen.

       There are two approaches to solve this problem, redrawing the screen on every frame and saving and
       restoring the background for every object drawn.

   Redrawing the Screen
       Since you have to draw the screen in the right order once to start with it's pretty easy to make this
       into a loop and redraw things in the right order for every frame.  Given a SDLx::App object $app, a
       SDL::Rect $rect, and a SDL::Color $color, you only have to create a new SDL::Rect $bg, representing the
       whole of the background surface and a new mapped color $bg_color, representing the background color.  The
       colors need to be mapped to the format of the current display. This is done by SDL::Video::map_RGB.

       my $color = SDL::Video::map_RGB (       $app->format,       $rect_r,       $rect_g,       $rect_b, );

       my $bg_color = SDL::Video::map_RGB (       $app->format,
             $bg_r,       $bg_g,       $bg_b, );

       You can write a draw_frame() function as follows:

               sub draw_frame
               {
                       my ($app, %args) = @_;

                       SDL::Video::fill_rect($app,  $args{bg},   $args{bg_color}   );
                       SDL::Video::fill_rect($app, $args{rect}, $args{rect_color} );
                       SDL::Video::update_rects($app, $args{bg} );
               }

       Since you can change the "x" and "y" coordinates of a rect with the x() and y() methods, you can move a
       rectangle across the screen with a loop like this:

               for my $x (0 .. 640)
               {
                       $rect->x( $x );
                       draw_frame( $app,
                               bg   => $bg,   bg_color   => $bg_color,
                               rect => $rect, rect_color => $color,
                       );
               }

       If $rect's starting y position is 190 and its height and width are 100, the rectangle (er, square) will
       move across the middle of the screen.

       Provided you can keep track of the proper order in which to redraw rectangles and provided you don't need
       the optimal speed necessary (since blitting every object takes more work than just blitting the portions
       you need), this works quite well.

   Undrawing the Updated Rectangle
       If you need more speed or want to make a different complexity tradeoff, you can take a snapshot of the
       destination rectangle before you blit onto it.  That way, when you need to redraw, you can blit the old
       snapshot back before blitting to the new position.

       Note:  I have no idea how this will work in the face of alpha blending, which, admittedly, I haven't even
       mentioned yet.  If you don't know what this means, forget it.  If you do know what this means and know
       why I'm waving my hands here, feel free to explain what should and what does happen and why.  :)

       With this technique, the frame-drawing subroutine has to be a little more complicated.  Instead of the
       background rect, it needs a rect for the previous position.  It also needs to do two updates (or must
       perform some scary math to figure out the rectangle of the correct size to update().  No thanks!).

               sub undraw_redraw_rect
               {
                       my ($app, %args) = @_;

                       SDL::Video::fill_rect($app, $args{old_rect}, $args{bg_color}   );
                       SDL::Video::fill_rect($app,  $args{rect},     $args{rect_color} );
                       SDL::Video::update_rects($app, $args{old_rect} );
                       SDL::Video::update_rects($app, $args{rect} );
               }

       We'll need to create a new SDL::Rect, $old_rect, that is a duplicate of $rect, at the same position at
       first.  You should already know how to do this.

       As before, the loop to call undraw_redraw_rect() would look something like:

               for my $x (0 .. 640)
               {
                       $rect->x( $x );

                       undraw_redraw_rect( $app,
                               rect       => $rect,  old_rect => $old_rect,
                               rect_color => $color, bg_color => $bgcolor,
                       );

                       $old_rect->x( $x );
               }

       If you run this code, you'll probably notice that it's tremendously faster than the previous version.  It
       may be too fast, where the alternate technique was just fast enough.  There are a couple of good ways to
       set a fixed animation speed regardless of the speed of the processor and graphics hardware (provided
       they're good enough, which is increasingly often the case), and we'll get to them soon.

SEE ALSO

       SDL::Tutorial::Drawing
           basic drawing with SDL Perl

       SDL::Tutorial::Images
           animating images

AUTHOR

       chromatic, <chromatic@wgz.org>

       Written for and maintained by the Perl SDL project, <http://sdl.perl.org/>.  See "AUTHORS" in SDL.

BUGS

       No known bugs.

       Copyright (c) 2003 - 2004, chromatic.  All rights reserved.  This module is distributed under the same
       terms as Perl itself, in the hope that it is useful but certainly under no guarantee.