shotgunefx has asked for the wisdom of the Perl Monks concerning the following question:

I've made a ton of progress on my Perl/SDL digital dashboard this week. (For anyone who cares, there are pics and video on my blog).

In some ways SDL is a godsend, in others maddening. I suppose a lot of it comes from the lack of documentation. I've also found a lot of bugs. As soon as I figure out why the newest releases won't install, I hope to start getting active in it's development. (At least in the bug reporting aspect).

So my animation manager works perfectly and fast. I decide to write a snippet to post here ( a subset of what I've done) that loads animated gifs. Adjusts the offsets if the image frame is smaller than the image, gathers up the timing info. And hours later, I give up (for now). I keep running into oddity after oddity. What I thought would be a 5 minutes snippet has taken a good six hours.

Anyway, here's my question. I know that an SDL::Rect is a surface in a sense. But apparently, I don't understand it's behavior like I thought it did.

If you were to look at the docs for SDL::Surface, you get the impression that the rectangles only server to denote locations within surfaces. Take the following example.
my $s_rect = SDL::Rect->new(-x => 0, -y => 0, -width => 64, -height => +64); # Source my $d_rect = SDL::Rect->new(-x => 0, -y => 0, -width => 64, -height => +64); # Destination $sprite->blit($s_rect,$app,$d_rect);
Now if I were to use the same rectangle for the source and destination
my $s_rect = SDL::Rect->new(-x => 0, -y => 0, -width => 64, -height => +64); # Source my $d_rect = SDL::Rect->new(-x => 0, -y => 0, -width => 64, -height => +64); # Destination $sprite->blit($s_rect,$app,$s_rect);
I'd expect from the documentation that it would work the same way, but apparently it doesn't. It appears to be blitting on itself.

So when you blit, is the copying following along the following lines using the rectangles for temporary buffers?

surface > src_rect > dst_rect > app

If someone could shed some light on this, I'd really appreciate it.

-Lee

perl digital dash (in progress)

Replies are listed 'Best First'.
Re: SDL Surfaces and Rectangles
by PodMaster (Abbot) on Jan 31, 2006 at 11:08 UTC
    I'd expect from the documentation that it would work the same way, but apparently it doesn't. It appears to be blitting on itself.
    Works fine for me :/ as I expect it should (SDL_Rect -- Defines a rectangular area)
    Perl v5.8.4 WinXP
    SDL 2.1.0 built against libsdl 1.2.7.0

    update: to clarify, in my tests both behave the same.
    SDL_BlitSurface

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      There is something I'm missing here. I did another example and it does indeed work. Here's a cut down version that illustrates the problem.

      There is an image here to test with. Note that this GIF image was saved with cropping. So the frame will jitter. My orginal code dealt with this but to keep it to the point, I've hacked it out.

      The load_sprites function if not passed a -tmpfile parameter, will try and create a temporary image at
      "/tmp/sprite-im.gif"

      What happens for me is that with the src and dst rectangles the same, it will run through the animation once and only once. You'll just keep seeing the what appears to be the last frame. If you change the blit to use the seperate but identical dimensionally $sprite->{-dst_rect}, it works as expected.

      I'm really at a loss here.
      #!/usr/bin/perl use strict; use warnings; use Image::Magick; use SDL; use SDL::App; use SDL::Surface; use SDL::Color; use SDL::Rect; use Data::Dumper; my $app = SDL::App->new( -title=>"Sprite Test", -width =>100, -height => 100, -depth => 24, ); my $sprite = load_sprites(-file=>"testlight-a.gif"); my $app_rect = SDL::Rect->new( -height => 480, -width => 600, -x => 0, + -y => 0 ) or die "Couldn't create SDL::Rect !"; for (0..100){ for my $im ( @{ $sprite->{-frames} } ){ $im->blit( $sprite->{-src_rect} ,$app, $sprite->{-src_rect}); #s +rc = src = not work. #$im->blit( $sprite->{-src_rect} ,$app, $sprite->{-dst_rect}); # +src = dst = works $app->update($sprite->{-src_rect}); $app->delay(200); } } #------------------------------------------------------------- # # Oddities: # If Surface not initialized via graphic file, blits will not take. # Image::Magick->Write is succeeding but not returning count of images + written. sub load_sprites { my %args = ( -file => undef, -tmpfile => '/tmp/sprite-im.gif', @_, ); die "File [$args{-file}] doesn't exist!" unless -e $args{-file}; my ($src_rect,$dst_rect, $magick, @frames, $x ); $magick = Image::Magick->new() or die "Couldn't create Image::Ma +gick object!: $!"; $magick->Read($args{-file}) ; my ($iw,$ih) = $magick->Get( qw /width height/) ; # Get the height + and width of image $src_rect = SDL::Rect->new( -height => $ih, -width => $iw, -x => 0 +, -y => 0 ) or die "Couldn't create SDL::Rect !"; $dst_rect = SDL::Rect->new( -height => $ih, -width => $iw, -x => 0 +, -y => 0 ) or die "Couldn't create SDL::Rect !"; foreach my $im (@$magick) { my ($w,$h,$ws,$hs); # Width, height, start of bounding box, # don't know if this returns valid info fo +r all formats. if ($im->Get( qw /width height bounding-box/ )=~m/^(\d+)x(\d+) +\+(\d+)\+(\d)/){ ($w,$h,$ws,$hs) = ($1,$2,$3,$4); warn join(", ",($w,$h,$ws,$hs)); }else{ die "Error retrieving image properties!"; } # For newer perls, could probably skip the tmp file altogther +and read/write a scalar $im->Write( filename => $args{-tmpfile}); # Isn't returning the count. According to the docs, should be +number of images written so can't error check. push @frames, SDL::Surface->new( -name => $args{-tmpfile}) ; } return { -frames=>\@frames, -x=>0, -y=>0, -src_rect=>$src_rect,-ds +t_rect=>$dst_rect}; }


      -Lee

      perl digital dash (in progress)
      Looking at your link again, it does explain it.

      The final blit rectangle is saved in dstrect after all clipping is performed (srcrect is not modified)

      That's a huge gotcha that I've not come across in any of the SDL Perl documents I've found.

      Thanks++


      -Lee

      perl digital dash (in progress)
        No prob. This is what bothers me with SDL and Tk. They bother to include documentation, but its horribly incomplete. Whereas wxPerl forces you to always refer to the external wxWidgets documentation (granted its annotated).

        Hope you send in a bug report :)

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

Re: SDL Surfaces and Rectangles
by shotgunefx (Parson) on Feb 01, 2006 at 14:53 UTC
    A little update. I finally managed to get the newest snapshot of SDL running after some "Build" problems.

    Still having the same issues, but I believe it's image dependant. The image frames do have some transparency.

    I believe this is where the bug lies. Having a hard time cutting it down to isolate what exactly is causing the problems. Because transparent pixels or not, once you run over with the intial frames, they are not overwriting the last frame even though all frames contain non-transparent pixels.

    Also, anyone care to comment why there are two versions of the SDL Perl modules? (2.X, 1.2.X)

    It would be nice to know what the differences are. So far, the only thing I can tell are that constants have been moved to SDL::Constants and SDL::Console has disappeared.


    -Lee

    perl digital dash (in progress)