I've never written games before, but I previously posted a Hangman that I thought was fun. I love the examples of forest fire and Game of Life and wanted to create something like those. I originally wanted to create Pong but decided to try a simple ball that bounces off the walls of a container.

I showed this to my daughter, and she asked if there could be more than one ball, so I added that. They don't, however, bounce off each other, and this gets at the same problem I was mulling with regard to adding obstacles in the field that should deflect the balls. I have a feeling that two-dimensional arrays would help me add this feature. Support for that is coming. Anyway, on to the script!

#!/usr/bin/env perl6 my enum HorzDir <Left Right>;

my enum VertDir <Up Down>; subset PosInt of Int where * > 0; class Ball {

has Int $.rows;

has Int $.cols;

has Int $.row is rw = (1..$!rows).pick;

has Int $.col is rw = (1..$!cols).pick;

has HorzDir $.horz-dir is rw = HorzDir.pick;

has VertDir $.vert-dir is rw = VertDir.pick; method Str { "($.row, $.col)" } method reverse-horz-dir {

$!horz-dir = $!horz-dir == Left ?? Right !! Left;

} method reverse-vert-dir {

$!vert-dir = $!vert-dir == Down ?? Up !! Down;

} method move {

if $!horz-dir == Right {

$!col += $!col < $!cols ?? 1 !! -1;

}

else {

$!col += $!col > 1 ?? -1 !! 1;

} if $!vert-dir == Down {

$!row += $!row < $.rows ?? 1 !! -1;

}

else {

$!row += $!row > 1 ?? -1 !! 1;

} $.reverse-horz-dir if $!col <= 1 || $!col >= $.cols;

$.reverse-vert-dir if $!row <= 1 || $!row >= $.rows;

}

} my $DOT = "\x25A0"; # ■

my $STAR = "\x2605"; # ★

my $SMILEY-FACE = "\x263A"; # ☺

my ($ROWS, $COLS) = qx/stty size/.words; sub MAIN (

PosInt :$rows=$ROWS - 4,

PosInt :$cols=$COLS - 2,

PosInt :$balls=1,

Numeric :$refresh=.1,

Bool :$smiley=False,

Bool :$star=False,

) {

print "\e[2J";

my Str $bar = '+' ~ '-' x $cols ~ '+';

my $icon = $smiley ?? $SMILEY-FACE !! $star ?? $STAR !! $DOT;

my Ball @balls = do for ^$balls { Ball.new(:$rows, :$cols) }; loop {

.move for @balls; print "\e[H";

my $screen = "$bar

"; for 1..$rows -> $this-row {

my $line = '|' ~ " " x $cols; for @balls -> $ball {

if $this-row == $ball.row {

$line.substr-rw($ball.col, 1) = $icon;

}

} $screen ~= "$line|

";

} $screen ~= $bar;

put $screen;

sleep $refresh;

}

}



There is a ton packed into this code, mostly because Perl's objects have such a compact syntax. There are so many new features I love in the language such as "subset" to create custom types and "enum" to create type-ish things. I can't imagine doing without my "MAIN" anymore, esp with the way it turns the amazing subroutine signatures into usage statements.

Thanks to the #perl6 IRC channel for suggestion on improving my code and answering all my questions.

Source in Github. Also, read my book.

UPDATE

Thanks to suggestions from Reddit, I herewith submit a new version with one very big improvement -- the balls fight to the death now! I agree that the enum stuff was a bit belabored. The suggestions for the "move" method were much better than what I had.