Created
October 9, 2009 16:32
-
-
Save kthakore/206164 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env perl | |
| use strict; | |
| use warnings; | |
| use lib 'lib'; | |
| use SDL; | |
| use SDL::App; | |
| use SDL::Color; | |
| use SDL::Event; | |
| use SDL::Mixer; | |
| use SDL::Rect; | |
| use SDL::Surface; | |
| use Bouncy::Brick; | |
| use Time::HiRes qw(time sleep); | |
| my $screen_width = 640; | |
| my $screen_height = 480; | |
| my $max_fps = 300; | |
| my $min_seconds_between_frames = 1 / $max_fps; | |
| my $app = SDL::App->new( | |
| -width => 640, | |
| -height => 480, | |
| -init => SDL_INIT_EVERYTHING | |
| # -flags => SDL_FULLSCREEN, | |
| ); | |
| my $mixer = SDL::Mixer->new( -frequency => 44100, -size => 4096 ); | |
| my $ping = SDL::Sound->new('ping'); | |
| my $explosion = SDL::Sound->new('explosion'); | |
| my $bounce = SDL::Sound->new('bounce'); | |
| my $app_rect = SDL::Rect->new( | |
| -height => $screen_height, | |
| -width => $screen_width, | |
| ); | |
| my $background_colour = $SDL::Color::yellow; | |
| my $ball = SDL::Surface->new( -name => 'ball2.png' ); | |
| $ball->display_format(); | |
| my $ball_rect = SDL::Rect->new( | |
| -x => 0, | |
| -y => 0, | |
| -width => $ball->width, | |
| -height => $ball->height, | |
| ); | |
| my $brick = SDL::Surface->new( -name => 'red.png' ); | |
| $brick->display_format(); | |
| my $brick_rect = SDL::Rect->new( | |
| -x => 0, | |
| -y => 0, | |
| -width => $brick->width, | |
| -height => $brick->height, | |
| ); | |
| Bouncy::Brick->surface($brick); | |
| Bouncy::Brick->rect($brick_rect); | |
| my @bricks = ( | |
| Bouncy::Brick->new( x => 0, y => 100 ), | |
| Bouncy::Brick->new( x => 64, y => 100 ), | |
| Bouncy::Brick->new( x => 128, y => 100 ), | |
| Bouncy::Brick->new( x => 192, y => 100 ), | |
| Bouncy::Brick->new( x => 256, y => 100 ), | |
| Bouncy::Brick->new( x => 0, y => 132 ), | |
| Bouncy::Brick->new( x => 64, y => 132 ), | |
| Bouncy::Brick->new( x => 128, y => 132 ), | |
| Bouncy::Brick->new( x => 192, y => 132 ), | |
| Bouncy::Brick->new( x => 256, y => 132 ), | |
| Bouncy::Brick->new( x => 0, y => 164 ), | |
| Bouncy::Brick->new( x => 0, y => 196 ), | |
| Bouncy::Brick->new( x => 0, y => 228 ), | |
| Bouncy::Brick->new( x => 0, y => 260 ), | |
| Bouncy::Brick->new( x => 0, y => 292 ), | |
| Bouncy::Brick->new( x => 0, y => 324 ), | |
| Bouncy::Brick->new( x => 576, y => 164 ), | |
| Bouncy::Brick->new( x => 576, y => 196 ), | |
| Bouncy::Brick->new( x => 576, y => 228 ), | |
| Bouncy::Brick->new( x => 576, y => 260 ), | |
| Bouncy::Brick->new( x => 576, y => 292 ), | |
| Bouncy::Brick->new( x => 576, y => 324 ), | |
| ); | |
| my $bat = SDL::Surface->new( -name => 'bat.png' ); | |
| $bat->display_format(); | |
| my $bat_rect = SDL::Rect->new( | |
| -x => 0, | |
| -y => 0, | |
| -width => $bat->width, | |
| -height => $bat->height, | |
| ); | |
| my $event = SDL::Event->new(); | |
| sub put_sprite { | |
| my ( $surface, $x, $y, $source, $source_rect ) = @_; | |
| my $dest_rect = SDL::Rect->new( | |
| -x => $x, | |
| -y => $y, | |
| -width => $source->width, | |
| -height => $source->height, | |
| ); | |
| $source->blit( $source_rect, $surface, $dest_rect ); | |
| return $dest_rect; | |
| } | |
| my $bat_x = 100; | |
| my $bat_y = $screen_height - $bat->height; | |
| my ( $x, $y ) = ( $bat_x + 54, $bat_y ); | |
| my $ball_xv = 300; # pixels per second | |
| my $ball_yv = -1000; # pixels per second | |
| my $gravity = 1250; # pixels per second per second | |
| my @xs = ($x); | |
| my @ys = ($y); | |
| my $background = SDL::Surface->new( | |
| -flags => SDL_SWSURFACE, | |
| -width => $screen_width, | |
| -height => $screen_height, | |
| ); | |
| $background->display_format(); | |
| $background->fill( $app_rect, $background_colour ); | |
| foreach my $brick (@bricks) { | |
| put_sprite( $background, $brick->x, $brick->y, $brick->surface, | |
| $brick->rect ); | |
| } | |
| #$background->update($app_rect); | |
| #warn "frame"; | |
| $background->blit( $app_rect, $app, $app_rect ); | |
| #$app->update($app_rect); | |
| $app->sync; | |
| SDL::ShowCursor(0); | |
| my $this_frame_time = time; | |
| my $last_frame_time = $this_frame_time; | |
| my $last_frame_sleep = 0; | |
| my $last_measured_fps_time = time; | |
| my $last_measured_fps_frames = 0; | |
| my $frames = 0; | |
| while (1) { | |
| my $now = time; | |
| #warn "frame"; | |
| $last_frame_time = $this_frame_time; | |
| $this_frame_time = $now; | |
| my $last_frame_seconds = $this_frame_time - $last_frame_time; | |
| if ( $now - $last_measured_fps_time > 1 ) { | |
| my $fps = ( $frames - $last_measured_fps_frames ) | |
| / ( $now - $last_measured_fps_time ); | |
| # printf( "%0.2f FPS\n", $fps ); | |
| $last_measured_fps_frames = $frames; | |
| $last_measured_fps_time = $now; | |
| } | |
| #warn $last_frame_seconds, ' <?' , $min_seconds_between_frames; | |
| if ( $last_frame_seconds < $min_seconds_between_frames ) { | |
| #warn "sleep"; | |
| my $seconds_to_sleep | |
| = $min_seconds_between_frames - $last_frame_seconds; | |
| my $actually_slept = sleep($seconds_to_sleep); | |
| $last_frame_sleep = $actually_slept; | |
| #warn " slept for $seconds_to_sleep = $last_frame_sleep"; | |
| $this_frame_time = time + $seconds_to_sleep - $actually_slept; | |
| } else { | |
| $last_frame_sleep = 0; | |
| } | |
| $frames++; | |
| my @updates; | |
| # process event queue | |
| $event->pump; | |
| # handle user events | |
| my $event = SDL::Event->new; | |
| while ( $event->poll() ) { | |
| my $etype = $event->type; | |
| exit if ( $etype eq SDL_QUIT ); | |
| exit if ( SDL::GetKeyState(SDLK_ESCAPE) ); | |
| exit if ( $etype eq SDL_KEYDOWN ); | |
| if ( $etype eq SDL_MOUSEBUTTONDOWN ) { | |
| $x = $bat_x + $bat->width / 3; | |
| $y = $bat_y; | |
| $ball_xv = 300; | |
| $ball_yv = -1000; | |
| } | |
| if ( $etype eq SDL_MOUSEMOTION ) { | |
| my $bat_background_rect = SDL::Rect->new( | |
| -x => $bat_x, | |
| -y => $bat_y, | |
| -width => $bat->width, | |
| -height => $bat->height, | |
| ); | |
| $background->blit( $bat_background_rect, $app, | |
| $bat_background_rect ); | |
| push @updates, $bat_background_rect; | |
| $bat_x = $event->motion_x - 56; | |
| $bat_x = 0 if $bat_x < 0; | |
| $bat_x = $screen_width - 112 if $bat_x + 112 > $screen_width; | |
| } | |
| } | |
| # draw tail | |
| if (0) { | |
| SDL::GFXAalineRGBA( | |
| $$app, $x, | |
| $y - $ball->height / 2, | |
| $xs[0] + $ball->width / 2, | |
| $ys[0] - $ball->height / 2, | |
| 0, 127, 127, 255 | |
| ); | |
| SDL::GFXAalineRGBA( | |
| $$app, | |
| $x + $ball->width, | |
| $y - $ball->height / 2, | |
| $xs[0] + $ball->width / 2, | |
| $ys[0] - $ball->height / 2, | |
| 0, 127, 127, 255 | |
| ); | |
| } | |
| my $ball_background_rect = SDL::Rect->new( | |
| -x => $xs[-1], | |
| -y => $ys[-1] - $ball->height, | |
| -width => $ball->width, | |
| -height => $ball->height, | |
| ); | |
| $background->blit( $ball_background_rect, $app, $ball_background_rect ); | |
| push @updates, $ball_background_rect; | |
| push @updates, | |
| put_sprite( $app, $x, $y - $ball->height, $ball, $ball_rect ); | |
| push @updates, put_sprite( $app, $bat_x, $bat_y, $bat, $bat_rect ); | |
| push @xs, $x; | |
| push @ys, $y; | |
| if ( @xs > 80 ) { | |
| shift @xs; | |
| shift @ys; | |
| } | |
| my $dx = $ball_xv * ( $last_frame_seconds + $last_frame_sleep ); | |
| $x += $dx; | |
| if ( $x + $ball->width > $screen_width ) { | |
| $ball_xv = $ball_xv * -0.9; | |
| $ball_yv = $ball_yv * 0.9; | |
| $x -= $dx; | |
| play_ping(); | |
| } | |
| if ( $x < 0 ) { | |
| $ball_xv = $ball_xv * -0.9; | |
| $ball_yv = $ball_yv * 0.9; | |
| $x -= $dx; | |
| play_ping(); | |
| } | |
| $ball_yv += $gravity * ( $last_frame_seconds + $last_frame_sleep ); | |
| my $dy = $ball_yv * ( $last_frame_seconds + $last_frame_sleep ); | |
| $y += $dy; | |
| if ( ( $x + $ball->width / 2 > $bat_x && $x < $bat_x + 108 ) | |
| && $y > $screen_height - $bat->height + 5 ) | |
| { | |
| $ball_yv = -1000; | |
| $ball_xv | |
| = 0.3 * $ball_xv + ( $x + $ball->width / 2 - $bat_x - 56 ) * 4; | |
| $y -= $dy; | |
| play_bounce(); | |
| } elsif ( $y > $screen_height ) { | |
| $ball_yv = $ball_yv * -0.7; | |
| $ball_xv = $ball_xv * 0.7; | |
| $y -= $dy; | |
| play_ping() if $dy > 0.2; | |
| } | |
| if ( $y - $ball->height < 0 ) { | |
| $ball_yv = $ball_yv * -1.1; | |
| $ball_xv = $ball_xv * 0.9; | |
| $y -= $dy; | |
| play_ping(); | |
| } | |
| foreach my $brick (@bricks) { | |
| next unless $brick->visible; | |
| if ( $x > $brick->x - $ball->width | |
| && $x < $brick->x + $brick->w | |
| && $y > $brick->y | |
| && $y < $brick->y + $brick->h + $ball->height ) | |
| { | |
| if ( $ys[-1] > $brick->y | |
| && $ys[-1] < $brick->y + $brick->h + $ball->height ) | |
| { | |
| $ball_xv = $ball_xv * -0.9; | |
| $x -= $dx; | |
| } else { | |
| $ball_yv = $ball_yv * -0.9; | |
| $y -= $dy; | |
| } | |
| my $brick_background_rect = SDL::Rect->new( | |
| -x => $brick->x, | |
| -y => $brick->y, | |
| -width => $brick->w, | |
| -height => $brick->h, | |
| ); | |
| $background->fill( $brick_background_rect, $background_colour ); | |
| $app->fill( $brick_background_rect, $background_colour ); | |
| push @updates, $brick_background_rect; | |
| $brick->visible(0); | |
| play_explosion(); | |
| last; | |
| } | |
| } | |
| $app->sync(); | |
| } | |
| sub play_ping { | |
| $mixer->play_channel( -1, $ping, 0 ); | |
| } | |
| sub play_explosion { | |
| $mixer->play_channel( -1, $explosion, 0 ); | |
| } | |
| sub play_bounce { | |
| $mixer->play_channel( -1, $bounce, 0 ); | |
| } | |
| SDL::ShowCursor(1); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment