Codebase list pangzero / 09eba78 lib / Games / PangZero / MenuItem.pm
09eba78

Tree @09eba78 (Download .tar.gz)

MenuItem.pm @09eba78raw · history · blame

##########################################################################
package Games::PangZero::MenuItem;
##########################################################################

@ISA = qw(Games::PangZero::GameObject);
use strict;
use warnings;
use vars qw($Gravity);
$Gravity = 0.2;

sub new {
  my ($class, $x, $y, $text) = @_;
  my $self                   = Games::PangZero::GameObject->new();
  %{$self}                   = ( %{$self},
    'targetX'   => $x,
    'targetY'   => $y,
    'h'         => 42,
    'selected'  => 0,
    'filled'    => 0,
    'fillcolor' => SDL::Video::map_RGB($Games::PangZero::Background->format(), 0, 0, 128),
    'parameter' => 0,
    'tooltip'   => [ @_[4 .. $#_] ],
  );
  bless $self, $class;
  $self->SetText($text);
  $self->SetInitialSpeed();
  return $self;
}

sub Center {
  my $self         = shift;
  $self->{targetX} = ( $Games::PangZero::ScreenWidth - $self->{w} ) / 2;
}

sub Show {
  my $self = shift;
  return if $self->CanSelect();
  $self->SetInitialSpeed();
}

sub Hide {
  my $self        = shift;
  $self->SUPER::Clear();
  $self->{state}  = 'leaving';
  $self->{speedX} = rand(10) - 5;
}

sub HideAndDelete {
  my $self                   = shift;
  $self->Hide();
  $self->{deleteAfterHiding} = 1;
}

sub Delete {
  my $self          = shift;
  $self->{selected} = $self->{filled} = 0;
  $self->SUPER::Delete();
}

sub ApproachingSpeed {
  my ($position, $speed, $target) = @_;

  if ($position + $speed * abs($speed / $Gravity) / 2 > $target) {
    return $speed - $Gravity;
  } else {
    return $speed + $Gravity;
  }
}

sub Advance {
  my $self = shift;

  if ('entering' eq $self->{state}) {
    $self->{x}     += $self->{speedX};
    $self->{y}     += $self->{speedY};
    $self->{speedX} = ApproachingSpeed($self->{x}, $self->{speedX}, $self->{targetX});
    $self->{speedY} = ApproachingSpeed($self->{y}, $self->{speedY}, $self->{targetY});
    if ( abs($self->{x} - $self->{targetX}) + abs($self->{y} - $self->{targetY}) < 2 ) {
      $self->{x}     = $self->{targetX};
      $self->{y}     = $self->{targetY};
      $self->{state} = 'shown';
    }
  } elsif ('leaving' eq $self->{state}) {
    $self->{x}      += $self->{speedX};
    $self->{y}      += $self->{speedY};
    $self->{speedY} += $Gravity;
    if ($self->{y} > $Games::PangZero::PhysicalScreenWidth) {
      $self->{state} = 'hidden';
      $self->Delete() if $self->{deleteAfterHiding}
    }
  }
}

sub Draw {
  my $self = shift;

  return if $self->{state} eq 'hidden';
  $self->TransferRect();
  if ($self->{selected} or $self->{filled}) {
    SDL::Video::fill_rect($Games::PangZero::App, $self->{rect}, $self->{fillcolor});
  }
  SDLx::SFont::print_text( $Games::PangZero::App,$self->{x} + 5 +$Games::PangZero::ScreenMargin, $self->{y} + $Games::PangZero::ScreenMargin, $self->{text});
}

sub SetInitialSpeed {
  my $self        = shift;
  $self->{x}      = $self->{targetX} + rand(500) - 250;
  $self->{y}      = $Games::PangZero::PhysicalScreenHeight;
  $self->{speedY} = -sqrt( 2 * $Gravity * ($self->{y} - $self->{targetY}) );
  $self->{speedX} = 0;
  $self->{state}  = 'entering';
}

sub InternalSetText {
  my ($self, $text) = @_;
  $self->SUPER::Clear();
  $self->{text}     = $text;
  $self->{w}        = Games::PangZero::Graphics::TextWidth($text) + 10;
}

sub SetText {
  my ($self, $text)  = @_;
  $self->{parameter} = '';
  $self->{basetext}  = $text;
  $self->InternalSetText($text);
}

sub SetParameter {
  my ($self, $parameter) = @_;
  $self->{parameter}     = $parameter;
  $self->InternalSetText($self->{basetext} . ' ' . $parameter);
}

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

  foreach my $item (@Games::PangZero::GameObjects) {
    $item->{selected} = 0 if ref $item eq 'Games::PangZero::MenuItem';
  }
  $self->{selected} = 1;
  $Games::PangZero::Game->ShowTooltip( @{$self->{tooltip}} );
}

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

  return $self->{state} =~ /(?:entering|shown)/;
}

1;