

Break Tris
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Break Tris Game</title>
<style>
canvas { background: #000; display: block; margin: 0 auto; }
</style>
</head>
<body>
<canvas id="gameCanvas" width="480" height="640"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const ROWS = 20;
const COLS = 10;
const BLOCK_SIZE = 30;
let gameStage = 1; // 1: Breakout, 2: Shooting
let score = 0;
// ==================== Breakout setup ====================
class Ball {
constructor() {
this.x = canvas.width / 2;
this.y = canvas.height - 60;
this.radius = 8;
this.speedX = 4 * (Math.random() > 0.5 ? 1 : -1);
this.speedY = -4;
}
move() {
this.x += this.speedX;
this.y += this.speedY;
if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {
this.speedX *= -1;
}
if (this.y - this.radius < 0) {
this.speedY *= -1;
}
}
draw() {
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.fill();
}
}
class Paddle {
constructor() {
this.width = 75;
this.height = 10;
this.x = (canvas.width - this.width) / 2;
this.y = canvas.height - 50;
this.speed = 7;
this.moveLeft = false;
this.moveRight = false;
}
move() {
if (this.moveLeft && this.x > 0) this.x -= this.speed;
if (this.moveRight && this.x + this.width < canvas.width) this.x += this.speed;
}
draw() {
ctx.fillStyle = "white";
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
class Brick {
constructor(x, y, active=true) {
this.x = x;
this.y = y;
this.width = BLOCK_SIZE;
this.height = BLOCK_SIZE/2;
this.active = active;
}
draw() {
if (this.active) {
ctx.fillStyle = "red";
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
}
const ball = new Ball();
const paddle = new Paddle();
const bricks = [];
for (let r=0; r<5; r++) {
for (let c=0; c<COLS; c++) {
bricks.push(new Brick(c*BLOCK_SIZE + 10, r*BLOCK_SIZE/2 + 30));
}
}
// ==================== Shooting setup ====================
let remainingBricks = [];
function initBricks() {
remainingBricks = bricks.filter(b => b.active);
}
class Shooter {
constructor() {
this.x = canvas.width/2;
this.y = canvas.height - 50;
this.width = 10;
this.height = 20;
this.speed = 5;
this.shooting = false;
}
move() {
if (keys['ArrowLeft']) this.x -= this.speed;
if (keys['ArrowRight']) this.x += this.speed;
if (this.x <0) this.x=0;
if (this.x + this.width > canvas.width) this.x=canvas.width - this.width;
}
draw() {
ctx.fillStyle = "yellow";
ctx.fillRect(this.x, this.y, this.width, this.height);
}
shoot() {
return new Bullet(this.x + this.width/2, this.y);
}
}
class Bullet {
constructor(x, y) {
this.x = x;
this.y = y;
this.speedY = -8;
}
move() {
this.y += this.speedY;
}
draw() {
ctx.fillStyle = "white";
ctx.fillRect(this.x-2, this.y, 4, 10);
}
offScreen() {
return this.y + 10 < 0;
}
hits(brick) {
return this.x > brick.x && this.x < brick.x + brick.width &&
this.y < brick.y + brick.height && this.y + 10 > brick.y;
}
}
const shooter = new Shooter();
let bullets = [];
// ===================== Controls =========================
const keys = {};
document.addEventListener('keydown', e => {
keys[e.key] = true;
});
document.addEventListener('keyup', e => {
keys[e.key] = false;
});
canvas.addEventListener('mousemove', e => {
if (gameStage === 1) {
paddle.x = e.offsetX - paddle.width/2;
}
});
document.addEventListener('click', () => {
if (gameStage === 2) {
bullets.push(shooter.shoot());
}
});
// ==================== Game Loop ===================
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (gameStage === 1) {
// Breakout stage
paddle.move();
ball.move();
// collision with paddle
if (ball.y + ball.radius > paddle.y && ball.x > paddle.x && ball.x < paddle.x + paddle.width) {
ball.speedY *= -1;
}
// collision with bricks
for (let brick of bricks) {
if (brick.active && ball.x > brick.x && ball.x < brick.x + brick.width &&
ball.y - ball.radius < brick.y + brick.height && ball.y + ball.radius > brick.y) {
brick.active = false;
ball.speedY *= -1;
score++;
break;
}
}
// check for stage complete
if (bricks.every(b => !b.active)) {
gameStage = 2;
initBricks();
}
// check for lose
if (ball.y - ball.radius > canvas.height) {
alert('Game Over! Your score: ' + score);
document.location.reload();
}
ball.draw();
paddle.draw();
} else if (gameStage === 2) {
// Shooting stage
shooter.move();
shooter.draw();
bullets.forEach(bullet => {
bullet.move();
bullet.draw();
});
bullets = bullets.filter(b => !b.offScreen());
// Check hits
for (let b of bullets) {
for (let brick of remainingBricks) {
if (brick.active && b.hits(brick)) {
brick.active = false;
}
}
}
// Check stage completion
if (remainingBricks.every(b => !b.active)) {
alert('Congratulations! You completed both stages.');
document.location.reload();
}
}
// Draw remaining bricks in stage 2
if (gameStage === 2) {
for (let brick of remainingBricks) {
brick.draw();
}
}
requestAnimationFrame(gameLoop);
}
setInterval(() => {
if (gameStage === 1) {
// nothing extra here
}
}, 1000);
// assign remaining bricks for stage 2
// Already initialized in initBricks
gameLoop();
</script>
</body>
</html>
Recommended Games
Other games you might enjoy