Game-TileMap

 view release on metacpan or  search on metacpan

lib/Game/TileMap/Legend.pm  view on Meta::CPAN

use constant VOID_OBJECT => 'void';

has field 'classes' => (
	default => sub { {} },

	# isa => HashRef [ ArrayRef [Str]],
);

has param 'characters_per_tile' => (
	default => sub { 1 },

	# isa => PositiveInt,
);

has field '_object_map' => (
	lazy => 1,

	# isa => HashRef [Str],
);

has field 'objects' => (
	default => sub { {} },

	# isa => HashRef [Any],
);

has field 'walls' => (
	default => sub { {} },

	# isa => HashRef [Bool],
);

has field 'voids' => (
	default => sub { {} },

	# isa => HashRef [Bool],
);

sub _build_object_map
{
	my $self = shift;
	my %classes = %{$self->classes};
	my %objects = %{$self->objects};
	my %map_reverse;

	foreach my $class (keys %classes) {
		my @objects = map { $objects{$_} } @{$classes{$class}};
		foreach my $obj (@objects) {
			$map_reverse{$obj} = $class;
		}
	}

	return \%map_reverse;
}

sub get_class_of_object
{
	my ($self, $obj) = @_;

	return $self->_object_map->{$obj}
		// croak "no such object '$obj' in map legend";
}

sub add_wall
{
	my ($self, $marker, $object) = @_;
	$object //= WALL_OBJECT;

	$self->add_terrain($marker, $object);
	$self->walls->{$object} = !!1;
	return $self;
}

sub add_void
{
	my ($self, $marker, $object) = @_;
	$object //= VOID_OBJECT;

	$self->add_terrain($marker, $object);
	$self->voids->{$object} = !!1;
	return $self;
}

sub add_terrain
{
	my ($self, $marker, $object) = @_;

	return $self->add_object(TERRAIN_CLASS, $marker, $object);
}

sub add_object
{
	my ($self, $class, $marker, $object) = @_;

	croak "marker '$marker' is already used"
		if exists $self->objects->{$marker};

	croak "marker '$marker' has wrong length"
		unless length $marker == $self->characters_per_tile;

	push @{$self->classes->{$class}}, $marker;
	$self->objects->{$marker} = $object;

	return $self;
}

1;

__END__

=head1 NAME

Game::TileMap::Legend - Map contents description

=head1 DESCRIPTION

All object classes must be string.

All map markers are strings with length equal to L</characters_per_tile>. Don't
use whitespace - it is removed before parsing, so can be used freely to improve
map readability, especially for multicharacter tiles.

All objects can be anything, but not C<undef>. String probably works best.

=head2 Attributes

=head3 characters_per_tile

The number of characters (horizontal only) than are used to define one tile.

Optional in the constructor. Default: C<1>

=head2 Methods

=head3 new

Moose-flavored constructor. See L</Attributes> for a list of possible arguments.

Note: it may be easier to call L<Game::TileMap/new_legend>.

=head3 add_wall

	$legend = $legend->add_wall($marker, $wall_object);

Defines a marker used to store a wall. You are required to set this.

C<$wall_object> is not required, by default it will be just C<'wall'>. You may
have more than one wall object.

Walls are considered not a part of the map. Think of them as physical obstacles.

=head3 add_void

	$legend = $legend->add_void($marker, $void_object);

Defines a marker used to store a void. You are required to set this.

C<$void_object> is not required, by default it will be just C<'void'>. You may
have more than one void object.

Voids are considered a part of the map, but they are not accessible. Think of
them as chasms which you can see over, but can't walk over.

=head3 add_terrain

	$legend = $legend->add_terrain($marker => $object);

Same as C<< add_object('terrain', $marker => $object) >>.

=head3 add_object

	$legend = $legend->add_object('class', $marker => $object);

Adds a new object with a given class and marker.

=head3 get_class_of_object

	my $class = $legend->get_class_of_object($object);

Returns the object class for a given object defined in the legend.



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