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

Morning all,

I have a working SDLx application implementing a 2D water drop effect (application start and initialize the display with a colored chessboard, then compute random water drops on it). This application is working fine (see the full code below) until I try to resize it (by clicking & dragging the bottom right of the window for example). As soon as I release the mouse button, the application ends without any message (window is closing, and I get back to the terminal prompt).

I have Strawberry Perl (5.14.4) installed (running on a Win10 laptop), and I wonder if my Perl/libraries installation is knowing issues, or if there is something wrong in my code.

Could someone test it and revert? Or provide a little help if something seems wrong? Thanks!

Here is the code:

#!/bin/perl use SDL; use SDL::Event; use SDL::GFX::Rotozoom; use SDL::Rect; use SDL::Video; use SDLx::App; use SDLx::Surface; use Math::Trig; use strict; use warnings; my $imgfile=''; my $scale=4; ######################### # Global initialization # Initialize buffers my $surface=load_surface(); my $surf_m=SDLx::Surface::pixel_array($surface); my $image=load_surface(); my $imge_m=SDLx::Surface::pixel_array($image); # Initialize application my $app=SDLx::App->new(t=>'Example',w=>$image->w*$scale,h=>$image->h*$ +scale,d=>32,resizeable=>'on'); # Initialize wavemaps my %wavemap=(wave=>0); foreach(0..(($image->h+1)*($image->w+1))){$wavemap{$wavemap{wave}}[$_] +=$wavemap{1-$wavemap{wave}}[$_]=0}; # Precompute maths my @displut; foreach(-256..256){$displut[$_+256]=int(tan(asin(sin(atan(int($_/4)))/ +4))*int($_/4)*15)}; # Add events $app->add_event_handler(\&on_event); $app->add_move_handler(\&on_move); $app->add_show_handler(\&on_show); # Start main loop $app->run; ######################### # Functions sub on_event{ my($event,$app)=@_; $app->stop if $event->type==SDL_QUIT; $app->resize($event->resize_w,$event->resize_h) if $event->type==SDL +_VIDEORESIZE; } sub on_move{ my($x,$y,$nx,$ny,$xdiff,$ydiff,$xdisp,$ydisp,$idx); my($w,$h)=($image->w,$image->h); # Set random drops (!int(rand(2)))&&($wavemap{$wavemap{wave}}[((int(rand($w-10))+5)*$w) ++int(rand($w-10))+5]=-100); # Update the wave map updatewavemaps(); # Draw screen SDL::Video::lock_surface($surface); for($x=0;$x<$w;$x++){ for($y=0;$y<$h;$y++){ $idx=($y*$w)+$x; $xdiff=int($wavemap{$wavemap{wave}}[$idx+1]-$wavemap{$wavemap{wa +ve}}[$idx]); $ydiff=int($wavemap{$wavemap{wave}}[$idx+$w]-$wavemap{$wavemap{w +ave}}[$idx]); $xdisp=$displut[$xdiff+256]; $ydisp=$displut[$ydiff+256]; $nx=$xdiff<0?$x-$xdisp:$x+$xdisp; $ny=$ydiff<0?$y-$ydisp:$y+$ydisp; $nx=$nx<0?0:$nx>=$w?$w-1:$nx; $ny=$ny<0?0:$ny>=$h?$h-1:$ny; vec(${$surf_m->[$x][$y]},0,32)=vec(${$imge_m->[$nx][$ny]},0,32); } } SDL::Video::unlock_surface($surface); } sub on_show{ my $buffer=SDL::GFX::Rotozoom::surface_xy($surface,0,($app->w/$surfa +ce->w),($app->h/$surface->h),1); SDL::Video::blit_surface($buffer,SDL::Rect->new(0,0,$buffer->w,$buff +er->h),$app,SDL::Rect->new(0,0,$app->w,$app->h)); $app->sync; } sub load_surface{ my $surface; if($imgfile ne ''){ my $tmp=SDL::Image::load($imgfile); $surface=SDLx::Surface->new(w=>$tmp->w,h=>$tmp->h,d=>32,color=>0xF +FFFFFFF); $surface->blit_by($tmp); }else{ $surface=SDLx::Surface->new(w=>100,h=>100,d=>32,color=>0xFFFFFFFF) +; for(my $x=0;$x<($surface->w)-5;$x+=20){ for(my $y=0;$y<($surface->h)-5;$y+=20){ my $c=SDL::Video::map_RGBA($surface->format(),255-int(($x*$y)/ +40),0,int(($x*$y)/40),255); SDL::Video::fill_rect($surface,SDL::Rect->new($x+2,$y+2,15,15) +,$c); } } } return $surface; } sub updatewavemaps{ my($x,$y,$n,$idx); my($w,$h,$da)=($image->w,$image->h,24); for($y=1;$y<$h;$y++){ for($x=1;$x<$w;$x++){ $idx=($y*$w)+$x; $n=($wavemap{$wavemap{wave}}[$idx-1]+ $wavemap{$wavemap{wave}}[$idx+1]+ $wavemap{$wavemap{wave}}[$idx-$w]+ $wavemap{$wavemap{wave}}[$idx+$w])/2- $wavemap{1-$wavemap{wave}}[$idx]; $wavemap{1-$wavemap{wave}}[$idx]=$n-($n/$da); } } $wavemap{wave}=1-$wavemap{wave}; }

