JSFiddle - React, Tailwind, and code Playground

by Sergei Sokolov

HTML

<canvas></canvas>
<br>
&larr; &uarr; &darr; &rarr; A, S, D, W &ndash; перемещать блок.
<br>Пробел — в исходное положение.

CSS

canvas {
  border: 1px solid grey;
}

JavaScript

/**
 * Plain game based on:
 * для вопроса https://qna.habr.com/q/1028492
 * Расставить ромбики в нужных координатах, ориентируясь на виртуальные координаты?
 */
 const ctx = document.querySelector('canvas').getContext('2d');
 ctx.translate(150, 75); // center to center
 
 // Fake isometric
 ctx.scale(1, .618);
 ctx.rotate(-Math.PI / 4);
 
 const rhombus = (x, y, fillStyle, strokeStyle, side = 40) => {
   ctx.save()
   ctx.translate(x * side, y * side);
   ctx.fillStyle = fillStyle || 'white';
   ctx.strokeStyle = strokeStyle || 'grey';
   ctx.fillRect(-side / 2, -side / 2, side, side);
   ctx.strokeRect(-side / 2, -side / 2, side, side);
   ctx.restore();
 }
 
const board = [
  {x: 0, y: 0, fill: 'FloralWhite'},
  {x: 1, y: 0, fill: 'FloralWhite'},
  {x: -1, y: 0, fill: 'FloralWhite'},
  {x: 0, y: 1, fill: 'FloralWhite'},
  {x: 0, y: -1, fill: 'FloralWhite'},
  {x: 1, y: -1, fill: 'FloralWhite'},
  {x: -1, y: 1, fill: 'FloralWhite'},
];

const player = {x: 2, y: 2, fill: 'red'};

const render = () => {
  ctx.clearRect(-500, -500, 1000, 1000);
  board.forEach((p) => rhombus(p.x, p.y, p.fill));
  rhombus(player.x, player.y, player.fill);
}

render();

document.addEventListener('keydown', (e) => {
  let dx = 0, dy = 0;
  switch (e.code) {
    case 'ArrowUp':
    	dx = 1, dy = -1; break;
    case 'ArrowDown':
    	dx = -1, dy = 1; break;
    case 'ArrowLeft':
    	dx = -1, dy = -1; break;
    case 'ArrowRight':
    	dx = 1, dy = 1; break;
    case 'KeyA':
    	dx = -1; break;
    case 'KeyS':
    	dy = 1; break;
    case 'KeyD':
    	dx = 1; break;
    case 'KeyW':
    	dy = -1; break;
    case 'Space':
      player.x = 2;
      player.y = 2;
    default:
      console.log(e.code);
  }
  
  player.x += dx;
  player.y += dy;
  render();
});