JonPerl has asked for the wisdom of the Perl Monks concerning the following question:

#!/usr/bin/perl use strict; $| = 1; my @map =([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]); my @char = (8,4); my %chir = {'xposition' => $char[0], 'ypostion' => $char[1]}; my $game = 1; #set to 0 for false while($game){ for (my $i=0;$i<@map;$i++){ for (my $p=0;$p<@{$map[$i]};$p++){ if(($i==8)&&($p==4)){ print("@"); } elsif($map[$i]->[$p]==0){ print(" "); } elsif($map[$i]->[$p]==1){ print("*"); } print(" "); } print("\n"); } for (my $i=0;$i<@map;$i++){ for (my $p=0;$p<@{$map[$i]};$p++){ print "\b" x 1; } print "\b" x 1; } }
ok so basically Im tying to draw a map using ASCII and then erase it then redraw it so it refreshes and people can see updates (like my "@" char moving across the screen). I have no idea how to get it to work and my current code isnt working.

Replies are listed 'Best First'.
Re: How do I get my ascii tile code to refresh without looking weird
by Joost (Canon) on Sep 12, 2007 at 18:20 UTC
Re: How do I get my ascii tile code to refresh without looking weird
by superfrink (Curate) on Sep 12, 2007 at 18:15 UTC
    The following bit of scrolling banner code might help. It uses the "\b" character to erase characters from the terminal.

    For anything more advanced I would look for a curses module on CPAN.

    #! /usr/bin/perl -w # # file: banner-1.pl # purpose: try to write a scrolling banner # details: this script shows how to implement a scrolling banner # that will run in a xterm window. # # author: chad c d clark # created: 2006-05-21 # # based on the following code by Chris Angell: # perl -e'$|++; 1 while select("","","",.04), # print "\b", qw(/ - \ |)[$i++%4]' # # $Id$ use strict; use POSIX; # ceil() # my $MESG = "This is my test message. "; # my $SIZE = 70; # #my $SIZE = 10; # my $MESG = " " . `/usr/bin/w | /usr/bin/sed 2d`; chomp $MESG; # my $SIZE = 70; my $MESG = qq{ The reason I'm so excited is it looks like if you plot price against profit, you get a nice curve with a big hump in the middle! And we all + know what humps mean! Humps mean local maxima! Or camels. But here they mea +n local maxima! - Joel Spolsky }; my $SIZE = 70; $|++; # do not buffer output I/O # remove "non-printable" characters (for example newlines) if ($MESG =~ s/[^[:print:]]/ /g) { print STDERR "$0: Warning removing non-printable characters from m +essage.\n"; } my $offset = 0; # start at beginning of the message my $length = length $MESG; # get the length of the message # to simulate a circular buffer the idea is to append the message stri +ng # to itself until we have enough extra to cover the display window. my $mult = ceil( ($length + $SIZE) / $length ); $MESG = $MESG x $mult; print "Text: "; # prime the loop for the space where the message will be printed print " " x $SIZE; while (1) { # get a chunk of the message my $chunk = substr $MESG, $offset, $SIZE; # print the chunk over the the last iteration print "\b" x $SIZE, $chunk; select("","","",.15); # sleep for part of a second # advance/wrap the offset pointer if (++$offset >= $length) { $offset = 0 }; } exit(0);
Re: How do I get my ascii tile code to refresh without looking weird
by Anno (Deacon) on Sep 12, 2007 at 18:53 UTC
    So essentially you want to show an animated image of your game map that shows a "@" moving around. The following code shows a simple solution, based on the assumption that your system has a clear command that prints the character sequence to clear the screen.

    The main difference to your approach is that it sets up the entire image as an array of lines instead of printing every character as it comes along. This is done by the sub image(). It uses the core module Time::HiRes to set the frame rate with sub-second resolution. The "@" is moved through a sample of six positions and back again.

    use Time::HiRes qw( sleep); use constant SIZE => 15; my @map = do { my @ones = ( 1) x SIZE; my @mixed = ( 1, ( 0) x (SIZE - 2), 1); ( [ @ones], map( [ @mixed], 1 .. SIZE - 2), [ @ones], ); }; my @positions = ( [ 8, 4], [ 9, 5], [ 10, 6], [10, 7], [10, 8], [ 10, +9]); my $clear_string = `clear`; for my $pos ( @positions, reverse @positions ) { print $clear_string; print image( \ @map, @$pos); sleep 0.2; } exit; sub image { my ( $map, $x, $y) = @_; my @image = map join( '', map $_ ? '* ' : ' ', @$_), @$map; $_ .= "\n" for @image; substr( $image[ $y], 2*$x, 1) = '@'; @image; }
    Anno