Games-PangZero

 view release on metacpan or  search on metacpan

lib/Games/PangZero/PlayableGameBase.pm  view on Meta::CPAN

##########################################################################
package Games::PangZero::PlayableGameBase;
##########################################################################

@ISA = qw( Games::PangZero::GameBase );

use strict;
use warnings;

sub new {
  my ($class) = @_;
  my $self    = Games::PangZero::GameBase->new();
  %{$self}    = (%{$self},
    'playersalive'   => 0,
    'level'          => 0,
    'backgrounds'    => [ qw( desert2.png l1.jpg  l2.jpg  l3.jpg  l4.jpg  l5.jpg  l6.jpg  l7.jpg  l8.jpg  l9.jpg )],
  );
  bless $self, $class;
}

sub ResetGame {
  my $self              = shift;
  $self->SUPER::ResetGame();
  $self->{playersalive} = 0;
  $Games::PangZero::GamePause  = 0;

  foreach my $player (@Games::PangZero::Players) {
    last if $player->{number} >= $Games::PangZero::NumGuys;
    $self->SpawnPlayer($player);
  }
  $self->SetGameLevel(0);
  $self->LayoutScoreBoard();
  push @Games::PangZero::GameObjects, (Games::PangZero::FpsIndicator->new());
}

sub SetGameSpeed {
  my $self = shift;

  $Games::PangZero::GameSpeed = 0.8 * $Games::PangZero::DifficultyLevel->{speed};
}

sub SetGameLevel {
  my ($self, $level) = @_;

  $self->{level} = $level;
  if (($level % 10) == 9) {
    $self->SetBackground( int($level / 10) + 1 );
  }
  $self->SetGameSpeed();
}

sub SpawnPlayer {
  my ($self, $player)          = @_;
  $player->{score}             = 0;
  $player->{scoreforbonuslife} = 200000;
  $player->{lives}             = 2;
  $player->{startX}            = ($Games::PangZero::ScreenWidth - $Games::PangZero::NumGuys * 60) / 2 + 60 * ($player->{number}+0.5) - 32;
  $player->{respawn}           = -1;
  my $guy                      = Games::PangZero::Guy->new($player);
  push @Games::PangZero::GameObjects, ($guy);
  ++$self->{playersalive};
  return $guy;
}

sub AdvanceGameObjects {
  my ($self) = @_;

  $self->SUPER::AdvanceGameObjects();
  $self->RespawnPlayers();
  --$Games::PangZero::GamePause if $Games::PangZero::GamePause > 0;
}

sub RespawnPlayers {
  my $self = shift;

  foreach my $player (@Games::PangZero::Players) {
    last if $player->{number} >= $Games::PangZero::NumGuys;
    if ($player->{respawn} > 0) {
      --$player->{respawn};
      $player->{score} = int($player->{respawn} / 100) if $self->{playersalive};
      if ($player->{respawn} <= 0) {
        my $guy            = $self->SpawnPlayer($player);
        $guy->{invincible} = 500;
      }
    }
  }
}

sub PlayerNextLife {
  my ($self, $guy) = @_;

  $guy->DeleteHarpoons;
  if ($guy->{player}->{lives}--) {
    $guy->{x}              = $guy->{player}->{startX};
    $guy->{y}              = $Games::PangZero::ScreenHeight - $guy->{h};
    $guy->{state}          = 'idle';
    $guy->{speedY}         = $guy->{speedX} = 0;
    $guy->{invincible}     = 500; # 0.5s
    $guy->{killed}         = 0;
    $guy->{justkilled}     = 0;
    $self->{playerspawned} = 1;
  } else {
    # One player less
    Games::PangZero::Highscore::AddHighScore($guy->{player}, $guy->{player}->{score}, $self->{level} + 1);
    $guy->Delete();
    --$self->{playersalive};
    $guy->{player}->{respawn} = 6000; # 60s
  }
}

sub PlayerDeathSequence {
  my $self = shift;
  my (@killedGuys, @deadGuys, $guy, $i);

  $self->DrawGame();
  Games::PangZero::Music::PlaySound('death');
  Games::PangZero::Graphics::RenderBorder($Games::PangZero::WhiteBorderSurface, $Games::PangZero::App);
  $Games::PangZero::App->sync();
  $self->Delay(10);
  Games::PangZero::Graphics::RenderBorder($Games::PangZero::RedBorderSurface, $Games::PangZero::App);
  Games::PangZero::Graphics::RenderBorder($Games::PangZero::RedBorderSurface, $Games::PangZero::Background);
  $Games::PangZero::App->sync();
  $self->Delay(90);

  @killedGuys = grep { $_->{justkilled}; } @Games::PangZero::GameObjects;
  foreach $guy (@killedGuys) {
    $guy->Clear();
    $guy->{killed} = 1;
    push @deadGuys, (Games::PangZero::DeadGuy->new($guy));
  }
  push @Games::PangZero::GameObjects, (@deadGuys);

  for ($i = 0; $i < 300; ++$i) {
    Games::PangZero::HandleEvents();
    return if $self->{abortgame};
    my $advance = $self->CalculateAdvances();
    while ($advance--) {
      foreach my $gameObject (@deadGuys) {
        $gameObject->Advance();
      }
    }
    $self->DrawGame();
    last if $deadGuys[0]->{deleted};
  }

  foreach $guy (@killedGuys) {
    $self->PlayerNextLife($guy);
  }

  Games::PangZero::Graphics::RenderBorder($Games::PangZero::BorderSurface, $Games::PangZero::App);
  Games::PangZero::Graphics::RenderBorder($Games::PangZero::BorderSurface, $Games::PangZero::Background);
}

sub SuperKill {
  my ($self, $guy) = @_;
  my @gameObjects  = @Games::PangZero::GameObjects;
  my $sound        = 0;
  foreach my $ball (@gameObjects) {
    next unless $ball->isa("Games::PangZero::Ball");
    $ball->Pop($guy, 'superkill');
    $sound = 1;
  }
  Games::PangZero::Music::PlaySound('pop') if $sound;
}

sub PopEveryBall {

lib/Games/PangZero/PlayableGameBase.pm  view on Meta::CPAN

    $dstrect->x($x + $i * 16);
    SDL::Video::blit_surface($player->{guySurface}, $srcrect, $Games::PangZero::App, $dstrect );
  }
}

sub DrawScore {
  my ($self, $player, $x, $y, $livesY) = @_;

  #SDL::Video::fill_rect( $Games::PangZero::App, $player->{scoreRect}, SDL::Color->new(0, 0, 0));
  $self->PrintNumber( $player, $x, $y, $player->{score});

  $livesY     = $self->{rowHeight} > 32 ? $y + 24 : $y + 16;
  my $dstrect = SDL::Rect->new($x, $livesY, 32, 32);
  my $srcrect = ($self->{rowHeight} <= 32)
              ? SDL::Rect->new(320, 176, 16, 16)
              : SDL::Rect->new(320, 128, 32, 32);

  if ($player->{lives} > 3) {
    SDL::Video::blit_surface($player->{guySurface}, $srcrect, $Games::PangZero::App, $dstrect );
    $self->PrintNumber( $player, $x + $srcrect->w() + 8, $livesY + ($srcrect->h() - 16 ) / 2, $player->{lives} );
  } else {
    foreach my $i ( 0 .. $player->{lives}-1 ) {
      $dstrect->x( $x + $i * ($srcrect->w() + 4) );
      SDL::Video::blit_surface($player->{guySurface}, $srcrect, $Games::PangZero::App, $dstrect );
    }
  }
}

sub PreAdvanceAction {}

