#!/usr/local/bin/perl -w
use strict;
use integer;
use Getopt::Std;
use Gtk;
use vars qw($automatic $window $canvas $pixmap $r_gc $width $height $b
+s
$orig_bs $shrink $VERBOSE $x $y);
my %o;
getopts('ab:svx:y:', \%o);
$VERBOSE = $o{'v'};
$shrink = $o{'s'};
$automatic = $o{'a'};
$width = $o{'x'} || 400;
$height = $o{'y'} || $o{'x'} || 400;
$bs = $o{'b'} || 10; # each "block" is 10x10 pixels by default
$orig_bs = $bs;
$x = int($width/$bs/2);
$y = int($height/$bs/2);
my $timeout = 512; # milliseconds
my $timer;
my @grid;
my %moves = (
65361 => sub { $x = int($width/$bs)-1 if --$x < 0 }, # west
65362 => sub { $y = int($height/$bs)-1 if --$y < 0 }, # north
65363 => sub { $x = 0 if ++$x >= int($width/$bs) }, # east
65364 => sub { $y = 0 if ++$y >= int($height/$bs) }, # south
);
{
my $prev_rand = 65361;
sub auto_move {
my $rand = 65361 + int rand 4;
if ( ($rand != $prev_rand) && (($rand % 2) == ($prev_rand % 2)
+) ) {
$rand = $prev_rand;
}
$prev_rand = $rand;
&{$moves{$rand}};
my $many = ($width/$bs) * ($height/$bs);
while(defined $grid[$x]->[$y]) {
$x = int(rand($width/$bs));
$y = int(rand($height/$bs));
print "attempt: ($x, $y)\n" if $VERBOSE;
return 0 if --$many < 0;
Gtk->timeout_remove($timer);
$timeout = $timeout/2;
#return 0 if $timeout < 1;
$timeout = 1 if $timeout < 1;
$timer = Gtk->timeout_add($timeout, \&auto_move, ());
if ($shrink) {
$bs--;
$bs=$orig_bs if $bs < 1;
}
}
random_color($canvas);
block_plot($x, $y);
return 1;
}
}
init Gtk;
$window = Gtk::Window->new('toplevel');
$window->signal_connect('destroy', sub { $window->destroy; exit 0 });
$window->signal_connect('key_press_event', \&key_handler);
$window->set_title('blox');
my $vbox = Gtk::VBox->new(0, 0);
$window->add($vbox);
$vbox->show;
$canvas = Gtk::DrawingArea->new;
$canvas->size($width, $height);
$canvas->signal_connect('expose_event', \&pixmap_expose);
$vbox->pack_start($canvas, 1, 1, 0);
$canvas->set_events([
'exposure_mask',
'button_press_mask',
'button1-motion-mask',
'button2-motion-mask',
'button3-motion-mask',
]);
$canvas->signal_connect('button_press_event', \&mouse_click);
$canvas->signal_connect('motion_notify_event', \&mouse_click);
$canvas->show;
$canvas->realize;
$pixmap = Gtk::Gdk::Pixmap->new($canvas->window, $width, $height, -1);
$r_gc = Gtk::Gdk::GC->new($canvas->window);
*random_color = \&set_random_color;
{
my %c = (
'red' => int(rand 65536),
'green' => int(rand 65536),
'blue' => int(rand 65536)
);
sub set_random_progressive_color {
my $widget = shift || return undef;
COLOR: for(keys %c) {
while(1) {
$c{$_} += (int(rand 3)-1) * int(rand 4096);
next COLOR if ($c{$_} > 0) && ($c{$_} < 65536);
}
}
my $r_color = $widget->window->get_colormap->color_alloc(\%c);
$r_gc->set_foreground($r_color);
1;
}
}
random_color($canvas);
sub block_plot {
my $x = shift; my $y = shift;
$grid[$x] = [] unless defined $grid[$x];
$grid[$x]->[$y] = 1;
# $pixmap->draw_rectangle($r_gc, 1, $x*$bs, $y*$bs, $bs, $bs); # fi
+lled
$pixmap->draw_rectangle($r_gc, 0, $x*$bs, $y*$bs, $bs, $bs); # out
+line
$canvas->window->draw_pixmap(
$canvas->style->fg_gc('normal'),
$pixmap, 0, 0, 0, 0, $width, $height
);
1;
}
sub blank_canvas {
$bs = $orig_bs;
my $widget = shift;
my $r_color = $widget->window->get_colormap->color_alloc(
{ 'red' => 0, 'green' => 0, 'blue' => 0 }
);
$r_gc->set_foreground($r_color);
$pixmap->draw_rectangle($r_gc, 1, 0, 0, $width, $height);
$widget->window->draw_pixmap(
$widget->style->fg_gc('normal'),
$pixmap, 0, 0, 0, 0, $width, $height
);
@grid = ();
}
$window->show;
$timer = Gtk->timeout_add($timeout, \&auto_move, ());
main Gtk;
{
my $previous_button = 1;
sub mouse_click {
my $widget = shift;
my $event = shift;
$x = int($event->{'x'}/$bs);
$y = int($event->{'y'}/$bs);
$previous_button = $event->{'button'} if defined $event->{'but
+ton'};
if ($previous_button == 1) {
set_random_color($canvas);
} elsif ($previous_button == 2) {
set_random_progressive_color($canvas);
} else {
# don't change the color for button 3
}
block_plot($x, $y);
1;
}
}
sub pixmap_expose {
my $widget = shift;
my $event = shift;
my ($x1, $y1, $x2, $y2) = @{$event->{'area'}};
$widget->window->draw_pixmap(
$widget->style->fg_gc('normal'),
$pixmap, $x1, $y1, $x1, $y1, $x2, $y2);
1;
}
sub set_random_color {
my $widget = shift || return undef;
my $r_color = $widget->window->get_colormap->color_alloc(
{
'red' => int(rand 65536),
'green' => int(rand 65536),
'blue' => int(rand 65536),
}
);
$r_gc->set_foreground($r_color);
}
sub key_handler {
my $widget = shift;
my $event = shift;
my $l = chr($event->{'keyval'});
if ($event->{'keyval'} == 65307) {
blank_canvas($canvas);
random_color($canvas);
$timeout = 512;
} elsif (defined $moves{$event->{'keyval'}}) {
&{$moves{$event->{'keyval'}}};
my $many = ($width/$bs) * ($height/$bs);
while(defined $grid[$x]->[$y]) {
$x = int(rand($width/$bs));
$y = int(rand($height/$bs));
return 1 if --$many < 0;
}
random_color($canvas);
block_plot($x, $y);
} elsif ($event->{'keyval'} == 32) { # space
# *random_color
} else {
print STDERR "$$event{'keyval'}\n";
}
1;
}
|