Yeah, I see you try to handle deleting objects in your code, but the sad fact is, you are overlooking something. In my experience, it is a hash key that is not getting completely removed, or you get auto-vivication in some hashes. But without actually trying to trouble shoot your code, and just from your comment " so every pixel is, unfortunately, a seperate, persistant line segment" , you need to rethink how you draw your lines, so that every pixel IS NOT a new segment. My first thought would be to create 1 segment for each moving object. Then as it moves and consumes another pixel, reconfigure the original segment to the end points of the collective pixels. If you think about it a bit, you should be able to do this easily, especially if they move vertically. I encountered a similar problem in Tk Realtime data aquisition, where I was adding many segments to a continuing graph, and the cpu would bog down after awhile. My solution was to use segments up to a point, then write them out as a solid non-updating curve, then start another temporary segment.
So this little project may be just too 'big' for Tk's abilities to handle?? No you are reaching a point where your desire to use straight forward programming techniques is hitting the limit, where you need to start creatively juggling. Just about any language you use, that has a canvas (and canvas items) will be the same. You cannot expect a widget to handle a gazzillion items, as effectively as a few hundred. BUT if you really insist on following your way of thinking, you might want to switch to SDL. SDL dosn't have the notion of line segments to keep track of, In SDL you write something to the screen and forget it and move on. This has advantages in situations like yours, but disadvantages in that there is no way to easily identify and manipulate an existing segment, and if it gets erased from the screen, it's gone. Just think about an algorithm that you can feed a set of points (pixels) and it will return 2 pixels which are the extreme end points. Then use those 2 points to reconfigure the bot on the update. That way your canvas will only be handling a fixed number of lines at any one time, just making them longer thru a reconfigure. Or if you eventually want to move along curves, use the technique I showed in Tk Realtime data aquisition, and have each bot, after say 100 updates, leave the last 100 points as a solid non-updatable curve, then start another 100 pixel set which is continually updated.
| [reply] |
| [reply] |
Try the Tk-Canvas-Point module, by Slaven Rezic. It is mostly a proof-of-concept trial module, and not gauranteed to do what
you want. Try this sample code. It makes little circles, but that is just so you can see them, it will do a single pixel.
#!/usr/bin/perl -w
use Tk;
use Tk::Canvas::Point;
use strict;
#adapted from Tk::CanvasPoint by Slaven Rezic
my $mw = MainWindow->new;
my $c = $mw->Canvas->pack(-fill => "both", -expand => 1);
$c->bind("all", "<1>" => sub {
my($c) = @_;
my(@tags) = $c->gettags("current");
warn "Tags of current item: @tags\n";
my(@coords) = $c->coords("current");
warn "Coords of current item: @coords\n";
});
my $tag = "";
$c->bind("all", "<Enter>" => sub {
my($c) = @_;
$tag = ($c->gettags("current"))[0];
});
$c->bind("all", "<Leave>" => sub {
my($c) = @_;
$tag = "";
});
my @p;
$mw->update;
create_points();
$mw->update;
for (1..10) {
delete_last_point();
$mw->update;
}
postscript(0);
$mw->update;
my $f = $mw->Frame->pack;
$mw->Button(-text => "Create points",
-command => sub { create_points() }
)->pack(-side => "left");
$mw->Button(-text => "Delete last point",
-command => sub { delete_last_point() },
)->pack(-side => "left");
$mw->Button(-text => "PS",
-command => sub { postscript(1) })->pack(-side => "left");
$mw->Label(-width => 10, -textvariable => \$tag)->pack;
MainLoop;
sub create_points {
for(1..100) {
my $width = rand(20);
push @p, $c->create('point',
rand($c->width),rand($c->height),
-width => $width,
-activefill => "white",
-activewidth => $width+2,
-fill => [qw(blue red green yellow black white)]->[ran
+d(5)],
-tags => "tag".int(rand(100)),
);
}
}
sub delete_last_point {
$c->delete(pop @p) if @p;
}
sub postscript {
my $display = shift;
my $f = "test.$$.ps";
$c->postscript(-file => $f);
open(F, $f) or die $!;
my($firstline) = <F>;
close F;
system("gv $f &") if $display;
}
__END__
Otherwise, you need to go to SDL to do this. SDL just "blits" stuff to the screen, and there is no object-item associated with it. That is why it is used for games, it can be alot faster. To erase what you previously blited, you write the background color to it's location. Tk is designed to have items, that you can tag, and have mouse and key bindings to it.
| [reply] [d/l] |