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

I'm trying to write my first few games, and for ease of development I chose perl/GTK2. I know a bit of perl, but I'm new to interfaces, so I'm learning GTK and GDK as I'm writing.

Since I take one step of at the time I currently have a checkered game board, and I've added the Quit functionality, I am now in the process of tracking the mouse over the board (that part works fine) and displaying a white rim on the current square the mouse is over. For this I have a small png with the rim and an alpha channel center. I'm using $pixbuf->composite to display the rim on the board, and here it goes wrong.

When I use interpolation method "nearest", as the gtk-demo does, along the top row I do get the correct rim, but it's displayed too high, on the second row it contrasts the background colour, alternating between too high and too low, and from the third row down it's gets even more weird. If I use "tiles", "bilinear" or "hyper", the placement is correct, the colour is correct, but the alpha channel is displayed as if it's not alpha, but white.

I've tried finding help/explanations through google, but the word composite in this context almost exclusively points to composite widgets, which is not helpful now, or to the definition of the composite method with no real explanation of the parameters. What am I doing wrong or where can I learn how to get this working?

I have the working code so far with all used external files at https://db.tt/b5p6qXAD . The code is thus:

#!/usr/bin/env perl use strict; use warnings; use utf8; use Data::Dumper; use Glib qw{ TRUE FALSE }; use Gtk2 '-init'; main(); exit(0); # Subroutines/callbacks sub main { my $builder; our $interface; our $image; our $board = Gtk2::Gdk::Pixbuf->new_from_file("./board.png") || die + "Reading board.png failed: $@\n"; our $back_width = $board->get_width; our $back_height = $board->get_height; our $background = Gtk2::Gdk::Pixbuf->new_from_file("./board.png") | +| die "Reading board.png 2nd time failed: $@\n"; our $focus = Gtk2::Gdk::Pixbuf->new_from_file("./Focus.png") || die + "Reading Focus.png failed: $@\n"; our $valid = Gtk2::Gdk::Pixbuf->new_from_file("./Valid.png") || die + "Reading Valid.png failed: $@\n"; our $invalid = Gtk2::Gdk::Pixbuf->new_from_file("./Invalid.png") || + die "Reading Invalid.png failed: $@\n"; our $statusbar; $builder = Gtk2::Builder->new(); # Load my glade XML file which I saved from my glade project # using 'gtkbuilder' format $builder->add_from_file( 'thud.glade' ); # Get my top level object as named in my glade project $interface = $builder->get_object( 'window1' ); $interface->add_events (['pointer-motion-mask', 'pointer-motion-hin +t-mask']); $image = $builder->get_object( 'image1' ); $image->set_from_pixbuf($background); $statusbar = $builder->get_object( 'statusbar1' ); our $context_id = $statusbar->get_context_id("Location"); # my @objects = $builder->get_objects(); # for (my $i=0; $i <= $#objects; $i++) { # print "Object $i: $objects[$i]\n"; # } $builder->connect_signals (undef); $interface->signal_connect('delete-event' => sub { Gtk2->main_quit +}); $interface->show(); Gtk2->main(); } # Defined by Glade sub gtk_main_quit () { # my ($widget, $event) = @_; Gtk2->main_quit(); return FALSE; } sub on_imagemenuitem5_activate () { # my ($widget, $event) = @_; Gtk2->main_quit(); return FALSE; } sub on_window_destroy { my ($widget, $data) = @_; Gtk2->main_quit(); return FALSE; } sub window1_motion_notify_event_cb () { my ($widget, $event) = @_; my ($x, $y) = our $interface->translate_coordinates(our $image, $ev +ent->x, $event->y); my $col=int(($x-1)/42) + 1; my $row=int(($y-1)/42) + 1; our $background = our $board->copy; $background->add_alpha(TRUE, "128", "128", "128"); if ($x>0 and $y> 0 and $x < 631 and $y < 631 and $col+$row > 6 and +$col+$row < 26 and abs($col-$row) < 10 and !($col == 8 and $row == 8) +) { our $focus->composite ($background, 1+42*($col-1), 1+42*($row-1), 42, 42, 0, 0, 1, 1, 'nearest', 127); our $statusbar->pop(our $context_id); $statusbar->push($context_id, sprintf("Cell %s%d\tx: %d\ty: %d", + chr($col+64), $row, $x, $y)); } $image->set_from_pixbuf($background); return FALSE; } sub statusbar1_text_popped_cb () { my ($widget, $event) = @_; # print "sub statusbar1_text_popped_cb (", $widget->get_name(), +")\n"; return FALSE; } sub statusbar1_text_pushed_cb () { my ($widget, $event) = @_; # print "sub statusbar1_text_pushed_cb (", $widget->get_name(), +")\n"; return FALSE; }