Update:

I have optimized the code above (issue still not fixed), and I have around 40 FPS for an image of 100x100 pixels (it is stretched to 400x400 for display, but performances on pixels manipulation is what matters here). Not too bad, but not enough to process a larger screen (e.g. 640x480 is 1 FPS).

Replies are listed 'Best First'.
Re: SDL/SDLx issue with application resizing
by Athanasius (Archbishop) on Jan 31, 2019 at 13:42 UTC

    Hello Garden Dwarf,

    As soon as I release the mouse button, the application ends without any message (window is closing, and I get back to the terminal prompt).

    I get the same result, except that I do get a message on the command terminal:

    23:34 >perl 1972_SoPW.pl SDL cannot set video:DDraw created surface with wrong pitch at C:/Perl +/Strawberry/strawberry-perl-ld-5.26.0.1-64bit-PDL/perl/site/lib/SDLx/ +App.pm line 146. 23:34 >

    My platform:

    • Windows 8.1, 64-bit
    • Strawberry Perl 5.26.0
    • SDL 2.546

    Hope that information helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Hello Athanasius,

      Thank you for your time, it helped me to verify that my installation is not corrupted. I guess now I have to find how to manage the application resizing properly, and despite my researches I wasn't able to find an example.

      By the way, I noticed that I have the same message appearing but not each time. Weird.

      If someone has succeeded into this previously, it would be nice to share some lines of code now. Thanks :)

        In SDL::Event I found this:

        Window resize events resize_w, resize_h When SDL_RESIZABLE is passed as a flag to SDL_SetVideoMode the user is + allowed to resize the applications window. When the window is resized an SDL_VIDEORESIZE is reported, with the new window width and height values stored in the resize structure's resize_w and resize_h. When an + SDL_VIDEORESIZE is received the window should be resized to the new dimensions using SDL_SetVideoMode.

        In your program it looks like you have everything except the last part where it says to use SDL_SetVideoMode.

        I couldn't find any examples that use that but I did find an example included in SDL called examples/cookbook/1.pl that uses SDL::Video::set_video_mode(320, 320, 32, SDL_SWSURFACE );

        The documentation for SDL::Video::set_video_mode() shows that function seems to be what you need:

        SDL_RESIZABLE Create a resizable window. When the window is resized by the user a SDL_VIDEORESIZE event is generated and SDL::Video::set_video_mode can be called again with the new size.

        There are more details there on how to call SDL::Video::set_video_mode().

        Your application looks interesting. Let us know how it works out. Good luck!

        Update:

        After looking at your application again and looking at the contents of App.pm I notice the resize() function you use calls SDL::Video::set_video_mode() so it seems like you've done it correctly. My comments above were not very helpful it seems.