http://qs321.pair.com?node_id=11101830

Hello community!

who knows me is aware I'm writing a game (engine?) and I asked here for the precious monks wisdom about circular area in a coordinates grid (AoA).

But now I'm progressing and I discovererd that the above illuminate function is not enough. I found a big resource of Roguelike_Vision_Algorithms and I choosed the simplest one (second example) and I ported it to Perl ( field_of_view sub in the below code ).

Impressed by this shiny exemple I wrapped into an interactive program to show my proof of concept:

```use strict;
use warnings;

# debug
my \$debug = 0;
# Point of View coordinates
my \$pov_coords = [15,15];
# sight range
# used to cast rays trough 360 degrees (default to 1)
# the map is an ArrayOfArrays taken from DATA
my @aoa;
my \$row = 0;
while(<DATA>){
chomp;
\$aoa[\$row] = [ map{ /\s/ ? '.' : \$_} split // ];
\$row++;
}

# first print of the map
local \$aoa[\$pov_coords->[0]][\$pov_coords->[1]]='X';
system ( \$^O =~ /mswin32/i ? 'cls' : 'clear') unless \$debug;
print "move the point of view X with wasd keys\n".
"+ or - to modify sight radius (now \$pov_radius)\nr to cycle stepp
field_of_view();
print_map();

# proof of concept loop
while ( my \$key = ReadKey(0) ){

system ( \$^O =~ /mswin32/i ? 'cls' : 'clear') unless \$debug;
# reinitialize the map
foreach my \$row (0..\$#aoa){
foreach my \$col( 0..\$#{\$aoa[\$row]} ){
\$aoa[\$row][\$col] = '.' unless \$aoa[\$row][\$col] eq 'O';
}
}
# movements and controls
if    (\$key eq 'w'){ \$pov_coords->[0]-- }
elsif (\$key eq 's'){ \$pov_coords->[0]++ }
elsif (\$key eq 'a'){ \$pov_coords->[1]-- }
elsif (\$key eq 'd'){ \$pov_coords->[1]++ }
elsif (\$key eq '+'){ \$pov_radius++ }
elsif (\$key eq '-'){ \$pov_radius-- }
+ }
else  { 0 }

print "move the point of view X with wasd keys\n".
"+ or - to modify sight radius (now \$pov_radius)\nr to cycle stepp
field_of_view();
local \$aoa[\$pov_coords->[0]][\$pov_coords->[1]]='X';
print_map();
}

# translated from:
# http://www.roguebasin.com/index.php?title=Eligloscode
sub field_of_view{
my \$i = 0;
my (\$x,\$y);

while ( \$i < 360 ){

\$x = cos( \$i * 0.01745);
\$y = sin( \$i * 0.01745);

my \$ox = \$pov_coords->[0] + 0.5;
my \$oy = \$pov_coords->[1] + 0.5;
# DEBUG
print "DEG \$i X \$x Y \$y OX \$ox OY \$oy\n" if \$debug;

# DEBUG
print "\t\$_ : intOX ".int(\$ox)." intOY ".int(\$oy)."\n" if
+\$debug;
next unless int(\$ox) >= 0                 and
int(\$ox) <= \$#{\$aoa[ 0 ]}         and
int(\$oy) >= 0                     and
int(\$oy) <= \$#aoa;

\$aoa[ int(\$ox) ][ int(\$oy) ] = ' '
if    \$aoa[ int(\$ox) ][ int(\$oy) ] ne 'O' and
\$aoa[ int(\$ox) ][ int(\$oy) ] ne 'X';

last if \$aoa[ int(\$ox) ][ int(\$oy) ] eq 'O';

\$ox+=\$x;
\$oy+=\$y;
}
}
}

sub print_map{
foreach my \$row (0..\$#aoa){
foreach my \$col( 0..\$#{\$aoa[\$row]} ){
print \$aoa[\$row][\$col];
}
print "\n";
}
}
__DATA__

OOO       OOOOOOOOOOOO OOOO
O OO    O      O          O
O  O    O      O     O  O O
O  O    O      OOOOOOO  O O
OOOO    OOOOOO            O
O            OOOOOOO  OOOOO
O                  O  O
O   OOOO           O  O
O   O           OOOO  OOOO
O           O
OOOO        O        O
O                    O
O           OOOOOO OOO
OOOOO            O O
OOOO      O OOOOO
O  O      O
OOO        O  O    OOO   OOO
OOO        OOOO          O
OOO   OOO  OO      OOOOO O
OOO   OOO  O O         O O
OOO  O  O   O    O O
O   O  O    O O
O    O O
OOOOOO            O    O O
OOO      O
OOO      O
OOOOOO   OOO      OOOO

Chatting in the perl irc channel daxim also implemented a semi-transparency feature I'd like to add to my game. Here daxim's patch (and a big thank to him):

```diff --git a/scpaste-585123.pl b/scpaste-585123.pl
index a23cf20..8fe0613 100644
--- a/scpaste-585123.pl
+++ b/scpaste-585123.pl
@@ -39 +39 @@ while ( my \$key = ReadKey(0) ){
-            \$aoa[\$row][\$col] = '.' unless \$aoa[\$row][\$col] eq 'O';
+            \$aoa[\$row][\$col] = '.' unless \$aoa[\$row][\$col] eq 'O' or
+\$aoa[\$row][\$col] eq '#';
@@ -66 +66 @@ sub field_of_view{
-
@@ -75 +75 @@ sub field_of_view{
+        for (my \$r = 0; \$r < \$radius; \$r++){
@@ -77 +77 @@ sub field_of_view{
-            print "\t\$_ : intOX ".int(\$ox)." intOY ".int(\$oy)."\n" if
+ \$debug;
+Y ".int(\$oy)."\n" if \$debug;
@@ -85,2 +85,6 @@ sub field_of_view{
-                    \$aoa[ int(\$ox) ][ int(\$oy) ] ne 'X';
-
+                    \$aoa[ int(\$ox) ][ int(\$oy) ] ne 'X' and
+                    \$aoa[ int(\$ox) ][ int(\$oy) ] ne '#';
+            if (\$aoa[ int(\$ox) ][ int(\$oy) ] eq '#') {
+                print "semi\n";
+            }
@@ -119 +123 @@ __DATA__
-      O           OOOOOO OOO
+      #           OOOOOO OOO

have fun!

L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re: 2d field of view, vision algorithm in grid (ray casting)
by Don Coyote (Friar) on Jun 29, 2019 at 08:39 UTC

The '-' ReadKey conditional goes into negative territory. That may cause some metaphysical disturbances for our X. I'd suggest limiting the lower end of visibility.