Game::RaycastFOV - raycast field-of-view and related routines
use Game::RaycastFOV qw(bypair circle line); bypair( { my ($x,$y) = @_; ... } $x1, $y1, $x2, $y2, ...); # Bresenham in XS circle( { my ($cx,$cy) = @_; ... } $x, $y, $radius); line( { my ($lx,$ly) = @_; ... } $x0, $y0, $x1, $y1); raycast( \&circle, sub { ... }, $x, $y, ...); # alternative (faster, slower) circle constructions cached_circle( { my ($cx,$cy) ... } $x, $y, $radius) swing_circle( { my ($cx,$cy) ... } $x, $y, $radius, $swing);
This module contains various subroutines for fast integer calculation of lines and circles (and a slow one, too) that help perform Field Of View (FOV) calculations to show what cells are visible from a given cell via raycasting out from that cell. Raycasting visits adjacent squares lots especially as the FOV grows so will benefit from caching and more closed-in than open level layouts.
.#.## .##.##### # #.##..##... #. .##.#.##.#... #. #####..#.#### # #. .#.#.#.###.##.. #.#.## ####....#.##... #....# ##...#.@#....## #.@# #..#.###....#.# ###.. .##.#####..#... #.. .##...####.## ##.# ....#.###.#.. . ###.###.#.. .######.# ....#
Utility function for slicing up an arbitrary list pairwise. Sort of like pairwise of List::Util only in a void context, and that returning the value -1 from the callback subroutine will abort the processing of subsequent items in the input list.
pairwise
-1
This routine looks up the radius in the %circle_points variable (which can be modified by users of this module) to obtain a pre-computed list of circle points that are fed to the callback as is done for the circle call.
%circle_points
Will silently do nothing if the radius is not found in the cache. This is by design so that cached_circle is fast.
NOTE these cached points may change without notice; applications should if necessary set their own specific sets of points to use.
Bresenham circle via fast integer math. Note that this may not produce a completely filled-in FOV at various radius. Also note that this call will produce duplicate values for various points, especially for small radius.
Bresenham line via fast integer math. Returning the value -1 from the callback subroutine will abort the processing of the line at the given point.
Given a circle-fn such as circle or swing_circle, the raycast calls line between x and y and the points returned by the circle function; line in turn will call the user-supplied point-fn to handle what should happen at each raycasted point. Additional arguments ... will be passed to the circle-fn following x and y (the center of the circle. "EXAMPLES" may be of more help?
Constructs points around the given radius by rotating a ray by swing radians over a complete circle. Smaller swing values will result in a more complete circle at the cost of additional CPU and memory use.
cached_circle uses values pre-computed from this call but only for specific radius.
See also the eg/ directory of this module's distribution.
eg/
https://github.com/thrig/ministry-of-silly-vaults/ has a FOV subdirectory with example scripts.
use Game::RaycastFOV qw(circle raycast swing_circle); use Math::Trig 'deg2rad'; # to only draw within the map area our $MAX_X = 79; our $MAX_Y = 23; # assuming a rows/columns array-of-arrays with characters our @map = ( ... ); sub plot { ... } my ($x, $y, $radius) = ...; raycast( \&circle, sub { my ($lx, $ly) = @_; # whoops line has wandered outside of map return -1 if $lx < 0 or $lx > $MAX_X or $ly < 0 or $ly > $MAX_Y; # may instead build up a string to print to terminal my $ch = $map[$ly][$lx]; plot($lx, $ly, $ch); # abort the line if FOV is blocked return -1 if $ch eq '#'; }, $x, $y, $radius ); # or instead using swing_circle raycast( \&swing_circle, sub { my ($lx, $ly) = @_; return -1 if $lx < 0 or $lx > $MAX_X or $ly < 0 or $ly > $MAX_Y; my $ch = $map[$ly][$lx]; plot($lx, $ly, $ch); return -1 if $ch eq '#'; }, $x, $y, $radius, deg2rad(5) # different arguments! );
The plot routine should cache whether something has been printed to the given cell to avoid repeated terminal or display updates.
or patches might best be applied towards
https://github.com/thrig/Game-RaycastFOV
List::Util, NetHack::FOV
https://github.com/thrig/ministry-of-silly-vaults/
There are other FOV algorithms and implementations to be found on the Internet.
thrig - Jeremy Mates (cpan:JMATES) <jeremy.mates at gmail.com>
<jeremy.mates at gmail.com>
This software is Copyright (c) 2020 by Jeremy Mates.
This is free software, licensed under:
The (three-clause) BSD License
To install Game::RaycastFOV, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Game::RaycastFOV
CPAN shell
perl -MCPAN -e shell install Game::RaycastFOV
For more information on module installation, please visit the detailed CPAN module installation guide.