Chandra-Game-Tetris

 view release on metacpan or  search on metacpan

lib/Chandra/Game/Tetris/Engine.pm  view on Meta::CPAN

			my $class = $cell ? "tetris-col filled block-$cell" : 'tetris-col';
			$tr->add_child({
				tag => 'td',
				class => $class,
				children => [{ tag => 'div' }],
			});
		}
	}
	return $html;
}

sub _lock_and_spawn {
	my ($self) = @_;
	my $grid = $self->grid;
	my $current = $self->blocks->current;
	$grid->lock_block(
		$current->cells, $current->row, $current->col, $current->id
	);
	my $cleared = $grid->clear_lines;
	$self->update_score($cleared);
	if (!$self->spawn_next($current)) {
		return {
			game_over => 1,
			grid => $self->render_grid,
			score => $self->score,
			lines => $self->lines,
			level => $self->level,
		};
	}
	my $next_html = $self->blocks->next->render->render;
	return {
		game_over => 0,
		grid => $self->render_grid,
		score => $self->score,
		lines => $self->lines,
		level => $self->level,
		next_block => $next_html,
	};
}

sub spawn_next {
	my ($self) = @_;
	my $blocks = $self->blocks;
	my $block = $blocks->next;
	$blocks->current($block);
	$block->row(0);
	$block->col(($self->grid->width / 2) - 2);
	return $self->grid->is_valid(
		$block->cells, $block->row, $block->col
	);
}

sub reset_game {
	my ($self) = @_;
	$self->grid->reset;
	$self->score(0);
	$self->lines(0);
	$self->level(1);
}

sub update_score {
	my ($self, $cleared) = @_;
	return unless $cleared;
	my @points = (0, 100, 300, 500, 800);
	my $pts = ($points[$cleared] // 800) * $self->level;
	$self->score($self->score + $pts);
	$self->lines($self->lines + $cleared);
	$self->level(int($self->lines / 10) + 1);
}


sub rotate_cw {
	my ($cells) = @_;
	my $n = scalar @$cells;
	my @r;
	for my $row (0 .. $n - 1) {
		for my $col (0 .. $n - 1) {
			$r[$row][$col] = $cells->[$n - 1 - $col][$row];
		}
	}
	return \@r;
}

sub css {
	return q|
		*, *::before, *::after {
			box-sizing: border-box;
			margin: 0;
			padding: 0;
		}

		:root {
			--background: rgb(20, 24, 27);
			--color: rgb(240, 244, 247);
			--cell: clamp(16px, min(calc((100vw - 160px) / 10), calc((100vh - 80px) / 18)), 40px);
			--grid-w: calc(var(--cell) * 10);
			--grid-h: calc(var(--cell) * 18);
			--panel-w: calc(var(--cell) * 5);
			--border: 1px solid rgb(40, 44, 47);
			--cell-bg: rgb(30, 34, 37);
		}

		body {
			background: var(--background);
			min-height: 100vh;
			display: flex;
			align-items: center;
			justify-content: center;
		}

		.wrapper {
			display: flex;
			flex-direction: column;
			align-items: center;
			gap: 0.5rem;
			padding: 1rem;
		}

		.title {
			color: var(--color);
			font-family: monospace;



( run in 0.805 second using v1.01-cache-2.11-cpan-13bb782fe5a )