onlyforbopi
9/28/2018 - 7:08 AM

JS.Games.Labyrinth.v1

JS.Games.Labyrinth.v1

* {
	margin: 0;
	padding: 0;
}

body {
	background: #222;
}

canvas.game {
	display: block;
	margin: 0 auto;
  border: 5px solid rgba(255,255,255,0.1);
}
var   canvas = null,
         ctx = null,
       width = 500,
      height = 500,
        game = {},
      colors = [
        '#f35d4f',
        '#006849',
        '#c0d988',
        '#6ddaf1',
        '#f1e85b'];

function init() {
  canvas = document.getElementById('game'),
  canvas.width = width;
  canvas.height = height;
  ctx = canvas.getContext('2d'),
  createGame(50, 50, 0);
  setupKeyEvents();
  loop();
}

function setupKeyEvents() {
  document.onkeydown = function(e) {
    move(game.p1, e.which, {left: 37, up: 38, right: 39, down: 40});
    move(game.p2, e.which, {left: 65, up: 87, right: 68, down: 83});
  };
}

function move(p, which, keys) {
  switch (which) {
    case keys.left:
      if (game.map[p.y][p.x-1] == " ") {
        game.map[p.y][p.x-1] = game.map[p.y][p.x];
        game.map[p.y][p.x] = " ";
        p.x -= 1;
      }
      break;
    case keys.up:
      if (game.map[p.y-1][p.x] == " ") {
        game.map[p.y-1][p.x] = game.map[p.y][p.x];
        game.map[p.y][p.x] = " ";
        p.y -= 1;
      }
      break;
    case keys.right:
      if (game.map[p.y][p.x+1] == " ") {
        game.map[p.y][p.x+1] = game.map[p.y][p.x];
        game.map[p.y][p.x] = " ";
        p.x += 1;
      }
      break;
    case keys.down:
      if (game.map[p.y+1][p.x] == " ") {
        game.map[p.y+1][p.x] = game.map[p.y][p.x];
        game.map[p.y][p.x] = " ";
        p.y += 1;
      }
      break;
  }
}

function loop() {
  draw();
  requestAnimFrame(loop);
}

function draw() {
  ctx.clearRect(0, 0, width, height);

  drawMap();

  var h = height / game.map.length;
  var w = width / game.map[0].length;

  game.p1.px = (game.p1.x + 0.5) * w;
  game.p1.py = (game.p1.y + 0.5) * h;
  game.p2.px = (game.p2.x + 0.5) * w;
  game.p2.py = (game.p2.y + 0.5) * h;

  ctx.beginPath();
  ctx.fillStyle = visionRadial(game.p1.px, game.p1.py);
  ctx.rect(game.p1.px - 50, game.p1.py - 50, 100, 100);
  ctx.fill();

  var p1 = ctx.getImageData(game.p1.px - 50, game.p1.py - 50, 100, 100);

  drawMap();

  ctx.beginPath();
  ctx.fillStyle = visionRadial(game.p2.px, game.p2.py);
  ctx.rect(0, 0, width, height);
  ctx.fill();

  ctx.putImageData(p1, game.p1.px - 50, game.p1.py - 50);
}

function drawMap() {
  var h = height / game.map.length;
  for (var y = 0; y < game.map.length; y++) {
    var row = game.map[y];
    var w = width / row.length;
    for (var x = 0; x < row.length; x++) {
      var c = row[x];
      ctx.beginPath();
      ctx.fillStyle = colors[charToColor(c)];
      ctx.rect(w * x, h * y, w, h);
      ctx.fill();
    }
  }
}

function visionRadial(x, y) {
  var grd = ctx.createRadialGradient(x, y, 10, x, y, 50);
  grd.addColorStop(0, "rgba(0,0,0,0)");
  grd.addColorStop(1, "black");
  return grd;
}

function charToColor(c) {
  switch (c) {
    case '#': return 1;
    case ' ': return 2;
    case '1': return 3;
    case '2': return 4;
    case '!': return 0;
    default: throw "No color mapping for char: " + c;
  }
}

