Skip to content

Instantly share code, notes, and snippets.

@easilyBaffled
Created December 14, 2020 02:50
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 easilyBaffled/ef3847935f2985bca1d8afb3ebf87e96 to your computer and use it in GitHub Desktop.
Save easilyBaffled/ef3847935f2985bca1d8afb3ebf87e96 to your computer and use it in GitHub Desktop.
import "./styles.scss";
import level1 from "./levels/level-1";
import { createShakeAnimation } from "./shakeAnimation";
const gridSize = parseInt(
getComputedStyle(document.body).getPropertyValue("--grid-size"),
10
);
const tileSize = parseInt(
getComputedStyle(document.body).getPropertyValue("--tile-size"),
10
);
let pos = {
x: 0,
y: 0
};
let lockMove = false;
const player = document.querySelector("#player");
const goal = document.querySelector("#goal");
const board = document.querySelector("#board");
const translate = ({ x, y }) =>
`translate(${x * tileSize}vw, ${y * tileSize}vw)`;
player.ontransitionend = () => (lockMove = false);
const getTileType = (tileChar) =>
({
s: "start",
e: "end",
w: "wall"
}[tileChar] ?? "empty");
const makeTileObj = (y) => (tileChar, x) => ({
type: getTileType(tileChar),
pos: { x, y }
});
const parseLine = (line, xCoord) =>
line.replace(/\|/g, "").split("").map(makeTileObj(xCoord));
const parseMap = (stringMap) =>
stringMap.match(/^\|(?<line>.+)\|$/gm).flatMap(parseLine);
const isNotEmpty = (tile) => tile.type !== "empty";
const isAWall = (tile) => tile.type === "wall";
const isStart = (tile) => tile.type === "start";
const isEnd = (tile) => tile.type === "end";
const renderLevel = ({ start, renderWalls, end }) => {
player.style.transform = translate(start.pos);
goal.style.transform = translate(end.pos);
board.insertAdjacentHTML("beforeend", renderWalls);
};
const createLevel = (mapString) => {
const mapArr = parseMap(mapString);
const nonEmptyTiles = mapArr.filter(isNotEmpty);
const walls = nonEmptyTiles.filter(isAWall);
const last = mapArr[mapArr.length - 1];
const renderWalls = walls.reduce(
(acc, wall) =>
acc +
`<div class="wall tile" style="transform: ${translate(wall.pos)}"></div>`,
""
);
const start = nonEmptyTiles.find(isStart);
const end = nonEmptyTiles.find(isEnd);
return {
mapString,
mapArr,
nonEmptyTiles,
walls,
renderWalls,
start,
end,
isValidMove: (pos) => {
return (
pos.x > -1 &&
pos.x <= last.pos.x &&
pos.y > -1 &&
pos.y <= last.pos.y &&
walls.every((w) => !(pos.x === w.pos.x && pos.y === w.pos.y))
);
}
};
};
const level = createLevel(level1);
renderLevel(level);
document.body.onkeyup = (e) => {
e.stopPropagation();
e.preventDefault();
if (lockMove) return;
const nextPos = {
ArrowUp: { x: pos.x, y: pos.y - 1 },
ArrowDown: { x: pos.x, y: pos.y + 1 },
ArrowLeft: { y: pos.y, x: pos.x - 1 },
ArrowRight: { y: pos.y, x: pos.x + 1 }
}[e.key];
if (!level.isValidMove(nextPos)) {
lockMove = true;
player
.animate(createShakeAnimation(pos, tileSize), {
// timing options
duration: 700,
iterations: 1,
easing: `cubic-bezier(.36,.07,.19,.97)`
})
.finished.then(() => {
console.log("done");
lockMove = false;
});
return;
}
pos = nextPos;
lockMove = true;
player.style.transform = translate(pos);
if (nextPos.x === level.end.pos.x && nextPos.y === level.end.pos.y)
setTimeout(() => alert("you win"), 300);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment