<html>

<head>
    <link rel="stylesheet" type="text/css" href="main.css">
     <script src="https://code.jquery.com/jquery-1.12.3.js" integrity="sha256-1XMpEtA4eKXNNpXcJ1pmMPs8JV+nwLdEqwiJeCQEkyc=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jcanvas/21.0.1/min/jcanvas.min.js"></script>
    <script src="game/game.js"></script>
</head>

<body>
    <h1>snakeQuery</h1>
    <canvas id="myCanvas" width="600" height="300">
        <p>This is fallback content
            for users of assistive technologies
            or of browsers that don't have
            full support for the Canvas API.</p>
    </canvas>
</body>

</html>
html,body{
    background-color: black;
    color: lawngreen;
    font-family: Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace; 
}
var gameRunning = false;
var gameover = false;
var bodySize = 10;
var headdir = { x: bodySize, y: 0 };
var speed = 200;
var initial = true;
var switchpoint = [];
var keymap = {
  119: { x: 0, y: -bodySize },
  97: { x: -bodySize, y: 0 },
  115: { x: 0, y: bodySize },
  100: { x: bodySize, y: 0 }
};
var font =
  "Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace";
var message = {
  fillStyle: "lime",
  strokeStyle: "lime",
  strokeWidth: 2,
  x: 300,
  y: 150,
  fontSize: 48,
  fontFamily: font,
  text: "--- scurr ---"
};
window.CP.PenTimer.MAX_TIME_IN_LOOP_WO_EXIT = 999999999;
var gameRoom = {
  fillStyle: "",
  strokeStyle: "lime",
  strokeWidth: bodySize,
  x: 0,
  y: 0,
  fromCenter: false,
  width: 600,
  height: 300,
  dir: { x: bodySize, y: 0 }
};
var basicSnake = {
  fillStyle: "black",
  strokeStyle: "lime",
  strokeWidth: 1,
  x: 45,
  y: 5,
  fromCenter: false,
  width: bodySize - 1,
  height: bodySize - 1,
  dir: { x: bodySize, y: 0 }
};
var basicFood = {
  fillStyle: "black",
  strokeStyle: "red",
  strokeWidth: 1,
  x: 45,
  y: 5,
  fromCenter: false,
  width: bodySize - 1,
  height: bodySize - 1,
  dir: { x: bodySize, y: 0 }
};
var snake = [basicSnake];
var food = null;
$(document).ready(function() {
  var $myCanvas = $("#myCanvas");
  $myCanvas.drawRect(gameRoom);
  $(window).keypress(async function(e) {
    var key = e.which;
    if (checkDir(key, snake[0]) != headdir) {
      headdir = checkDir(key, snake[0]);
      switchpoint.push({ x: snake[0].x, y: snake[0].y });
    }
    if (key === 32) {
      initial = false;
      gameRunning = !gameRunning;
      while (gameRunning) {
        if (checkCollision(snake, bodySize, gameRoom, food)) {

          snake.forEach((sBody, i) => {
            moveSnake(snake, snake.length - 1 - i);
          });
          if (!food) {
            food = createFood(gameRoom, snake);
          }
          drawGame(snake, gameRoom, food, $myCanvas);
          await sleep(speed);
        } else {
          gameRunning = !gameRunning;
          gameover = true;
        }
      }
      if (gameover) {
        message.text = "--- Game Over " + snake.length + " ---";
        $("canvas").drawText(message);
      } else if (!initial && !gameRunning) {
        message.text = "--- Pause " + snake.length + " ---";
        $("canvas").drawText(message);
      }
    }
  });
});
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
function drawGame(psnake, gameRoom, food, canvas) {
  canvas.clearCanvas({}).drawRect(gameRoom);
  canvas.drawRect(food);
  psnake.forEach((s, i) => {
    canvas.drawRect(s);
  });
}
function checkDir(key, s) {
  if (keymap[key]) {
    return keymap[key];
  } else {
    return s.dir;
  }
}
function moveSnake(s, i) {
  var sdir;
  if (s[i - 1]) {
    sdir = s[i - 1].dir;
  } else {
    sdir = headdir;
  }
  switchpoint.forEach(sp => {
    checkSwitchpoint(sp, sdir, i, s);
  });
  s[i].x += s[i].dir.x;
  s[i].y += s[i].dir.y;
}
function checkCollision(s, bSize, gR, foo) {
  if (checkFood(foo, s[0])) {
    food = null;
    snake = addNewBody(snake);
  }
  return checkWall(s[0], bSize, gR) && checkSelf(s);
}
function checkSwitchpoint(sP, dirToSet, i, s) {
  if (s[i].x === sP.x && s[i].y === sP.y) {
    s[i].dir = dirToSet;
    if (i === s.length - 1) {
      let killpoint = switchpoint.indexOf(sP);
      switchpoint.splice(killpoint, 1);
    }
  }
}
function addNewBody(sna) {
  let output = jQuery.extend(true, [], sna);
  let s = jQuery.extend(true, {}, basicSnake);
  i = output.length - 1;
  s.dir = output[i].dir;
  s.x = output[i].x - output[i].dir.x;
  s.y = output[i].y - output[i].dir.y;
  output.push(s);
  return output;
}
function checkWall(s, bSize, gR) {
  return (
    s.y < gR.height - bSize &&
    bSize / 2 <= s.y &&
    bSize / 2 <= s.x &&
    s.x < gR.width - bSize
  );
}
function checkFood(foo, s) {
  if (foo) {
    return s.x === foo.x && s.y === foo.y;
  } else {
    return null;
  }
}
function createFood(gR, s) {
  let gRwidth = (gR.width - bodySize * 2) / bodySize;
  let gRheight = (gR.height - bodySize * 2) / bodySize;
  let snakePositions = [];
  let raster = [];
  s.forEach(sB => {
    snakePositions.push({
      x: (sB.x - bodySize / 2) / bodySize,
      y: (sB.y - bodySize / 2) / bodySize + 1
    });
  });
  for (i = 0; i < gRwidth; i++) {
    let xPos = i + 1;
    for (a = 0; a < gRheight; a++) {
      let yPos = a + 1;
      let output = { x: xPos, y: yPos };
      let check = false;
      snakePositions.forEach(sB => {
        if (sB.x === output.x && sB.y === output.y) {
          check = true;
        }
      });
      if (!check) {
        raster.push({ x: xPos, y: yPos });
      }
    }
  }
  let foodRandIndex = Math.floor(Math.random() * raster.length - 1) + 0;
  let out = jQuery.extend(true, {}, basicFood);
  out.x = raster[foodRandIndex].x * bodySize + bodySize / 2;
  out.y = raster[foodRandIndex].y * bodySize + bodySize / 2;
  return out;
}
function checkSelf(s) {
  let head = { x: s[0].x, y: s[0].y };
  ok = true;
  s.forEach((sp, i) => {
    if (sp.x === head.x && sp.y === head.y && i != 0) {
      ok = false;
      return;
    }
  });
  return ok;
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.