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('#') # required
                ->add_void('.') # required
                ->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 (map lines are trimmed before processing).

    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).

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.