X-Git-Url: http://git.shiar.nl/wormy.git/blobdiff_plain/3d225e408bf05bd9c50959bda8ffd2eeef19e5fe..48c2bc131fc366f422101f985714f4cc642e27b0:/lib/Games/Wormy/Render.pm diff --git a/lib/Games/Wormy/Render.pm b/lib/Games/Wormy/Render.pm new file mode 100644 index 0000000..a1f29f5 --- /dev/null +++ b/lib/Games/Wormy/Render.pm @@ -0,0 +1,152 @@ +package Games::Wormy::Render; + +use 5.010; +use strict; +use warnings; + +use Imager; +use List::Util qw(sum max); + +our $VERSION = '1.00'; + +our %COL = ( + bg => Imager::Color->new(255, 255, 255), + wall => Imager::Color->new( 0, 0, 0), + player => [ + { + main => Imager::Color->new(hue => 120, v => 1, s => .67), + outer => Imager::Color->new(hue => 120, v => 1, s => .33), + }, + ], + bouncy => Imager::Color->new(hue => 180, v => 1, s => 1), +); + +sub level { + my ($self, $level) = @_; + + my $field = Imager->new(xsize => $level->{width}, ysize => $level->{height}); + $field->box(filled => 1, color => $COL{bg}); + + # initial player paths + require Math::Trig; + my $DIRMULT = Math::Trig::pi() / 128; + for my $num (0 .. $#{ $level->{worms} }) { + my $player = $level->{worms}->[$num]; + $field->line( + x1 => $player->{x}, + y1 => $player->{y}, + x2 => $player->{x} + sin($_ * $DIRMULT) * 15, + y2 => $player->{y} + cos($_ * $DIRMULT) * 15, + color => $COL{player}->[$num]->{outer}, + ) for $player->{d} + 13, $player->{d} - 13; + $field->line( + x1 => $player->{x}, + y1 => $player->{y}, + x2 => $player->{x} + sin($player->{d} * $DIRMULT) * 20, + y2 => $player->{y} + cos($player->{d} * $DIRMULT) * 20, + color => $COL{player}->[$num]->{main}, + ); + $field->circle( + x => $player->{x}, + y => $player->{y}, + r => 2, + color => $COL{player}->[$num]->{main}, + ); + last; + } + + # outer field borders + $field->box( + xmin => $_, ymin => 0, + xmax => $_+1, ymax => $level->{height} - 1, + filled => 1, + color => $COL{wall}, + ) for 0, $level->{width} - 2; + $field->box( + ymin => $_, xmin => 2, + ymax => $_+1, xmax => $level->{width} - 1, + filled => 1, + color => $COL{wall}, + ) for 0, $level->{height} - 2; + + # draw objects + for my $object (@{ $level->{objects} }) { + my @x = @$object{'x1', 'x2'}; + my @y = @$object{'y1', 'y2'}; + given ($object->{type}) { + when (1) { + $field->line( + x1 => $x[0], + y1 => $y[0], + x2 => $x[1], + y2 => $y[1], + color => $COL{wall}, + ); + } + when (2) { + $field->polyline( + points => [ + [ $x[0], $y[0]], [ $x[1], $y[1]], + [++$x[1], $y[1]], [++$x[0], $y[0]], + [$x[0], ++$y[0]], [$x[1], ++$y[1]], + [--$x[1], $y[1]], [--$x[0], $y[0]], + ], + color => $COL{wall}, + ); + } + when (3) { + $field->box( + xmin => $x[0], + ymin => $y[0], + xmax => $x[1], + ymax => $y[0] + $y[1], + filled => 1, + color => $COL{wall}, + ); + } + when (4) { + $field->circle( + x => $x[0], + y => $y[0], + r => $x[1], + filled => 1, + color => $COL{wall}, + ); + } + } + } + + for my $bouncy (@{ $level->{balls} }) { + $field->box( + xmin => $bouncy->{x}, + ymin => $bouncy->{y}, + xmax => $bouncy->{x} + 1, + ymax => $bouncy->{y} + 1, + color => $COL{bouncy}, + ); + } + + return $field; +} + +sub composite { + my $self = shift; + + # single level can be returned directly + return $self->level($_[0]) if @_ == 1; + + # concatenate images of multiple levels + my $width = max map { $_->{width} } @_; + my $height = sum(map { $_->{height} + 1 } @_) - 1; + my $output = Imager->new(xsize => $width, ysize => $height); + $output->box(filled => 1, color => [64, 0, 0]); + $height = 0; + for (@_) { + $output->paste(src => $self->level($_), top => $height); + $height += $_->{height} + 1; + } + return $output; +} + +1; +