Game-LevelMap

 view release on metacpan or  search on metacpan

lib/Game/LevelMap.pm  view on Meta::CPAN

            if ( $cols != $newcols ) {
                croak 'unequal column length at row index ' . $#map;
            }
        } else {
            $cols = $newcols;
        }
    }
    $self->level( \@map );
    return $self;
}

# TODO this might buffer and only print what differs across successive
# calls (for less bandwidth over an SSH connection)
sub to_panel {
    my $self = shift;
    my ( $col, $row, $width, $height, $x, $y ) = map int, @_[ 0 .. 5 ];
    my $oobfn    = $_[6] // sub { return ' ' };
    my $lm       = $self->level;
    my $map_cols = $lm->$#*;
    my $map_rows = $lm->[0]->$#*;
    croak "x must be within the level map" if $x < 0 or $x > $map_cols;
    croak "y must be within the level map" if $y < 0 or $y > $map_rows;
    my $scol = $x - int( $width / 2 );
    my $srow = $y - int( $height / 2 );
    my $s    = '';

    for my $r ( $srow .. $srow + $height - 1 ) {
        $s .= "\e[" . $row++ . ';' . $col . 'H';
        for my $c ( $scol .. $scol + $width - 1 ) {
            if ( $c < 0 or $c > $map_cols or $r < 0 or $r > $map_rows ) {
                $s .= $oobfn->( $lm, $c, $r, $map_cols, $map_rows );
            } else {
                $s .= $lm->[$r][$c];
            }
        }
    }
    print $s;
    return $self;
}

sub to_string {
    my ($self) = @_;
    my $lm     = $self->level;
    my $s      = '';
    for my $rowref ( $lm->@* ) { $s .= join( '', $rowref->@* ) . $/ }
    return $s;
}

sub to_terminal {
    my $self = shift;
    my ( $col, $row ) = map int, @_;
    my $lm = $self->level;
    my $s  = '';
    for my $rowref ( $lm->@* ) {
        $s .= "\e[" . $row++ . ';' . $col . 'H' . join( '', $rowref->@* );
    }
    print $s;
    return $self;
}

sub update_terminal {
    my $self = $_[0];
    my ( $col, $row ) = map int, @_[ 1 .. 2 ];
    my $lm = $self->level;
    my $s  = '';
    for my $point ( @_[ 3 .. $#_ ] ) {
        $s .= "\e["
          . ( $row + $point->[1] ) . ';'
          . ( $col + $point->[0] ) . 'H'
          . $lm->[ $point->[1] ][ $point->[0] ];
    }
    print $s;
    return $self;
}

1;
__END__

=head1 NAME

Game::LevelMap - level map representation

=head1 SYNOPSIS

  use Game::LevelMap;

  my $lm = Game::LevelMap->new( from_string => <<'EOF' );
  .....
  .@.>.
  .....
  EOF

  print $lm->to_string;

  # the following methods may require buffering disabled
  STDOUT->autoflush(1);

  $lm->to_terminal( 1, 1 );

  # maybe instead there's a static border, indent
  $lm->to_terminal( 2, 2 );
  ...
  # several points on the map changed, update them
  $lm->update_terminal( 2, 2, [ 5, 2 ], [ 4, 2 ] );

  # complicated, see docs tests eg/panel-viewer
  $lm->to_panel( ... );

=head1 DESCRIPTION

A small level map implementation that uses characters (or strings
consisting of escape sequences or combining characters, or objects that
hopefully stringify themselves properly) in an array of arrays
representing a level map as might be used in a game.

  x cols
  y rows

Points use the geometric form (x,y) col,row which is backwards from what
terminal escape sequences use.



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