Skip to content

Instantly share code, notes, and snippets.

@dmitryshelomanov
Created July 2, 2019 08:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmitryshelomanov/9ea1b3ab4790eac8bda1dc16ca80133d to your computer and use it in GitHub Desktop.
Save dmitryshelomanov/9ea1b3ab4790eac8bda1dc16ca80133d to your computer and use it in GitHub Desktop.
import { createEvent, createStore } from "effector";
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const scoreElement = document.querySelector("#score");
const DIRECTIONS = {
LEFT: 37,
RIGHT: 39,
TOP: 38,
DOWN: 40
};
const APPLES_TYPE = {
SIMPLE: 1
};
const eatApple = createEvent("eat apple");
const eatSelf = createEvent("eat self");
const changeDirection = createEvent("change direaction");
const storeBoard = createStore(0)
.on(eatApple, (prev, next) => prev + next)
.on(eatSelf, () => 0);
const direction = createStore(DIRECTIONS.RIGHT)
.on(changeDirection, (_, dir) => dir)
.on(eatSelf, () => DIRECTIONS.RIGHT);
storeBoard.watch(count => {
scoreElement.textContent = count;
});
function setCanvasSize(ctx, { w, h }) {
ctx.canvas.height = h;
ctx.canvas.width = w;
}
function drawSquare(ctx, [x, y], cellSize, color = "black") {
ctx.fillStyle = color;
ctx.fillRect(x, y, cellSize, cellSize);
}
function renderApple(ctx, apple) {
drawSquare(ctx, apple[0], apple[2], "red");
}
function biuildSnake(cellSize, length) {
return Array.from({ length }, (_, i) => [cellSize * i, 0]);
}
function randomPosiotion({ w, h }, cellSize) {
const x = Math.floor(w / cellSize);
const y = Math.floor(h / cellSize);
function intNumber(n) {
return Math.floor(Math.random() * n);
}
return [intNumber(x) * cellSize, intNumber(y) * cellSize];
}
function getNextPositionByDirection([x, y], dir, cellSize) {
switch (dir) {
case DIRECTIONS.LEFT:
return [x - cellSize, y];
case DIRECTIONS.RIGHT:
return [x + cellSize, y];
case DIRECTIONS.TOP:
return [x, y - cellSize];
case DIRECTIONS.DOWN:
return [x, y + cellSize];
default:
return [x, y];
}
}
function checkBounds([x, y], { w, h }, cellSize) {
if (w < x) {
x = 0;
}
if (h < y) {
y = 0;
}
if (y < 0) {
y = h - cellSize;
}
if (x < 0) {
x = w - cellSize;
}
return [x, y];
}
function checkCollision([x, y], [x1, y1]) {
if (x === x1 && y === y1) {
return true;
}
return false;
}
function keyboardHandle(handle) {
document.addEventListener("keyup", e => {
if (Object.values(DIRECTIONS).includes(e.keyCode)) {
handle(e.keyCode);
}
});
}
function main({ w, h, fps = 10, interval = 100 / fps }) {
let isPressed = false;
let now = null;
let then = Date.now();
const cellSize = 20;
let snake = biuildSnake(cellSize, 3);
let apple = [
randomPosiotion({ w, h }, cellSize),
APPLES_TYPE.SIMPLE,
cellSize
];
setCanvasSize(ctx, { w, h }, cellSize);
function moveSnake(nextPosition) {
const [_, ...tail] = snake;
return [...tail, nextPosition];
}
function loop() {
now = Date.now();
const delta = now - then;
requestAnimationFrame(loop);
if (delta > interval) {
then = now - (delta % interval);
ctx.clearRect(0, 0, w, h);
const headPosition = getNextPositionByDirection(
snake[snake.length - 1],
direction.getState(),
cellSize
);
const nextPosition = checkBounds(headPosition, { w, h }, cellSize);
snake = moveSnake(nextPosition);
const isEat = checkCollision(nextPosition, apple[0]);
if (isEat) {
apple[0] = randomPosiotion({ w, h }, cellSize);
eatApple(apple[1]);
const peaceOfSnake = getNextPositionByDirection(
snake[snake.length - 1],
direction.getState(),
cellSize
);
snake.push(peaceOfSnake);
}
renderApple(ctx, apple, cellSize);
for (let i = 0; i < snake.length; i++) {
const isCrash = checkCollision(snake[snake.length - 1], snake[i]);
if (i !== snake.length - 1 && isCrash) {
snake = biuildSnake(cellSize, 3);
eatSelf();
}
drawSquare(ctx, snake[i], cellSize, "black");
}
isPressed = false;
}
}
keyboardHandle(key => {
if (!isPressed) {
isPressed = true;
const dir = direction.getState();
if (key === DIRECTIONS.RIGHT && dir !== DIRECTIONS.LEFT)
changeDirection(DIRECTIONS.RIGHT);
if (key === DIRECTIONS.DOWN && dir !== DIRECTIONS.TOP)
changeDirection(DIRECTIONS.DOWN);
if (key === DIRECTIONS.LEFT && dir !== DIRECTIONS.RIGHT)
changeDirection(DIRECTIONS.LEFT);
if (key === DIRECTIONS.TOP && dir !== DIRECTIONS.DOWN)
changeDirection(DIRECTIONS.TOP);
}
});
requestAnimationFrame(loop);
}
main({ w: 500, h: 500, fps: 60, interval: 100 });
@dmitryshelomanov
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment