Codebase list pangzero / upstream/latest lib / Games / PangZero / PanicGame.pm
upstream/latest

Tree @upstream/latest (Download .tar.gz)

PanicGame.pm @upstream/latestraw · history · blame

##########################################################################
package Games::PangZero::PanicGame;
##########################################################################

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

sub new {
  my ($class) = @_;
  my $self    = Games::PangZero::PlayableGameBase->new();
  %{$self}    = (%{$self},
    'spawndelay'     => 0,
    'superballdelay' => 0,
    'leveladvance'   => 0,
    'panicleveldesc' => undef,
  );
  bless $self, $class;
}

sub ResetGame {
  my $self                 = shift;
  $self->SUPER::ResetGame();
  $self->{spawndelay}      = 0;
  $self->{superballdelay}  = 2500 + $self->Rand(2500);  # 25sec - 50sec
  $self->{superballdelay} *= $Games::PangZero::DifficultyLevel->{superball};
}

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

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

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

  $levelIndex = ($level > $#Games::PangZero::PanicLevels) ? $#Games::PangZero::PanicLevels : $level;
  $self->{leveldesc} = $Games::PangZero::PanicLevels[$levelIndex];
  die unless $self->{leveldesc};
  $self->{leveladvance} = 0;
  $self->SUPER::SetGameLevel($level);
}

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

  $self->SpawnBalls() if $Games::PangZero::GamePause <= 0;
  $self->SUPER::AdvanceGame();
}

sub SpawnBalls {
  my $self = shift;
  my ($randmax, $rnd, $ballName, $balldesc, $deathBallCount, $earthquakeBallCount, $hasBonus);

  --$self->{superballdelay};
  if ($self->{superballdelay} <= 0) {
    push @Games::PangZero::GameObjects, (
      Games::PangZero::Ball::Spawn($Games::PangZero::BallDesc{sprintf('super%d', $self->Rand(2))}, -1, $self->Rand(40) < 20 ? 0 : 1) );
    $self->{superballdelay} = (2500 + $self->Rand(2000)) * $Games::PangZero::DifficultyLevel->{superball}; # 25sec - 45sec
  }

  --$self->{spawndelay};
  return if $self->{spawndelay} > 0;
  $deathBallCount = $earthquakeBallCount = -1;
  $randmax = 10000;
  while ($self->{spawndelay} <= 0) {
    if ($Games::PangZero::DifficultyLevel->{name} eq 'Miki') {
      $balldesc = $Games::PangZero::BallDesc{'death'};
      last;
    }
    $rnd     = int($self->Rand($randmax));
    $randmax = 0;

    # We try to find the balldesc that falls at $rnd
    my $ballRoulette = $self->{leveldesc}->{balls};
    for (my $i = 0; $i < scalar @{$ballRoulette}; $i+=2) {
      my $rouletteWeight = $ballRoulette->[$i+1];
      $randmax          += $rouletteWeight;
      $rnd              -= $rouletteWeight;
      if ($rnd < 0) {
        $ballName = $ballRoulette->[$i];
        last;
      }
    }
    next unless ($ballName); # $rnd too large.. We'll have a better $randmax this time!

    ($balldesc) = $Games::PangZero::BallDesc{$ballName};
    if ($balldesc->{class} eq 'DeathBall') {
      next unless $Games::PangZero::DeathBallsEnabled;
      $deathBallCount = Games::PangZero::DeathBall::CountDeathBalls() if $deathBallCount < 0; # Lazy counting
      next if $deathBallCount >= 2;
    }
    if ($balldesc->{class} eq 'EarthquakeBall') {
      next unless $Games::PangZero::EarthquakeBallsEnabled;
      $earthquakeBallCount = Games::PangZero::EarthquakeBall::CountEarthquakeBalls if $earthquakeBallCount < 0;
      next if $earthquakeBallCount >= 1;
    }
    if ($balldesc->{class} eq 'WaterBall') {
      next unless $Games::PangZero::WaterBallsEnabled;
    }
    if ($balldesc->{class} eq 'SeekerBall') {
      next unless $Games::PangZero::SeekerBallsEnabled;
    }
    last if $balldesc;
  }

  $hasBonus = 1 if ($balldesc->{width} >= 32) and ($self->Rand(1) < $Games::PangZero::DifficultyLevel->{bonusprobability});

  push @Games::PangZero::GameObjects, ( Games::PangZero::Ball::Spawn($balldesc, -1, $self->Rand(40) < 20 ? 0 : 1, $hasBonus) );
  $self->{spawndelay}  = $self->{leveldesc}->{spawndelay} * $balldesc->{spawndelay} * 50;
  $self->{spawndelay} /= ($Games::PangZero::NumGuys + 1) / 2;
  $self->{spawndelay} *= $Games::PangZero::DifficultyLevel->{spawnmultiplier};
}

sub OnBallPopped {
  my $self = shift;

  ++$self->{leveladvance};
  if ($self->{leveladvance} >= 18) {
    Games::PangZero::Music::PlaySound('level');
    $self->SetGameLevel($self->{level}+1);
  }
}

sub DrawLevelIndicator {
  my ($self, $x, $y) = @_;

  $self->{levelIndicatorRect} = SDL::Rect->new($x, $y, 140, $self->{scoreBoardHeight}) unless $self->{levelIndicatorRect};
  SDL::Video::fill_rect($Games::PangZero::App, $self->{levelIndicatorRect}, SDL::Video::map_RGB($Games::PangZero::App->format(), 0, 0, 0));
  SDL::Video::blit_surface($Games::PangZero::LevelIndicatorSurface2, SDL::Rect->new($x, $y, $Games::PangZero::LevelIndicatorSurface2->w, $Games::PangZero::LevelIndicatorSurface2->h),
                           $Games::PangZero::App,                    SDL::Rect->new($x, $y, 0, 0));
  SDL::Video::blit_surface($Games::PangZero::LevelIndicatorSurface, SDL::Rect->new(0, 0, 130 * $self->{leveladvance} / 17, 30), $Games::PangZero::App, SDL::Rect->new($x, $y, 0, 0));
  SDLx::SFont::print_text( $Games::PangZero::App, $x + 25, $y + 3, 'Level ' . ($self->{level}+1) );

  SDLx::SFont::print_text( $Games::PangZero::App, $x, $y + 40, sprintf('spd: %d/%d', $Games::PangZero::GameSpeed * 100, $self->{leveldesc}->{spawndelay}) ) if $self->{scoreBoardHeight} >= 64;

}

1;