breakout game in typescript

Here is a basic breakout game built in TypeScript using canvas and object-oriented programming:

index.ts
// Define canvas element and set context
const canvas = <HTMLCanvasElement>document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

// Define ball properties
class Ball {
  x: number;
  y: number;
  dx: number;
  dy: number;
  radius: number;

  constructor(x: number, y: number, dx: number, dy: number, radius: number) {
    this.x = x;
    this.y = y;
    this.dx = dx;
    this.dy = dy;
    this.radius = radius;
  }

  // Draw ball on canvas
  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
    ctx.fillStyle = 'red';
    ctx.fill();
    ctx.closePath();
  }

  // Move ball on canvas
  move() {
    this.x += this.dx;
    this.y += this.dy;
  }

  // Check for collision with walls
  checkWalls() {
    if (this.x + this.dx > canvas.width - this.radius || this.x + this.dx < this.radius) {
      this.dx = -this.dx;
    }
    if (this.y + this.dy < this.radius) {
      this.dy = -this.dy;
    } else if (this.y + this.dy > canvas.height - this.radius) {
      // Game over
      clearInterval(interval);
      alert('Game over!');
      document.location.reload();
    }
  }
}

// Define paddle properties and methods
class Paddle {
  width: number;
  height: number;
  x: number;
  y: number;

  constructor(width: number, height: number, x: number, y: number) {
    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;
  }

  // Draw paddle on canvas
  draw() {
    ctx.beginPath();
    ctx.rect(this.x, this.y, this.width, this.height);
    ctx.fillStyle = 'blue';
    ctx.fill();
    ctx.closePath();
  }

  // Move paddle on canvas
  move(dir: string) {
    if (dir === 'left' && this.x > 0) {
      this.x -= 7;
    } else if (dir === 'right' && this.x < canvas.width - this.width) {
      this.x += 7;
    }
  }
}

// Define brick properties and methods
class Brick {
  x: number;
  y: number;
  status: number;

  constructor(x: number, y: number, status: number) {
    this.x = x;
    this.y = y;
    this.status = status;
  }

  // Draw brick on canvas
  draw() {
    ctx.beginPath();
    ctx.rect(this.x, this.y, brickWidth, brickHeight);
    ctx.fillStyle = 'green';
    ctx.fill();
    ctx.closePath();
  }
}

// Initialize game variables
const ball = new Ball(canvas.width/2, canvas.height-30, 2, -2, 10);
const paddle = new Paddle(75, 10, (canvas.width-75)/2, canvas.height-10);
const brickRows = 3;
const brickCols = 5;
const brickWidth = 75;
const brickHeight = 20;
const brickPadding = 10;
const brickOffsetTop = 30;
const brickOffsetLeft = 30;
let bricks: Brick[] = [];

// Populate bricks array
for (let c = 0; c < brickCols; c++) {
  for (let r = 0; r < brickRows; r++) {
    const brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
    const brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
    bricks.push(new Brick(brickX, brickY, 1));
  }
}

// Keep score and number of lives
let score = 0;
let lives = 3;

// Draw score on canvas
function drawScore() {
  ctx.font = '16px Arial';
  ctx.fillStyle = 'black';
  ctx.fillText('Score: ' + score, 8, 20);
}

// Draw number of lives on canvas
function drawLives() {
  ctx.font = '16px Arial';
  ctx.fillStyle = 'black';
  ctx.fillText('Lives: ' + lives, canvas.width-65, 20);
}

// Check for collision between ball and bricks
function collisionDetection() {
  bricks.forEach((brick) => {
    if (brick.status === 1) {
      if (ball.x > brick.x && ball.x < brick.x+brickWidth && ball.y > brick.y && ball.y < brick.y+brickHeight) {
        ball.dy = -ball.dy;
        brick.status = 0;
        score++;
        if (score === brickRows*brickCols) {
          // Game won
          clearInterval(interval);
          alert('You win!');
          document.location.reload();
        }
      }
    }
  });
}

// Add event listeners to move paddle
document.addEventListener('keydown', keyDownHandler);
document.addEventListener('keyup', keyUpHandler);

let rightPressed = false;
let leftPressed = false;

function keyDownHandler(e: KeyboardEvent) {
  if (e.key === 'ArrowRight') {
    rightPressed = true;
  } else if (e.key === 'ArrowLeft') {
    leftPressed = true;
  }
}

function keyUpHandler(e: KeyboardEvent) {
  if (e.key === 'ArrowRight') {
    rightPressed = false;
  } else if (e.key === 'ArrowLeft') {
    leftPressed = false;
  }
}

// Main game loop
function gameLoop() {
  // Clear canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Draw elements
  ball.draw();
  paddle.draw();
  bricks.forEach((brick) => brick.draw());
  drawScore();
  drawLives();

  // Move elements
  ball.move();
  paddle.move(rightPressed ? 'right' : leftPressed ? 'left' : '');
  
  // Check for collision with walls and paddle
  ball.checkWalls();
  if (ball.y + ball.dy > canvas.height - ball.radius - paddle.height) {
    if (ball.x > paddle.x && ball.x < paddle.x + paddle.width) {
      ball.dy = -ball.dy;
    } else {
      lives--;
      if (!lives) {
        // Game over
        clearInterval(interval);
        alert('Game over!');
        document.location.reload();
      } else {
        // Reset ball and paddle
        ball.x = canvas.width/2;
        ball.y = canvas.height-30;
        ball.dy = -ball.dy;
        paddle.x = (canvas.width-paddle.width)/2;
      }
    }
  }

  // Check for collision between ball and bricks
  collisionDetection();
}

// Start game loop on interval
const interval = setInterval(gameLoop, 10);
5424 chars
232 lines

This code initializes a canvas element, creates ball, paddle, and brick classes, populates an array of bricks, and sets up event listeners to move the paddle. The game loop clears the canvas, draws elements, moves elements, checks for collisions, and updates the score and lives. The game ends when the ball hits the bottom of the canvas and there are no lives remaining, or all bricks have been destroyed.

gistlibby LogSnag