Niecza Perl 6 and Gtk
..er, Tetris
|
by Martin Berends
London Perl Workshop
12 November 2011
|
|
Graphical User Interfaces
(Event driven programming)
|
* Like in Soviet Russia:
* You don't call the GUI libraries.
* The GUI libraries call you.
|
|
Events == user actions
and system signals
|
Examples:
* Mouse and keyboard input
* Clock ticks and file I/O
|
|
Event handlers are a form
of callback routine
|
my $window = Window.new("helloworld");
$window.add_DeleteEvent: sub ($obj, $args) { #OK
# runs when the user deletes the window using the "close
# window" widget in the window frame.
Application.Quit;
};
Application.Run;
|
|
BTW, that was part of
niecza/examples/gtk1.pl
|
About Niecza:
* a recent Perl 6 implementation by Stefan O'Rear
* uses Mono or .NET, on Linux, OS X and Windows
|
|
Niecza uses most CLR libraries (from GAC)
and auto-marshals params & return values
|
# Translated from http://www.mono-project.com/GtkSharp:_Hello_World
constant $GTK = "gtk-sharp,Version=2.12.0.0,Culture=neutral,PublicKeyToken=35e10195dab3c99f";
constant Application = CLR::("Gtk.Application,$GTK");
constant Window = CLR::("Gtk.Window,$GTK");
constant Button = CLR::("Gtk.Button,$GTK");
Application.Init;
my $window = Window.new("helloworld");
|
|
|
Gtk (and Gdk)
in 'Gnome Libraries' at http://docs.go-mono.com
|
Widgets including: AboutDialog Arrow Box Button
Calendar Clipboard ComboBox Curve Dialog Drag DrawingArea
FileChooserDialog Menu Printer ProgressBar Scrollbar Statusbar Timeout
Toolbar TrayIcon VolumeButton Win32EmbedWidget WindowGroup
and over 200 others
|
|
Drawing with Gdk and Cairo
|
constant GdkCairoHelper = CLR::("Gdk.CairoHelper,$GDK");
constant GtkDrawingArea = CLR::("Gtk.DrawingArea,$GTK");
my $drawingarea = GtkDrawingArea.new;
$drawingarea.add_ExposeEvent: sub ($obj, $args) {
my $cc = GdkCairoHelper.Create($obj.GdkWindow); # Cairo Context
my $windowX=0; my $windowY=0; my $windowWidth=0; my $windowHeight=0; my $windowDepth=0;
$obj.GdkWindow.GetGeometry($windowX, $windowY, $windowWidth, $windowHeight, $windowDepth);
$cc.SetSourceRGB(0.95.Num, 0.90.Num, 0.85.Num); $cc.Paint; # background color
...
|
|
constant GLibTimeout = CLR::("GLib.Timeout,$GLIB");
GLibTimeout.Add: 60000, sub () { # Update once per minute
$drawingarea.QueueDrawArea(0,0,$windowSizeX,$windowSizeY);
return True; # meaning please continue calling this timeout handler
};
|
|
niecza/examples/gtk-clock.pl
|
|
Introducing Tetris (Tetromino-tennis)
|
constant matrixRows = 20; constant matrixColumns = 10;
my @tetrominoes = # cell coordinates relative to the "middle" cell
[ -1, 0, 0, 0, 1, 0, 2, 0 ], # I
[ -1, 0, 0, 0, 1, 0, 1, 1 ], # J
[ -1, 1, -1, 0, 0, 0, 1, 0 ], # L
[ -1, 1, -1, 0, 0, 0, 0, 1 ], # O
[ -1, 1, 0, 1, 0, 0, 1, 0 ], # S
[ -1, 0, 0, 0, 0, 1, 1, 0 ], # T
[ -1, 0, 0, 0, 0, 1, 1, 1 ]; # Z
|
|
Colours
(must convert Rat -> Num to marshal to Float)
|
my @colors = # Copied approximately from the PC version
[0, 0, 0 ], # 0: black background
[0.5.Num, 0, 0 ], # 1: I maroon
[1, 1, 1 ], # 2: J white
[0.9.Num, 0, 0.9.Num], # 3: L dark magenta
[0, 0, 0.6.Num], # 4: O dark blue
[0, 0.8.Num, 0 ], # 5: S green
[0.7.Num, 0.7.Num, 0 ], # 6: T brown
[0, 0.8.Num, 0.8.Num]; # 7: Z dark cyan
|
|
Physics (1)
- pieces should obey laws of nature
|
sub CanMovePiece($deltaX, $deltaY) {
my $canMove = True;
for @piece -> $x, $y {
if $x+$pieceX+$deltaX < 0 || $x+$pieceX+$deltaX >= matrixColumns ||
$y+$pieceY+$deltaY < 0 || $y+$pieceY+$deltaY >= matrixRows ||
@matrix[$y+$pieceY+$deltaY][$x+$pieceX+$deltaX] != 0
{ $canMove = False; }
}
$canMove;
}
|
|
Physics (2)
- pieces should obey laws of nature
|
sub TryRotatePiece() {
my @p = @piece;
@piece .= map({ $^b, -$^a });
if ! CanMovePiece(0, 0) {
@piece = @p;
}
}
|
|
Keyboard input
(give the user the illusion of control)
|
sub KeyPressEvent($sender, $eventargs) { #OK not used
given $eventargs.Event.Key {
when 'Up' { if $colorindex != 4 { TryRotatePiece() } }
when 'Down' { while CanMovePiece(0,1) {++$pieceY;} }
when 'Left' { if CanMovePiece(-1,0) {--$pieceX;} }
when 'Right' { if CanMovePiece( 1,0) {++$pieceX;} }
}
return True; # means this keypress is now handled
}
|
|
niecza/examples/gtk-tetris.pl
|
|
|