Problems? Is your data what you think it is? PerlMonks

2d field of view, vision algorithm in grid (ray casting)

by Discipulus (Abbot)
 on Jun 24, 2019 at 19:05 UTC Need Help??

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.

The ReadKey function can take octal values for timings so the program will self close after some time without a keypress.

while ( my \$key = ReadKey(010) ){

Create A New User
Node Status?
node history
Node Type: CUFP [id://11101830]
Approved by haukex
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2021-01-16 09:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
The STEM quote I most wish I'd made is:

Results (159 votes). Check out past polls.

Notices?