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.