sub AdvanceGame {
  my $self                     = shift;
  %Games::PangZero::GameEvents = ();
  $self->PreAdvanceAction(); # Hook for something special

  if ($self->{superKillCount} > 0) {
    if (--$self->{superKillDelay} <= 0) {
      --$self->{superKillCount};
      $self->{superKillDelay} = 50;
      $self->SuperKill($self->{superKillGuy});
    }
    $Games::PangZero::GamePause = 0;
  }

  $self->AdvanceGameObjects();
  if ($Games::PangZero::GameEvents{earthquake}) {
    Games::PangZero::Music::PlaySound('quake');
    foreach my $guy (@Games::PangZero::GameObjects) {
      $guy->Earthquake($Games::PangZero::GameEvents{earthquake}) if ref $guy eq 'Games::PangZero::Guy';
    }
  }

  if ($Games::PangZero::GameEvents{'pop'}) {
    Games::PangZero::Music::PlaySound('pop');
  }

  if ($Games::PangZero::GameEvents{meltdown} and $Games::PangZero::DifficultyLevel->{name} ne 'Miki') {
    $self->DeathballMeltdown();
  } elsif ($Games::PangZero::GameEvents{kill} ) {
    $self->PlayerDeathSequence();
    return if $self->{playersalive} <= 0;
    $Games::PangZero::GamePause = 200 if $Games::PangZero::GamePause < 200;
    Games::PangZero::GamePause::Show();
  } elsif ($Games::PangZero::GameEvents{magic}) {
    if ($Games::PangZero::GamePause < 200) {
      $Games::PangZero::GamePause = 200;
      Games::PangZero::Music::PlaySound('pause');
      Games::PangZero::GamePause::Show();
    }
  } elsif ($Games::PangZero::GameEvents{superpause}) {
    if ($Games::PangZero::GamePause < 800) {
      $Games::PangZero::GamePause = 800;
      Games::PangZero::Music::PlaySound('pause');
      Games::PangZero::GamePause::Show();
    }
  } elsif ($Games::PangZero::GameEvents{superkill}) {
    $self->{superKillCount}  = 5;
    $self->{superKillDelay}  = 0;
    $self->{superKillGuy}    = $Games::PangZero::GameEvents{superkillguy};
    $self->{spawndelay}      = 250;
    $self->{superballdelay} += 1000; # 10 second penalty
    my @gameObjects = @Games::PangZero::GameObjects;
    foreach my $spawningBall (@gameObjects) {
      $spawningBall->Delete if $spawningBall->{spawning};
    }
  }
}

sub Run {
  my ($self) = shift;

  $self->ResetGame();
  Games::PangZero::GameTimer::ResetTimer();

  $self->{superKillCount} = 0;
  $self->{superKillDelay} = 0;
  $self->{superKillGuy}   = undef;

  while (1) {

    # Calculate advance (how many game updates to perform)
    my $advance = $self->CalculateAdvances();

    # Advance the game

    %Games::PangZero::Events = ();
    Games::PangZero::HandleEvents();
    while ($advance--) {
      return if $self->{abortgame};
      $self->AdvanceGame();
    }

    if ($self->{playersalive} <= 0) {
      my $gameoverSurface = SDL::Image::load("$Games::PangZero::DataDir/gameover.png");
      my @gameObjects     = @Games::PangZero::GameObjects;
      foreach (@gameObjects) { $_->Delete() if ('Games::PangZero::DeadGuy' eq ref $_); }
      $self->DrawGame();
      SDL::Video::blit_surface($gameoverSurface, SDL::Rect->new(0, 0, $gameoverSurface->w, $gameoverSurface->h),
                               $Games::PangZero::App, SDL::Rect->new(
                                 ($Games::PangZero::PhysicalScreenWidth - $gameoverSurface->w) / 2, $Games::PangZero::PhysicalScreenHeight / 2 - 100,
                                 $gameoverSurface->w, $gameoverSurface->h));
      $Games::PangZero::App->sync();
      SDL::delay(1000);
      for (my $i=0; $i < 20; ++$i) {
        SDL::delay(100);
        %Games::PangZero::Events = ();
        Games::PangZero::HandleEvents();
        last if $self->{abortgame};
        last if %Games::PangZero::Events;
      }
      last;
    }
    $self->DrawGame();
  }
}

1;



( run in 1.473 second using v1.01-cache-2.11-cpan-39bf76dae61 )