Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

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

by Discipulus (Abbot)
on Jun 24, 2019 at 19:05 UTC ( #11101830=CUFP: print w/replies, xml ) 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; use Term::ReadKey; ReadMode 'cbreak'; # debug my $debug = 0; # Point of View coordinates my $pov_coords = [15,15]; # sight range my $pov_radius = 5; # used to cast rays trough 360 degrees (default to 1) my @stepping_radius = (1,2,4,8,16,32); # 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 +ing radius (now $stepping_radius[ 0 ])\n"; 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-- } elsif ($key eq 'r'){ push @stepping_radius, shift @stepping_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 +ing radius (now $stepping_radius[ 0 ])\n"; 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; for ( 0..$pov_radius ){ # 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; } $i+= $stepping_radius[ 0 ]; } } 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{ - + my $radius = $pov_radius; # reinit from global @@ -75 +75 @@ sub field_of_view{ - for ( 0..$pov_radius ){ + for (my $r = 0; $r < $radius; $r++){ @@ -77 +77 @@ sub field_of_view{ - print "\t$_ : intOX ".int($ox)." intOY ".int($oy)."\n" if + $debug; + print "\t$r : r $r radius $radius intOX ".int($ox)." intO +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"; + $radius /= 2; + } @@ -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.

    elsif ($key eq '-'){ ! $pov_radius < 1 and $pov_radius-- }

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

Log In?
Username:
Password:

What's my password?
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 imbibing at the Monastery: (9)
As of 2019-10-22 16:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?