Games-GUI-Battleship
view release on metacpan or search on metacpan
lib/Games/GUI/Battleship/Renderer.pm view on Meta::CPAN
package Games::GUI::Battleship::Renderer;
use v5.38;
use experimental 'signatures';
use feature 'try';
no warnings 'experimental::try';
use Cairo;
use List::Util qw(min max);
# Math constant
my $PI = 3.14159265358979323846;
sub new ( $class, %args ) {
my $self = {
cell_size => 32,
player_origin => [ 50, 80 ],
opponent_origin => [ 460, 80 ],
header_height => 60,
label_margin => 26,
};
return bless $self, $class;
}
sub cell_size ($self) {
return $self->{cell_size};
}
sub player_origin ($self) {
return @{ $self->{player_origin} };
}
sub opponent_origin ($self) {
return @{ $self->{opponent_origin} };
}
sub update_layout ( $self, $vp_w, $vp_h ) {
$self->{vp_w} = $vp_w;
$self->{vp_h} = $vp_h;
my $w_factor = $vp_w / 940;
# Header height scales smoothly with window height and width
my $header_h = int( 72 + ( $vp_h - 600 ) * 0.05 + ( $vp_w - 900 ) * 0.035 );
$header_h = max( 74, min( 170, $header_h ) );
# Footer height scales with height and width
my $footer_h = int( 40 + ( $vp_h - 600 ) * 0.03 + ( $vp_w - 900 ) * 0.015 );
$footer_h = max( 42, min( 75, $footer_h ) );
# Dynamic label margin around each board for larger titles and labels
my $avail_h_est = $vp_h - $header_h - $footer_h - 40;
my $avail_w_est = ( $vp_w - 60 - 80 ) / 2;
my $cs_est = min( int( $avail_h_est / 10 ), int( $avail_w_est / 10 ) );
$cs_est = max( 24, min( 140, $cs_est ) );
my $label_m = int( 28 + ( $cs_est * 0.28 ) + ( $vp_w * 0.012 ) );
$label_m = max( 32, min( 80, $label_m ) );
$self->{label_margin} = $label_m;
my $avail_h = $vp_h - $header_h - $footer_h - $label_m;
my $avail_w = ( $vp_w - 60 - ( 2 * $label_m ) ) / 2;
my $cs_h = int( $avail_h / 10 );
my $cs_w = int( $avail_w / 10 );
my $cs = min( $cs_h, $cs_w );
$cs = max( 24, min( 140, $cs ) );
$self->{cell_size} = $cs;
my $board_px = 10 * $cs;
my $gap =
max( 24, int( ( $vp_w - ( 2 * $board_px ) - ( 2 * $label_m ) ) / 3 ) );
$gap = min( 120, $gap );
my $total_w = ( 2 * $board_px ) + ( 2 * $label_m ) + $gap;
my $start_x = max( 15, int( ( $vp_w - $total_w ) / 2 ) );
my $start_y = $header_h + $label_m;
$self->{player_origin} = [ $start_x + $label_m, $start_y ];
$self->{opponent_origin} =
[ $start_x + $board_px + $label_m + $gap + $label_m, $start_y ];
return $cs;
}
sub point_to_cell ( $self, $px, $py, $board_type ) {
my ( $ox, $oy ) =
( $board_type eq 'player' )
? $self->player_origin
: $self->opponent_origin;
my $cs = $self->{cell_size};
if ( $px >= $ox
&& $px < $ox + ( 10 * $cs )
&& $py >= $oy
&& $py < $oy + ( 10 * $cs ) )
( run in 0.517 second using v1.01-cache-2.11-cpan-f1796dc4e6b )