The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Game::TileMap - Representation of tile-based two-dimensional rectangular maps

SYNOPSIS

        use Game::TileMap;

        # first, create a map legend

        my $legend = Game::TileMap->new_legend;

        $legend
                ->add_wall('#')
                ->add_void('.')
                ->add_terrain('_' => 'pavement')
                ->add_object('monster_spawns', 'a' => 'spawn_a')
                ->add_object('monster_spawns', 'b' => 'spawn_b')
                ->add_object('surroundings', '=' => 'chest')
                ;

        # next, create a map

        my $map_str = <<MAP;

        .__.......
        .__.......
        .__.......
        .__.......
        .__..#####
        .__..#a__=
        .__..#__b_
        ._________
        .__..#####
        .__.......
        .__.......

        MAP

        my $map = Game::TileMap->new(
                legend => $legend,
                map => $map_str
        );

        # map can be queried to get some info about its contents
        my @monsters = $map->get_all_of_class('monster_spawns');
        my @chests = $map->get_all_of_type('chest');
        my $true = $map->check_within_map(0, 5);
        my $false = $map->check_can_be_accessed(0, 5);

DESCRIPTION

Game::TileMap is a module which helps you build and store simple two-dimensional maps of tiles, where each tile contains only one element. Maps created from this module are generally considered immutable and should only be used to define a map, not to store its changing state.

Maps can be created out of strings or arrays of arrays and are stored as an array of array of Game::TileMap::Tile. Some helpful features are in place:

  • map markers (usually just single characters) are translated into objects specified in the legend

    Map characters can't be whitespace (whitespace is removed before processing - can be used for improved visibility).

    Legend objects can't be falsy, but other than that they can be anything (string, object, reference).

  • each legend object is assigned to a class, which you can query for later

    If you add a class surroundings:

            $legend->add_object('surroundings', '@' => 'trash bin')
                   ->add_object('surroundings', '=' => 'desk')
                   ->add_object('surroundings', 'H' => 'locker')
                   ->add_object('surroundings', 'L' => 'chair');

    Then you can easily get information about locations of those tiles on a map:

            my @all_surroundings = $map->get_all_of_class('surroundings');

    This array will contains blessed objects of Game::TileMap::Tile class.

  • you define how your maps look yourself

    Only predefined objects are walls (can't be accessed and are considered not a part of map) and voids (can't be accessed, but are a part of map). Their predefined class is terrain. You are free to introduce as many objects and classes as needed.

  • bottom-left corner of the stringified map is at [0;0], while top-right is at [max;max]

    This lets you think of a map like you think of a coordinate frame (first quarter).

  • map array has X coordinates in first dimension and Y coordinates in second dimension

    This way you can get more familiar notation:

            $map->coordinates->[3][5]; # actual point at [3;5]
  • supports multi-character maps

            my $legend = Game::TileMap->new_legend(characters_per_tile => 2);
    
            $legend
                    ->add_wall('##')
                    ->add_void('..')
                    ->add_terrain('__' => 'pavement')
                    ->add_terrain('_~' => 'mud')
                    ->add_terrain('_,' => 'grass')
            ;
    
            my $map_str = <<MAP;
            _, __ __ __ _~
            _, __ ## ## _~
            __ __ ## ## _~
            _, __ ## ## _~
            _, __ __ __ _~
            MAP

Attributes

legend

A reference to map legend. Required in constructor.

coordinates

The constructed map: array of array of Game::TileMap::Tile.

size_x

Horizontal size of the map.

size_y

Vertical size of the map.

Methods

new_legend

Static method which returns a new instance of Game::TileMap::Legend. Note that legends are reusable.

new

Moose-flavored constructor. Possible arguments are:

  • map => ArrayRef | Str

    Optional.

    Map input that will be passed to from_string or from_array.

  • legend => InstanceOf ['Game::TileMap::Legend']

    Required.

    Legend of the map, which describes its contents.

from_string

        my $map = Game::TileMap->new(legend => $legend);
        $map->from_string($map_str);

Creates a map from a string.

from_array

        my $map = Game::TileMap->new(legend => $legend);
        $map->from_array($map_aref);

Creates a map from an array.

to_string

Creates a string from a map.

to_string_and_mark

        print $map->to_string_and_mark([[1, 2], [1, 3]]);

        print $str = $map->to_string_and_mark([[5, 5]], 'X');

Creates a string from a map and marks given positions with a marker. The default marker is '!' (times the number of characters per tile).

Useful during debugging.

check_within_map

        my $bool = $map->check_within_map($pos_x, $pos_y);

Returns true if the given position is considered to be inside the map (not outside of bounds and not a wall).

Note that $pos_x and $pos_y can be decimal (not just integers).

check_can_be_accessed

        my $bool = $map->check_can_be_accessed($pos_x, $pos_y);

Returns true if the given position is considered accessible (not outside of bounds and not a wall or a void).

Note that $pos_x and $pos_y can be decimal (not just integers).

get_all_of_class

        my @arr = $map->get_all_of_class('class_name');

Returns all map objects (in form of Game::TileMap::Tile instances) that are assigned to a given class (found out by string equality check).

get_all_of_type

        my @arr = $map->get_all_of_type($object);

Returns all map objects (in form of Game::TileMap::Tile instances) that are of a given object type (found out by string equality check).

get_class_of_object

        my $class_name = $map->get_class_of_object($object);

Does the reverse of "get_all_of_class" for one $object, which can be either an instance of Game::TileMap::Tile or just a string.

SEE ALSO

Game::LevelMap is more suited for terminal games.

Games::Board is more focused on creating board games.

AUTHOR

Bartosz Jarzyna <bbrtj.pro@gmail.com>

COPYRIGHT AND LICENSE

Copyright (C) 2022 by Bartosz Jarzyna

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.