#!/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{wave}}[$idx]); $ydiff=int($wavemap{$wavemap{wave}}[$idx+$w]-$wavemap{$wavemap{wave}}[$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/$surface->w),($app->h/$surface->h),1); SDL::Video::blit_surface($buffer,SDL::Rect->new(0,0,$buffer->w,$buffer->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=>0xFFFFFFFF); $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}; }