├── .gitignore ├── lib ├── perltidyrc ├── Makefile.ini ├── SDLManualLatex.pm └── book.sty ├── font.ttf ├── src ├── logo.png ├── images │ ├── first.png │ ├── pdl.png │ ├── pong1.png │ ├── pong2.png │ ├── puzz1.png │ ├── draw-1.png │ ├── draw-2.png │ ├── draw-3.png │ ├── draw-4.png │ ├── effects.png │ ├── flower.png │ ├── painted.png │ ├── tetris.png │ ├── collision.png │ ├── flower-1.png │ ├── opengl-1.png │ ├── spectro-1.png │ └── xs_effects.png ├── 08-coro.pod ├── 01-first.pod ├── 10-profiling.pod ├── 13-free_resources.pod ├── 11-XS_effects.pod ├── 00-preface.pod ├── 03-events.pod ├── 12-PDL_OpenGL.pod ├── 09-CPAN.pod ├── 02-drawing.pod ├── 04-game.pod ├── 07-puzz.pod ├── 06-tetris.pod └── 08-music_and_sound.pod ├── data ├── sample.wav ├── tetris_1.png ├── tetris_2.png ├── tetris_3.png ├── tetris_4.png ├── tetris_5.png ├── tetris_6.png ├── tetris_7.png ├── tetris_back.png └── music │ ├── 04-Zech.ogg │ ├── 03-Teleforce.ogg │ ├── 02-Arid-Sands.ogg │ ├── 01-PC-Speaker-Sorrow.ogg │ └── Songs ├── games └── tetris.zip ├── dist └── SDL_Manual.pdf ├── code_listings ├── froggs.png ├── first.pl ├── drawing.pl ├── cpan.pl ├── event_quitting.pl ├── sols_pp.pl ├── flower.pl ├── music_sound.pl ├── openglapp.pl ├── audio.pl ├── game_loop_simple.pl ├── pdl.pl ├── profile_0.pl ├── xs_effects.pl ├── palette_cycle.pl ├── profile_1.pl ├── bouncing.pl ├── game_sdlx.pl ├── mouse_paint.pl ├── sound_event.pl ├── game_fixed.pl ├── stereograph.pl ├── sdl_mixer_spectro.pl ├── pong.pl └── tetris.pl ├── TODO ├── bin ├── book-to-html ├── ascii-to-pod.pl ├── book-to-latex └── extract_programlisting ├── INSTALL ├── Makefile ├── typemap └── README.pod /.gitignore: -------------------------------------------------------------------------------- 1 | build* 2 | *.swp 3 | eg/* 4 | 5 | -------------------------------------------------------------------------------- /lib/perltidyrc: -------------------------------------------------------------------------------- 1 | --indent-columns=4 2 | --maximum-line-length=70 3 | -------------------------------------------------------------------------------- /font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/font.ttf -------------------------------------------------------------------------------- /src/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/logo.png -------------------------------------------------------------------------------- /data/sample.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/sample.wav -------------------------------------------------------------------------------- /data/tetris_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_1.png -------------------------------------------------------------------------------- /data/tetris_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_2.png -------------------------------------------------------------------------------- /data/tetris_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_3.png -------------------------------------------------------------------------------- /data/tetris_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_4.png -------------------------------------------------------------------------------- /data/tetris_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_5.png -------------------------------------------------------------------------------- /data/tetris_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_6.png -------------------------------------------------------------------------------- /data/tetris_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_7.png -------------------------------------------------------------------------------- /games/tetris.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/games/tetris.zip -------------------------------------------------------------------------------- /data/tetris_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/tetris_back.png -------------------------------------------------------------------------------- /dist/SDL_Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/dist/SDL_Manual.pdf -------------------------------------------------------------------------------- /src/images/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/first.png -------------------------------------------------------------------------------- /src/images/pdl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/pdl.png -------------------------------------------------------------------------------- /src/images/pong1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/pong1.png -------------------------------------------------------------------------------- /src/images/pong2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/pong2.png -------------------------------------------------------------------------------- /src/images/puzz1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/puzz1.png -------------------------------------------------------------------------------- /data/music/04-Zech.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/music/04-Zech.ogg -------------------------------------------------------------------------------- /src/images/draw-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/draw-1.png -------------------------------------------------------------------------------- /src/images/draw-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/draw-2.png -------------------------------------------------------------------------------- /src/images/draw-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/draw-3.png -------------------------------------------------------------------------------- /src/images/draw-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/draw-4.png -------------------------------------------------------------------------------- /src/images/effects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/effects.png -------------------------------------------------------------------------------- /src/images/flower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/flower.png -------------------------------------------------------------------------------- /src/images/painted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/painted.png -------------------------------------------------------------------------------- /src/images/tetris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/tetris.png -------------------------------------------------------------------------------- /code_listings/froggs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/code_listings/froggs.png -------------------------------------------------------------------------------- /src/images/collision.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/collision.png -------------------------------------------------------------------------------- /src/images/flower-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/flower-1.png -------------------------------------------------------------------------------- /src/images/opengl-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/opengl-1.png -------------------------------------------------------------------------------- /src/images/spectro-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/spectro-1.png -------------------------------------------------------------------------------- /src/images/xs_effects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/src/images/xs_effects.png -------------------------------------------------------------------------------- /data/music/03-Teleforce.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/music/03-Teleforce.ogg -------------------------------------------------------------------------------- /data/music/02-Arid-Sands.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/music/02-Arid-Sands.ogg -------------------------------------------------------------------------------- /lib/Makefile.ini: -------------------------------------------------------------------------------- 1 | BUILD_STRATEGY := xelatex 2 | XELATEX := xelatex 3 | BINARY_TARGET_DIR := ../dist 4 | 5 | -------------------------------------------------------------------------------- /data/music/01-PC-Speaker-Sorrow.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerlGameDev/SDL_Manual/HEAD/data/music/01-PC-Speaker-Sorrow.ogg -------------------------------------------------------------------------------- /src/08-coro.pod: -------------------------------------------------------------------------------- 1 | =head0 Almost multi-threaded Games 2 | 3 | =head1 Author 4 | 5 | This chapter's content has been graciously provided by C. 6 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODO: 2 | 3 | - Read chromatic's MP indexing stuff and emulate 4 | - Write =for intent for chapters that get complicate 5 | - Add more 'exercises'/'deviations' at the end of Chapters: 6 | 7 | -------------------------------------------------------------------------------- /code_listings/first.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use SDL; 5 | use SDLx::App; 6 | my $app = SDLx::App->new(width => 400, height => 400, title => 'Pong - A clone'); 7 | 8 | sleep(2); 9 | -------------------------------------------------------------------------------- /bin/book-to-html: -------------------------------------------------------------------------------- 1 | #!perl -w 2 | use strict; 3 | use Pod::PseudoPod::HTML; 4 | 5 | for (@ARGV) { 6 | my $parser = Pod::PseudoPod::HTML->new(); 7 | $parser->output_fh( *STDOUT ); 8 | $parser->codes_in_verbatim(1); 9 | $parser->parse_file( $_ ); 10 | } 11 | -------------------------------------------------------------------------------- /data/music/Songs: -------------------------------------------------------------------------------- 1 | 01 - PC Speaker's Sorrow ( skoshu : http://8bitcollective.com/music/skoshu/PC+Speaker%27s+Sorrow/ ) 2 | 02 - Arid Sands ( skoshu : http://8bitcollective.com/music/skoshu/Secret+of+Mana+-+Arid+Sands+VRC6+Cover/ ) 3 | 03 - Teleforce ( µB : http://8bitcollective.com/music/%C2%B5B/Teleforce+(Teslabit)/ ) 4 | 04 - Zech! ( skoshu : http://8bitcollective.com/music/skoshu/Zech!+-+Secret+Of+Mana+JUICED!/) 5 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | = DEPS = 2 | * GNU make 3 | * perl 5.10 4 | * the Perl 5 module Pod::PseudoPod::LaTeX version 1.101050 or newer 5 | * A number of LaTeX packages (see lib/*.sty). Ubuntu 10.04 6 | supplies most of what is needed with its texlive-latex-base, 7 | texlive-latex-extra, texlive-xetex, texlive-fonts-extra and 8 | texlive-latex-recommended packages. 9 | * We use the ttf-liberation packages for fonts 10 | 11 | = RUN = 12 | 13 | $ make 14 | 15 | -------------------------------------------------------------------------------- /code_listings/drawing.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use SDL; 5 | use SDLx::App; 6 | my $app = SDLx::App->new(width => 400, height => 400, title => 'Drawing Examples'); 7 | 8 | $app->draw_line( [200,20], [20,200], [255, 255, 0, 255] ); 9 | 10 | $app->draw_rect([ 10, 20, 40 , 40], [255,255,255,255]); 11 | 12 | $app->draw_circle([100,100], 20, [255,0,0,255]); 13 | 14 | $app->draw_circle_filled( [100,100], 19, [0,0,255,255] ); 15 | 16 | $app->update(); 17 | 18 | sleep(2); 19 | -------------------------------------------------------------------------------- /bin/ascii-to-pod.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use 5.010; 4 | use utf8; 5 | use open IO => ':encoding(utf8)';; 6 | 7 | use Data::Dumper; 8 | $Data::Dumper::Useqq = 1; 9 | 10 | say "=begin table\n"; 11 | while (<>) { 12 | chomp; 13 | s/^\s+//; 14 | next unless length $_; 15 | my @row = split /\s{2,}/, $_; 16 | say "=headrow\n" if $. == 1; 17 | 18 | say "=row\n"; 19 | 20 | for my $c (@row) { 21 | say "=cell $c\n"; 22 | } 23 | 24 | say "=bodyrows\n" if $. == 1; 25 | } 26 | say "=end table"; 27 | -------------------------------------------------------------------------------- /code_listings/cpan.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use SDLx::App; 5 | 6 | use Game::Life; 7 | use Data::Dumper; 8 | 9 | my $app = SDLx::App->new( w=>400, h=> 400); 10 | 11 | my $game = new Game::Life(100); 12 | my $starting = [ [ 1, 1, 1 ], [ 1, 0, 0 ], [ 0, 1, 0 ] ]; 13 | 14 | $game->place_points( 96, 96, $starting ); 15 | for ( 1 .. 100 ) { 16 | my $grid = $game->get_grid(); 17 | $app->draw_rect( undef, 0 ); 18 | foreach( 0..100 ) 19 | { 20 | my $x = $_; 21 | foreach( 0..100) 22 | { 23 | $app->draw_rect( [$x*4, $_*4, 4,4 ], 0xFF0000FF ) if $grid->[$x][$_]; 24 | } 25 | 26 | } 27 | $game->process(); 28 | $app->update(); 29 | } 30 | 31 | 32 | sleep(2); 33 | -------------------------------------------------------------------------------- /code_listings/event_quitting.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use SDL::Event; 5 | use SDLx::App; 6 | 7 | my $app = SDLx::App->new( w => 200, h => 200, d => 32, title => "Quit Events" ); 8 | 9 | #We can add an event handler 10 | $app->add_event_handler( \&quit_event ); 11 | 12 | #Then we will run the app 13 | #which will start a loop for keeping the app alive 14 | $app->run(); 15 | 16 | sub quit_event 17 | { 18 | #The callback is provided a SDL::Event to use 19 | my $event = shift; 20 | 21 | #Each event handler also returns you back the Controller call it 22 | my $controller = shift; 23 | 24 | #Stoping the controller for us will exit $app->run() for us 25 | $controller->stop if $event->type == SDL_QUIT; 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /bin/book-to-latex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use warnings; 4 | use feature ':5.10'; 5 | use Getopt::Long; 6 | use SDLManualLatex; 7 | use Template; 8 | 9 | main(); 10 | 11 | sub main { 12 | my $paper; 13 | GetOptions( 14 | 15 | # Should be one of: a4, letter. 16 | 'paper:s' => \$paper, 17 | ) or die; 18 | 19 | my $output; 20 | for (@ARGV) { 21 | my $parser = SDLManualLatex->new(); 22 | $parser->emit_environments( sidebar => "sidebar" ); 23 | $parser->codes_in_verbatim(1); 24 | $parser->output_string( \$output ); 25 | $parser->parse_file($_); 26 | } 27 | 28 | my $tt = Template->new( { INCLUDE_PATH => 'lib', } ); 29 | 30 | print $tt->process( 31 | 'book.sty', { 32 | content => $output, 33 | paper => $paper, 34 | } ); 35 | 36 | } ## end sub main 37 | 38 | -------------------------------------------------------------------------------- /code_listings/sols_pp.pl: -------------------------------------------------------------------------------- 1 | 2 | use strict; 3 | use warnings; 4 | 5 | use SDL; 6 | use SDLx::App; 7 | 8 | 9 | sub render { 10 | my $screen = shift; 11 | if ( SDL::Video::MUSTLOCK($screen) ) { 12 | return if ( SDL::Video::lock_surface($screen) < 0 ); 13 | } 14 | 15 | my $ticks = SDL::get_ticks(); 16 | my ( $i, $y, $yofs, $ofs ) = ( 0, 0, 0, 0 ); 17 | for ( $i = 0; $i < 480; $i++ ) { 18 | for ( my $j = 0, $ofs = $yofs; $j < 640; $j++, $ofs++ ) { 19 | $screen->set_pixels( $ofs, ( $i * $i + $j * $j + $ticks ) ); 20 | } 21 | $yofs += $screen->pitch / 4; 22 | } 23 | 24 | 25 | SDL::Video::unlock_surface($screen) if ( SDL::Video::MUSTLOCK($screen) ); 26 | 27 | SDL::Video::update_rect( $screen, 0, 0, 640, 480 ); 28 | 29 | return 0; 30 | } 31 | 32 | 33 | my $app = SDLx::App->new( width => 640, height => 480, eoq => 1, title => "Grovvy XS Effects" ); 34 | 35 | $app->add_show_handler( sub{ render( $app ) } ); 36 | 37 | $app->run(); 38 | 39 | -------------------------------------------------------------------------------- /code_listings/flower.pl: -------------------------------------------------------------------------------- 1 | use SDL; 2 | use SDLx::App; 3 | use SDLx::Sprite; 4 | 5 | my $app = SDLx::App->new( w => 500, h => 500, d => 32, title => 'Pretty Flowers' ); 6 | 7 | # Draw Code Starts here 8 | 9 | my $flower = SDLx::Sprite->new ( width => 50, height => 100 ); 10 | 11 | $flower->surface->draw_rect ( [0,0,50,100], [0,0,0,0] ); 12 | 13 | $flower->surface->draw_rect ( [23,30, 4, 100], [0,255,0,255] ); 14 | $flower->surface->draw_circle_filled ( [25,25], 10, [150,0,0,255] ); 15 | $flower->surface->draw_circle ( [25,25], 10, [255,0,0,255] ); 16 | $flower->alpha_key( 0 ); 17 | 18 | $app->draw_rect( [0,0,500,500], [20,50,170, 255] ); 19 | 20 | $app->draw_rect( [0,400,500,100], [50,170,20,100] ); 21 | 22 | foreach( 0..500 ) 23 | { 24 | my $y = 425 - rand( 50 ); 25 | $flower->draw_xy( $app, rand(500)-20, $y ); 26 | } 27 | 28 | #Draw Code Ends Here 29 | 30 | $app->update(); 31 | 32 | require SDL::Video; 33 | 34 | SDL::Video::save_BMP( $app, 'flower.bmp'); 35 | 36 | sleep(2); 37 | -------------------------------------------------------------------------------- /code_listings/music_sound.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use Carp; 5 | use SDL::Audio; 6 | use SDL::Mixer; 7 | use SDL::Mixer::Samples; 8 | use SDL::Mixer::Channels; 9 | use SDL::Mixer::Music; 10 | SDL::init(SDL_INIT_AUDIO); 11 | 12 | unless( SDL::Mixer::open_audio( 44100, AUDIO_S16SYS, 2, 4096 ) == 0 ) 13 | { 14 | Carp::croak "Cannot open audio: ".SDL::get_error(); 15 | } 16 | 17 | my $sample = SDL::Mixer::Samples::load_WAV('data/sample.wav'); 18 | 19 | unless( $sample) 20 | { 21 | Carp::croak "Cannot load file data/sample.wav: ".SDL::get_error(); 22 | } 23 | 24 | my $playing_channel = SDL::Mixer::Channels::play_channel( -1, $sample, 0 ); 25 | 26 | #Load our awesome music from U 27 | my $background_music = SDL::Mixer::Music::load_MUS('data/music/01-PC-Speaker-Sorrow.ogg'); 28 | 29 | unless( $background_music ) 30 | { 31 | Carp::croak "Cannot load music file data/music/01-PC-Speaker-Sorrow.ogg: ".SDL::get_error() ; 32 | } 33 | 34 | SDL::Mixer::Music::play_music( $background_music,0 ); 35 | 36 | sleep(2); 37 | 38 | SDL::Mixer::Music::halt_music(); 39 | SDL::Mixer::close_audio; 40 | -------------------------------------------------------------------------------- /code_listings/openglapp.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use SDLx::App; 5 | use SDL::Event; 6 | 7 | use OpenGL qw/:all/; 8 | 9 | my $app = SDLx::App->new( 10 | title => "OpenGL App", 11 | width => 600, 12 | height => 600, 13 | gl => 1, 14 | eoq => 1 15 | ); 16 | 17 | glEnable(GL_DEPTH_TEST); 18 | glMatrixMode(GL_PROJECTION); 19 | glLoadIdentity; 20 | gluPerspective(60, $app->w/$app->h, 1, 1000 ); 21 | glTranslatef( 0,0,-20); 22 | glutInit(); 23 | 24 | my $rotate = [0,0]; 25 | 26 | $app->add_show_handler( 27 | sub{ 28 | my $dt = shift; 29 | 30 | #clear the screen 31 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 32 | glColor3d(0,1,1); 33 | 34 | glPushMatrix(); 35 | 36 | glRotatef($rotate->[0], 1,0,0); 37 | glRotatef($rotate->[1], 0,1,0); 38 | 39 | glutSolidTeapot(2); 40 | 41 | #sync the SDL application with the OpenGL buffer data 42 | $app->sync; 43 | 44 | glPopMatrix(); 45 | } 46 | ); 47 | 48 | $app->add_event_handler( 49 | 50 | sub { 51 | my ($e ) = shift; 52 | 53 | if( $e->type == SDL_MOUSEMOTION ) 54 | { 55 | $rotate = [$e->motion_x, $e->motion_y]; 56 | } 57 | 58 | } 59 | 60 | ); 61 | 62 | $app->run(); 63 | 64 | -------------------------------------------------------------------------------- /code_listings/audio.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | use strict; 3 | use SDL; 4 | use SDL::Audio; 5 | use SDL::AudioSpec; 6 | 7 | use threads; 8 | use threads::shared; 9 | 10 | SDL::init(SDL_INIT_AUDIO); 11 | 12 | 13 | my $desired = SDL::AudioSpec->new; 14 | 15 | $desired->freq(44100); 16 | $desired->format(SDL::Audio::AUDIO_S16SYS); 17 | $desired->channels(2); 18 | $desired->samples(4096); 19 | $desired->callback('main::audio_callback'); 20 | 21 | 22 | my $done :shared = 0; 23 | 24 | sub audio_callback { 25 | $done = 1; 26 | warn 'Set Done:'.$done; 27 | #SDL::Audio::pause(2); 28 | } 29 | 30 | my $obtained = SDL::AudioSpec->new; 31 | unless( SDL::Audio::open( $desired, $obtained ) == 0 ) 32 | { 33 | die "Problem opening audio:".SDL::get_error(); 34 | } 35 | my $wav_ref = SDL::Audio::load_wav( 'data/sample.wav', $obtained ); 36 | 37 | unless ( $wav_ref ) 38 | { 39 | 40 | die "Problem loading wav data:".SDL::get_error(); 41 | 42 | } 43 | my ( $wav_spec, $audio_buf, $audio_len ) = @{$wav_ref}; 44 | 45 | 46 | SDL::Audio::pause(0); 47 | 48 | while( $done != 1 && SDL::Audio::get_status() == SDL_AUDIO_PLAYING ) 49 | { 50 | warn $done; 51 | 52 | SDL::delay(100); 53 | 54 | } 55 | SDL::Audio::free_wav($audio_buf); 56 | SDL::Audio::close(); 57 | 58 | -------------------------------------------------------------------------------- /code_listings/game_loop_simple.pl: -------------------------------------------------------------------------------- 1 | 2 | use strict; 3 | use warnings; 4 | use SDL; 5 | use SDL::Event; 6 | use SDL::Events; 7 | use SDLx::App; 8 | 9 | my $app = SDLx::App->new( 10 | width => 200, 11 | height => 200, 12 | title => 'Pew Pew' 13 | ); 14 | 15 | #Don't need to quit yet 16 | my $quit = 0; 17 | 18 | #Start laser on the left 19 | my $laser = 0; 20 | 21 | sub get_events { 22 | 23 | my $event = SDL::Event->new(); 24 | 25 | #Pump the event queue 26 | SDL::Events::pump_events; 27 | 28 | while ( SDL::Events::poll_event($event) ) { 29 | $quit = 1 if $event->type == SDL_QUIT; 30 | } 31 | } 32 | 33 | sub calculate_next_positions { 34 | $laser++; 35 | $laser = 0 if $laser > $app->w(); 36 | } 37 | 38 | sub render { 39 | 40 | #Draw the background first 41 | $app->draw_rect( [ 0, 0, $app->w, $app->h ], 0 ); 42 | 43 | #Draw the laser 44 | $app->draw_rect( [ $laser, $app->h / 2, 10, 2 ], [ 255, 0, 0, 255 ] ); 45 | 46 | $app->update(); 47 | 48 | } 49 | 50 | while ( !$quit ) { 51 | get_events(); 52 | calculate_next_positions(); 53 | render(); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /code_listings/pdl.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDLx::App; 4 | use PDL; 5 | 6 | my $app = SDLx::App->new( 7 | title => "PDL and SDL aplication", 8 | width => 640, height => 480, eoq => 1 ); 9 | 10 | 11 | sub make_surface_piddle { 12 | my ( $bytes_per_pixel, $width, $height) = @_; 13 | my $piddle = zeros( byte, $bytes_per_pixel, $width, $height ); 14 | my $pointer = $piddle->get_dataref(); 15 | my $s = SDL::Surface->new_from( 16 | $pointer, $width, $height, 32, 17 | $width * $bytes_per_pixel 18 | ); 19 | 20 | my $surface = SDLx::Surface->new( surface => $s ); 21 | 22 | return ( $piddle, $surface ); 23 | } 24 | 25 | 26 | my ( $piddle, $surface ) = make_surface_piddle( 4, 400, 200 ); 27 | 28 | $app->add_move_handler( sub { 29 | 30 | SDL::Video::lock_surface($surface); 31 | 32 | $piddle->mslice( 'X', 33 | [ rand(400), rand(400), 1 ], 34 | [ rand(200), rand(200), 1 ] 35 | ) .= pdl( rand(225), rand(225), rand(225), 255 ); 36 | 37 | SDL::Video::unlock_surface($surface); 38 | } ); 39 | 40 | 41 | $app->add_show_handler( sub { 42 | 43 | $surface->blit( $app, [0,0,$surface->w,$surface->h], [10,10,0,0] ); 44 | $app->update(); 45 | 46 | }); 47 | 48 | $app->run(); 49 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PERL = perl 2 | 3 | ifeq "$(PAPER)" "" 4 | PAPER = $(shell paperconf) 5 | endif 6 | 7 | ifneq "$(TEST)" "" 8 | BOOK = build/test.$(PAPER) 9 | CHAPTERS = $(wildcard test/*.pod) 10 | else 11 | BOOK = build/SDL_Manual.$(PAPER) 12 | CHAPTERS = \ 13 | src/00-preface.pod \ 14 | src/01-first.pod \ 15 | src/02-drawing.pod \ 16 | src/03-events.pod \ 17 | src/04-game.pod \ 18 | src/05-pong.pod \ 19 | src/06-tetris.pod \ 20 | src/07-puzz.pod \ 21 | src/08-music_and_sound.pod \ 22 | src/09-CPAN.pod \ 23 | src/11-XS_effects.pod \ 24 | src/12-PDL_OpenGL.pod \ 25 | src/13-free_resources.pod 26 | 27 | endif 28 | 29 | default: prepare pdf clean 30 | 31 | prepare: clean 32 | mkdir build 33 | 34 | html: prepare $(CHAPTERS) bin/book-to-html 35 | $(PERL) bin/book-to-html $(CHAPTERS) > $(BOOK).html 36 | 37 | pdf: tex lib/Makefile 38 | #cp src/mmd-table.svg build/mmd-table.svg 39 | cd build && make -I ../lib -f ../lib/Makefile 40 | 41 | tex: prepare $(CHAPTERS) lib/SDLManualLatex.pm lib/book.sty bin/book-to-latex 42 | $(PERL) -Ilib bin/book-to-latex --paper $(PAPER) $(CHAPTERS) > $(BOOK).tex 43 | 44 | rel_pdf: pdf 45 | cp $(BOOK).pdf dist/SDL_Manual.pdf 46 | 47 | rel_html: html 48 | cp $(BOOK).html dist/SDL_Manual.html 49 | 50 | bump: rel_pdf rel_html 51 | 52 | clean: 53 | rm -rf build/ 54 | 55 | .PHONY: clean 56 | 57 | # vim: set noexpandtab 58 | -------------------------------------------------------------------------------- /code_listings/profile_0.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use SDL::Video; 5 | use SDLx::App; 6 | 7 | my $app = SDLx::App->new( 8 | w => 600, 9 | h => 600, 10 | eoq => 1, 11 | flags => SDL_HWSURFACE | SDL_DOUBLEBUF, 12 | init => SDL_INIT_VIDEO, 13 | title => 'Profiling', 14 | dt => 0.2 15 | ); 16 | 17 | my $walkers = []; 18 | 19 | foreach(0..20) 20 | { 21 | 22 | $walkers->[$_] = { 23 | id => $_, 24 | position => [ rand() * 600, rand() * 600 ], 25 | velocity => [ rand() * 20, rand() * 20 ], 26 | color => [ 255, 0, 0, 255 ] 27 | } 28 | 29 | 30 | } 31 | 32 | sub show_blocks{ 33 | $app->draw_rect( [ 0, 0, 600, 600 ], 0 ); 34 | 35 | foreach ( @{$walkers} ) { 36 | 37 | $app->draw_rect( [ @{ $_->{position} }, 5, 5 ], $_->{color} ); 38 | 39 | } 40 | 41 | $app->update(); 42 | 43 | } 44 | 45 | sub move_blocks{ 46 | my $dt = shift; 47 | foreach ( @{$walkers} ) { 48 | 49 | $_->{position}->[0] += $_->{velocity}->[0] * $dt; 50 | $_->{velocity}->[0] *= -1 51 | if ( $_->{position}->[0] > 590 || $_->{position}->[0] < 0 ); 52 | $_->{position}->[1] += $_->{velocity}->[1] * $dt; 53 | $_->{velocity}->[1] *= -1 54 | if ( $_->{position}->[1] > 590 || $_->{position}->[1] < 0 ); 55 | 56 | } 57 | 58 | } 59 | 60 | $app->add_show_handler( \&show_blocks ); 61 | $app->add_move_handler( \&move_blocks ); 62 | 63 | $app->run(); 64 | -------------------------------------------------------------------------------- /code_listings/xs_effects.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Inline with => 'SDL'; 4 | use SDL; 5 | use SDLx::App; 6 | 7 | 8 | my $app = SDLx::App->new( width => 640, height => 480, eoq => 1, title => "Grovvy XS Effects" ); 9 | 10 | $app->add_show_handler( \&render ); 11 | 12 | $app->run(); 13 | 14 | use Inline C => <<'END'; 15 | 16 | void render( float delta, SDL_Surface *screen ) 17 | { 18 | // Lock surface if needed 19 | if (SDL_MUSTLOCK(screen)) 20 | if (SDL_LockSurface(screen) < 0) 21 | return; 22 | 23 | // Ask SDL for the time in milliseconds 24 | int tick = SDL_GetTicks(); 25 | 26 | // Declare a couple of variables 27 | int i, j, yofs, ofs; 28 | 29 | // Draw to screen 30 | yofs = 0; 31 | for (i = 0; i < screen->h; i++) 32 | { 33 | for (j = 0, ofs = yofs; j < screen->w; j++, ofs++) 34 | { 35 | 36 | Uint32 value = i * i + j * j + tick; 37 | Uint8 a = value >> 2; 38 | Uint8 b = value >> 4; 39 | Uint8 g = value >> 8; 40 | Uint8 r = value >> 16; 41 | 42 | Uint32 map_val = SDL_MapRGBA( screen->format, r, g, b, a); 43 | ((unsigned int*)screen->pixels)[ofs] = map_val; 44 | } 45 | yofs += screen->pitch / 4; 46 | } 47 | 48 | // Unlock if needed 49 | if (SDL_MUSTLOCK(screen)) 50 | SDL_UnlockSurface(screen); 51 | 52 | // Tell SDL to update the whole screen 53 | SDL_UpdateRect(screen, 0, 0, screen->w,screen->h); 54 | } 55 | 56 | END 57 | 58 | 59 | -------------------------------------------------------------------------------- /bin/extract_programlisting: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use Modern::Perl; 4 | package ExtractProgramListing; 5 | use base "Pod::Parser"; 6 | use File::Basename; 7 | use IO::All; 8 | use Perl::Tidy 'perltidy'; 9 | 10 | my $listing = 0; 11 | my $prefix = "#!/usr/bin/env perl\n\n"; 12 | my $program = $prefix; 13 | my $seq = 1; 14 | my $example_dir = "eg"; 15 | 16 | sub textblock {} 17 | sub interior_sequence {} 18 | sub begin_input{ $seq = 1 } 19 | 20 | sub command { 21 | shift; 22 | if ($_[1] =~ /^programlisting/) { 23 | 24 | if ($_[0] eq 'begin') { 25 | $listing++; 26 | } 27 | elsif ($_[0] eq 'end') { 28 | 29 | my $file = basename($_[3]{-file}); 30 | $file =~ s/\.pod/-$seq.pl/; 31 | $file = "$example_dir/$file"; 32 | 33 | $program =~ s/^\s+//; 34 | my $fmt; 35 | 36 | perltidy( 37 | argv => [], 38 | source => \$program, 39 | destination => \$fmt, 40 | perltidyrc => 'lib/perltidyrc', 41 | ); 42 | 43 | $fmt > io($file); 44 | 45 | $program = $prefix; 46 | $listing--; 47 | $seq++; 48 | } 49 | } 50 | } 51 | 52 | sub verbatim { 53 | shift; 54 | $program .= $_[0] if ($listing); 55 | } 56 | 57 | package main; 58 | 59 | my $p = ExtractProgramListing->new(); 60 | 61 | mkdir('eg') unless (-d 'eg'); 62 | $p->parse_from_file($_) for (@ARGV); 63 | -------------------------------------------------------------------------------- /code_listings/palette_cycle.pl: -------------------------------------------------------------------------------- 1 | use Modern::Perl; 2 | use SDL; 3 | use SDL::Video; 4 | use SDL::Color; 5 | use SDL::Image; 6 | use SDL::Event; 7 | use SDL ':init'; 8 | use SDL::Event; 9 | use SDL::Events ':all'; 10 | my $screen_width = 300; 11 | my $screen_height = 340; 12 | my $x = 0; 13 | my $quit = 0; 14 | SDL::init(SDL_INIT_VIDEO); 15 | 16 | # make a screen surface 17 | my $screen_surface 18 | = SDL::Video::set_video_mode( $screen_width, $screen_height, 8, 19 | SDL_SWSURFACE | SDL_HWPALETTE ); 20 | 21 | # load and blit an image 22 | my $img = SDL::Image::load('froggs.png'); 23 | 24 | # this image blit only needs to be done *once* :) 25 | SDL::Video::blit_surface( $img, undef, $screen_surface, undef ); 26 | 27 | 28 | while ( !$quit ) { 29 | 30 | # check for a quit? 31 | get_events(); 32 | # 33 | set_palette(); 34 | } 35 | 36 | sub get_events { 37 | my $event = SDL::Event->new(); 38 | 39 | #Pump the event queue 40 | SDL::Events::pump_events; 41 | while ( SDL::Events::poll_event($event) ) { 42 | $quit = 1 if $event->type == SDL_QUIT; 43 | } 44 | } 45 | 46 | sub set_palette { 47 | my @clrs; 48 | 49 | #push 256 color objects into an array 50 | foreach my $i ( 0 .. 255 ) { $clrs[$i] = SDL::Color->new( $x, 0, $i ); } 51 | 52 | # update surfaces' palette with 256 new colors 53 | my $rc 54 | = SDL::Video::set_palette( $screen_surface, SDL_PHYSPAL, 0, @clrs ); 55 | $x++; 56 | $x = 0 if $x == 255; 57 | } -------------------------------------------------------------------------------- /code_listings/profile_1.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use SDL::Video; 5 | use SDLx::App; 6 | 7 | my $app = SDLx::App->new( 8 | w => 600, 9 | h => 600, 10 | eoq => 1, 11 | flags => SDL_HWSURFACE | SDL_DOUBLEBUF, 12 | init => SDL_INIT_VIDEO, 13 | title => 'Profiling', 14 | dt => 0.2 15 | ); 16 | 17 | my $walkers = []; 18 | 19 | my $profile_counter = 0; 20 | 21 | foreach(0..20) 22 | { 23 | 24 | $walkers->[$_] = { 25 | id => $_, 26 | position => [ rand() * 600, rand() * 600 ], 27 | velocity => [ rand() * 20, rand() * 20 ], 28 | color => [ 255, 0, 0, 255 ] 29 | } 30 | 31 | 32 | } 33 | 34 | sub show_blocks{ 35 | $app->draw_rect( [ 0, 0, 600, 600 ], 0 ); 36 | 37 | foreach ( @{$walkers} ) { 38 | $app->draw_rect( [ @{ $_->{position} }, 5, 5 ], $_->{color} ); 39 | } 40 | 41 | $app->flip(); 42 | 43 | } 44 | 45 | sub move_blocks{ 46 | my $dt = shift; 47 | foreach ( @{$walkers} ) { 48 | 49 | $_->{position}->[0] += $_->{velocity}->[0] * $dt; 50 | $_->{velocity}->[0] *= -1 51 | if ( $_->{position}->[0] > 590 || $_->{position}->[0] < 0 ); 52 | $_->{position}->[1] += $_->{velocity}->[1] * $dt; 53 | $_->{velocity}->[1] *= -1 54 | if ( $_->{position}->[1] > 590 || $_->{position}->[1] < 0 ); 55 | 56 | } 57 | 58 | } 59 | 60 | $app->add_show_handler( \&show_blocks ); 61 | $app->add_move_handler( \&move_blocks ); 62 | 63 | $app->add_move_handler( sub {$app->stop() if $profile_counter++ > 100; } ); 64 | 65 | $app->run(); 66 | -------------------------------------------------------------------------------- /code_listings/bouncing.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use SDL; 5 | use SDL::Video; 6 | use SDL::Event; 7 | use SDL::Events; 8 | 9 | use SDLx::App; 10 | use SDLx::Controller::Interface; 11 | my $app = SDLx::App->new( w => 512, h => 512, dt => 0.02, flags => SDL_HWSURFACE|SDL_DOUBLEBUF ); 12 | my $ball = 13 | SDLx::Controller::Interface->new( x => 10, h => 10, v_x => 150, v_y => 150 ); 14 | 15 | $app->add_event_handler( sub { return 0 if $_[0]->type == SDL_QUIT; return 1 } 16 | ); 17 | 18 | $ball->set_acceleration( 19 | sub { 20 | my ( $time, $s ) = @_; 21 | if ( $s->x >= $app->w - 10 ) { 22 | $s->x( $app->w - 11 ); 23 | $s->v_x( -1 * $s->v_x ); 24 | } 25 | elsif ( $s->x <= 0 ) { 26 | $s->x(11); 27 | $s->v_x( -1 * $s->v_x ); 28 | } 29 | 30 | if ( $s->y >= $app->h - 10 ) { 31 | $s->y( $app->h - 11 ); 32 | $s->v_y( $s->v_y * -0.9 ); 33 | 34 | } 35 | elsif ( $s->y <= 0 ) { 36 | $s->y(11); 37 | $s->v_y( $s->v_y * -0.9 ); 38 | 39 | } 40 | return ( 0, 0, 0 ); 41 | } 42 | ); 43 | 44 | my $previous = [0,0,0,0]; 45 | $ball->attach( 46 | $app, 47 | sub { 48 | $app->draw_rect([0,0,$app->w, $app->h], 0 ); 49 | my $current = [ $_[0]->x, $_[0]->y, 10, 10 ]; 50 | $app->draw_rect( $current, 0xFF0000FF ); 51 | $app->update( $current ); 52 | $app->update( $previous ); 53 | $previous = $current; 54 | } 55 | ); 56 | 57 | $app->run(); 58 | 59 | -------------------------------------------------------------------------------- /code_listings/game_sdlx.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use SDL::Event; 5 | use SDLx::App; 6 | 7 | my $app = SDLx::App->new( 8 | width => 200, 9 | height => 200, 10 | title => 'Pew Pew' 11 | ); 12 | 13 | my $laser = 0; 14 | my $velocity = 10; 15 | 16 | #We can add an event handler 17 | $app->add_event_handler( \&quit_event ); 18 | 19 | #We tell app to handle the appropriate times to 20 | #call both rendering and physics calculation 21 | 22 | $app->add_move_handler( \&calculate_laser ); 23 | $app->add_show_handler( \&render_laser ); 24 | 25 | $app->run(); 26 | 27 | sub quit_event { 28 | 29 | #The callback is provided a SDL::Event to use 30 | my $event = shift; 31 | 32 | #Each event handler also returns you back the Controller call it 33 | my $controller = shift; 34 | 35 | #Stoping the controller for us will exit $app->run() for us 36 | $controller->stop if $event->type == SDL_QUIT; 37 | } 38 | 39 | sub calculate_laser { 40 | 41 | # The step is the difference in Time calculated for the 42 | # next jump 43 | my ( $step, $app, $t ) = @_; 44 | $laser += $velocity * $step; 45 | $laser = 0 if $laser > $app->w; 46 | } 47 | 48 | sub render_laser { 49 | my ( $delta, $app ) = @_; 50 | 51 | # The delta can be used to render blurred frames 52 | 53 | #Draw the background first 54 | $app->draw_rect( [ 0, 0, $app->w, $app->h ], 0 ); 55 | 56 | #Draw the laser 57 | $app->draw_rect( [ $laser, $app->h / 2, 10, 2 ], [ 255, 0, 0, 255 ] ); 58 | $app->update(); 59 | 60 | } 61 | -------------------------------------------------------------------------------- /code_listings/mouse_paint.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use SDL; 4 | use Cwd; 5 | use SDL::Event; 6 | use SDLx::App; 7 | 8 | my $app = SDLx::App->new( w => 600, h => 480, d => 32, title => "Simple Paint"); 9 | sub quit_event { 10 | 11 | my $event = shift; 12 | my $controller = shift; 13 | $controller->stop if $event->type == SDL_QUIT; 14 | 15 | } 16 | 17 | 18 | 19 | my @colors = ( 0xFF0000FF, 0x00FF00FF, 20 | 0x0000FFFF, 0xFFFF00FF, 21 | 0xFF00FFFF, 0x00FFFFFF, 22 | 0xCCFFCCFF, 0xFFCC33FF, 23 | 0x000000FF, 0xFFFFFFFF ); 24 | 25 | my $brush_color = 0; 26 | 27 | 28 | my $drawing = 0; 29 | sub mouse_event { 30 | 31 | my $event = shift; 32 | 33 | if($event->type == SDL_MOUSEBUTTONDOWN || $drawing) 34 | { 35 | 36 | $drawing = 1; 37 | my $x = $event->button_x; 38 | my $y = $event->button_y; 39 | $app->draw_rect( [$x,$y, 2, 2], $colors[$brush_color]); 40 | $app->update(); 41 | } 42 | $drawing = 0 if($event->type == SDL_MOUSEBUTTONUP ); 43 | } 44 | 45 | 46 | sub save_image { 47 | 48 | if( SDL::Video::save_BMP( $app, 'painted.bmp' ) == 0 && -e 'painted.bmp') 49 | { 50 | warn 'Saved painted.bmp to '.cwd(); 51 | } 52 | else 53 | { 54 | warn 'Could not save painted.bmp: '.SDL::get_errors(); 55 | } 56 | 57 | } 58 | 59 | 60 | sub keyboard_event { 61 | 62 | my $event = shift; 63 | my $controller = shift; 64 | if ( $event->type == SDL_KEYDOWN ) 65 | { 66 | my $key_name = SDL::Events::get_key_name( $event->key_sym ); 67 | 68 | $brush_color = $key_name if $key_name =~ /\d/; 69 | 70 | my $mod_state = SDL::Events::get_mod_state(); 71 | save_image if $key_name =~ /^s$/ && ($mod_state & KMOD_CTRL); 72 | 73 | $app->draw_rect( [0,0,$app->w, $app->h], 0 ) if $key_name =~ /^c$/; 74 | $controller->stop() if $key_name =~ /^q$/ 75 | } 76 | $app->update(); 77 | return 1; 78 | } 79 | 80 | 81 | $app->add_event_handler( \&quit_event ); 82 | $app->add_event_handler( \&mouse_event ); 83 | $app->add_event_handler( \&keyboard_event ); 84 | $app->run(); 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/01-first.pod: -------------------------------------------------------------------------------- 1 | =head0 The Screen 2 | 3 | X