function createGame(w, h, torches) {
  var others = "12!",
           x = null,
           y = null;

  game.map = [];
  for (y = 0; y < h; y++) {
    game.map[y] = [];
    for (x = 0; x < w; x++) {
      if (x === 0 || x == w-1 || y === 0 || y == h-1) {
        game.map[y][x] = "##";
      } else {
        game.map[y][x] = "#";
      }
    }
  }

  // prim's algorithm
  var cell = {
    x: Math.floor(Math.random() * (w - 1) + 1),
    y: Math.floor(Math.random() * (h - 1) + 1)
  };
  game.map[cell.y][cell.x] = " ";
  var walls = [
    {x: cell.x - 1, y: cell.y},
    {x: cell.x + 1, y: cell.y},
    {x: cell.x, y: cell.y - 1},
    {x: cell.x, y: cell.y + 1}
  ];
  while (walls.length > 0) {
    var wall = walls.splice(Math.floor(Math.random() * walls.length), 1)[0];

    if (game.map[wall.y - 1] && game.map[wall.y + 1] &&
      game.map[wall.y - 1][wall.x] == " " && game.map[wall.y + 1][wall.x] == "#")
    {
      game.map[wall.y + 1][wall.x] = game.map[wall.y][wall.x] = " ";
      walls.push({x: wall.x - 1, y: wall.y + 1});
      walls.push({x: wall.x + 1, y: wall.y + 1});
      walls.push({x: wall.x, y: wall.y + 2});
    }
    else if (game.map[wall.y - 1] && game.map[wall.y + 1] &&
      game.map[wall.y + 1][wall.x] == " " && game.map[wall.y - 1][wall.x] == "#")
    {
      game.map[wall.y - 1][wall.x] = game.map[wall.y][wall.x] = " ";
      walls.push({x: wall.x - 1, y: wall.y - 1});
      walls.push({x: wall.x + 1, y: wall.y - 1});
      walls.push({x: wall.x, y: wall.y - 2});
    }
    else if (game.map[wall.y] && game.map[wall.y] &&
      game.map[wall.y][wall.x - 1] == " " && game.map[wall.y][wall.x + 1] == "#")
    {
      game.map[wall.y][wall.x + 1] = game.map[wall.y][wall.x] = " ";
      walls.push({x: wall.x + 1, y: wall.y - 1});
      walls.push({x: wall.x + 1, y: wall.y + 1});
      walls.push({x: wall.x + 2, y: wall.y});
    }
    else if (game.map[wall.y] && game.map[wall.y] &&
      game.map[wall.y][wall.x + 1] == " " && game.map[wall.y][wall.x - 1] == "#")
    {
      game.map[wall.y][wall.x - 1] = game.map[wall.y][wall.x] = " ";
      walls.push({x: wall.x - 1, y: wall.y - 1});
      walls.push({x: wall.x - 1, y: wall.y + 1});
      walls.push({x: wall.x - 2, y: wall.y});
    }
  }

  for (y = 0; y < h; y++) {
    for (x = 0; x < w; x++) {
      if (game.map[y][x] == "##") {
        game.map[y][x] = "#";
      }
    }
  }

  // place players and torches
  while (others.length > 0) {
    x = Math.floor(Math.random() * w);
    y = Math.floor(Math.random() * h);
    if (game.map[y][x] == " ") {
      game.map[y][x] = others[
        Math.floor(Math.random() * others.length)
      ];
      switch (game.map[y][x]) {
        case "1":
          game.p1 = {x: x, y: y};
          others = others.replace("1", "");
          break;
        case "2":
          game.p2 = {x: x, y: y};
          others = others.replace("2", "");
          break;
        case "!":
          torches--;
          if (torches <= 0) {
            others = others.replace("!", "");
          }
          break;
        default:
          throw "Invalid char: " + game.map[y][x];
      }
    }
  }
}

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

init();

JS.Games.Labyrinth.v1

A labyrinth game where two players must find each other.

A Pen by Pan Doul on CodePen.

License.

<canvas id="game" class="game"></canvas>