JSFiddle - React, Tailwind, and code Playground

by muztv

HTML

<canvas id="app"></canvas>

CSS

html, body {
  margin: 0;
  padding: 0;
  height: 100vh;
}

Babel + JSX

const canvas = document.getElementById('app');
canvas.width = document.body.offsetWidth;
canvas.height = document.body.offsetHeight;
const ctx = canvas.getContext('2d');
let time = 0;


class Figure {
  x = 0;
  y = 0;
  color = 'black';

  constructor({ x, y, color }) {
    this.setProperty('x', x);
    this.setProperty('y', y);
    this.setProperty('color', color);
  }

  setProperty(name, value) {
    if (typeof value === 'function') {
      Object.defineProperty(this, name, {
        get: value
      });
    } else {
      this[name] = value;
    }
  }
}

class Rect extends Figure {
  width = 0;
  height = 0;

  constructor({ width, height, ...props}) {
    super(props);
    this.setProperty('width', width);
    this.setProperty('height', height);
  }
}

class Circle extends Figure {
  radius = 0;

  constructor({ radius, ...props}) {
    super(props);
    this.setProperty('radius', radius);
  }
}


const obstacles = new Set();

for(let i = 0; i < 100; i++) {
  const props = {
    x: () => 100 + Math.sin((time / 8 + i * 1000) / 1000) * canvas.width,
    y: 10 + i * 10,
    width: i + 10,
    height: i / 2 + 10,
    color: 'gray'
  }

  if (i % 10 === 1) {
    [props.x, props.y] = [props.y, props.y];
  }

  obstacles.add(new Rect(props))
}

const user = new Circle({
  x: 100,
  y: 100,
  radius: 10,
  color: 'green'
})


// const isItemCollision = (item1, item2, allowRecision = true) => {
//   return (
//     (item1.x < item2.x && (item1.x + item1.width) > item2.x) &&
//     (item1.y < item2.y && (item1.y + item1.width) > item2.y)
//     || !allowRecision && isCollision(item2, item1, false)
//   )
// }

const isCollision = (x, y, item) => {
  return (
    (item.x < x && (item.x + item.width) > x) &&
    (item.y < y && (item.y + item.width) > y)
  )
}

const renderItem = (item) => {
  ctx.fillStyle = item.color;

  switch(item.constructor.name) {
    case 'Rect':
      ctx.fillRect(item.x, item.y, item.width, item.height)
    break;
    case 'Circle':
     ...