[snip code]
I think that this looks a bit better.
[snip code]
But there is so much that could be done with this.
Hmm. I don't think *either* of those look terribly "Matrix-like".
Niether does this particularly, but it was entertaining to write.
#!/user/bin/perl
# Set the randomness to zero and you have Rain.
# Set the randomness low WRT Velocity and you have Swarm
# Set the randomness high WRT Velocity and you have Brownian Motion
use strict;
use warnings;
use Tk;
my $top = MainWindow->new();
my $maxobj = 50;
my $maxvel = 15;
my $run = 0;
my ($height,$width,$maxx, $maxy, $minx, $miny);
my @objects;
my @printable;
my $color = '';
my $randomness = 4;
$minx = $miny = 0;
for (20 .. 255){
push @printable, chr($_) if (chr($_) =~ /\p{Print}/);
}
my $canvas = $top->Canvas(
-background => 'black'
)->pack(-fill => 'both', -expand => 'y');
$top->bind('<Configure>' => sub {
$top->XEvent;
$maxx = $canvas->width - $minx;
$maxy = $canvas->height - $miny;
}
);
my $frame = $top->Frame->pack;
$frame->Label(
-text => 'Number of objects',
)->grid(-row => 1, -column => 0);
my $maxobjentry = $frame->Entry(
-textvariable => \$maxobj,
-width => 5
)->grid(-row => 1, -column => 1);
$frame->Label(
-text => 'Maximum Velocity'
)->grid(-row => 1, -column => 2);
my $maxventry = $frame->Entry(
-textvariable => \$maxvel,
-width => 5,
-validate => 'all',
-vcmd => sub{
if ($_[0] =~ /[^\d]+/){
return 0;
}else{
return 1;
}
}
)->grid(-row => 1, -column => 3);
$frame->Label(
-text => 'Randomness'
)->grid(-row => 1,-column => 4);
my $maxrandentry = $frame->Entry(
-textvariable => \$randomness,
-width => 5,
-validate => 'all',
-vcmd => sub{
if ($_[0] =~ /[^\d]+/){
return 0;
}else{
return 1;
}
}
)->grid(-row => 1,-column => 5);
$frame->Button(
-text => 'Start',
-command => sub{ $run = 1; setup(); run_it();},
-width => 6,
)->grid(-row => 1, -column => 6);
$frame->Button(
-text => 'Pause',
-command => sub{
$run = 0;
$maxobjentry->configure(-state => 'normal');
},
-width => 6,
)->grid(-row => 1, -column => 7);
$frame->Button(
-text => 'Resume',
-command => sub{ $run = 1; run_it(); },
-width => 6,
)->grid(-row => 1, -column => 8);
my @letters = split //,'Not "The Matrix")';
for (0..$#letters){
$objects[$_]{object} = $canvas->createText((120+$_*18),100,
-text => $letters[$_],
-fill => 'light green',
-font => '-*-Courier-Medium-R-Normal--*-280-*-*-*-*-*-*'
);
}
$maxventry->bind($maxventry, '<Up>' => sub { $maxvel++ });
$maxventry->bind($maxventry, '<Down>' => sub { $maxvel-- });
$maxrandentry->bind($maxrandentry, '<Up>' => sub { $randomness++ });
$maxrandentry->bind($maxrandentry, '<Down>' => sub { $randomness-- });
$top->protocol('WM_DELETE_WINDOW' => sub{$run = 0, $top->update; $top->destroy});
MainLoop;
sub setup{
return unless $run;
$maxobjentry->configure(-state => 'disabled');
if (@objects){
for (@objects){
$canvas->delete($$_{object});
}
@objects = ();
}
my @fnames = qw/Times Hevatica Courier/;
for (0 .. $maxobj-1){
my $x = int(rand($maxx));
my $y = int(rand($maxy));
for (0 .. 2){
my $rgb = unpack('H*', pack('n', (int(rand(192)+64))));
$rgb =~ s/.+(\w\w)$/$1/;
$color .= $rgb;
}
my $font = '-*-'.$fnames[int(rand(2)+.5)].'-Medium-R-Normal--*-'.(int(rand(40)+20)*10).'-*-*-*-*-*-*';
$objects[$_]{velx} = 0;
$objects[$_]{vely} = int(rand($maxvel)+1);
$objects[$_]{object} = $canvas->createText($x, $y,
-text => $printable[int(rand(@printable))],
-fill => '#'.$color,
-font => $font
);
$color = '';
}
}
sub run_it{
while ($run) {
$maxvel = 0 if ($maxvel !~ /\d/);
$randomness = 0 if ($randomness !~ /\d/);
for(0 .. $#objects){
$objects[$_]{velx} += int(rand($randomness*2)+.5)-$randomness if $randomness;
$objects[$_]{vely} += int(rand($randomness*2)+.5)-$randomness if $randomness;
$objects[$_]{velx} = $maxvel if ($objects[$_]{velx} > $maxvel);
$objects[$_]{velx} = -$maxvel if ($objects[$_]{velx} < -$maxvel);
$objects[$_]{vely} = $maxvel if ($objects[$_]{vely} > $maxvel);
$objects[$_]{vely} = -$maxvel if ($objects[$_]{vely} < -$maxvel);
$canvas->move($objects[$_]{object}, $objects[$_]{velx}, $objects[$_]{vely});
my ($x,$y) = $canvas->coords($objects[$_]{object});
if ($x > $maxx){ $canvas->move($objects[$_]{object}, -$maxx,0) }
if ($x < $minx){ $canvas->move($objects[$_]{object}, $maxx,0) }
if ($y > $maxy){ $canvas->move($objects[$_]{object}, 0, -$maxy) }
if ($y < $miny){ $canvas->move($objects[$_]{object}, 0, $maxy) }
}
$top->update;
}
}