DEV Community

artydev
artydev

Posted on

2

A Very Simple Game in plain JS

You can play with it here SlidingGame:

<html lang="de">
  <head>
    <meta charset="utf-8" />
    <title>title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://efpage.de/DML/DML_homepage/lib/DML-min.js"></script>
  </head>
  <body>
    <script>
      var dove = new Image();
      dove.src =
        "https://pbs.twimg.com/profile_images/810261498635423745/7Jt0ZuOq_400x400.jpg";
      function sleep(ms) {
        return new Promise((r, err) => {
          setTimeout(r, ms);
        });
      }

      class Board {
        cssCell = `
      background:darkorange;
      height:100px; width:100px;
      margin:0px;cursor:pointer;flex: 0 0 100px;
      display:flex;align-items: center;
      justify-content: center;color: orange; 
      padding: 1px;
    `;

        cssBoard = `
      padding:10px;display:flex;
      flex-wrap:wrap;background:darkorange;
      width:408px;margin:0 auto;
      border-radius: 5px;
    `;

        historypos = [];
        undos = [];
        redos = [];
        undoing = false;
        redoing = false;

        checkValidBoard() {
          function checkPos(c) {
            return c.dataset.pos == c.dataset.curpos;
          }
          return this.cells.every(checkPos);
        }

        findDirectionToMove(cell) {
          const [getCol, getRow] = [
            (pos) => pos % 4,
            (pos) => Math.trunc(pos / 4)
          ];

          const cellpos = Number(cell.dataset.curpos);
          const emptyCellpos = Number(this.emptyCell.dataset.curpos);

          const rowcolEmpty = [getRow(emptyCellpos), getCol(emptyCellpos)];
          const rowcolCell = [getRow(cellpos), getCol(cellpos)];

          const sameColOrRow =
            rowcolEmpty[0] == rowcolCell[0] || rowcolEmpty[1] == rowcolCell[1];

          if (!sameColOrRow) return;

          const directions = {
            [cellpos - 1]: "left",
            [cellpos + 1]: "right",
            [cellpos - 4]: "up",
            [cellpos + 4]: "down"
          };
          let posdir = Object.keys(directions).find(
            (pos) => pos == emptyCellpos
          );
          return directions[posdir];
        }

        findOpositeDirection(direction) {
          if (direction == "up") {
            return "down";
          }
          if (direction == "down") {
            return "up";
          }
          if (direction == "left") {
            return "right";
          }
          if ((direction = "right")) {
            return "left";
          }
        }

        moveCell(cell) {
          const direction = this.findDirectionToMove(cell);
          if (!direction) return;

          const amount = 102;
          const duration = 200;
          const coef = {
            left: -1,
            right: 1,
            down: 1,
            up: -1
          };

          const oppositeDirection = this.findOpositeDirection(direction);

          const cssTranslate = (cell, direction) => {
            if (direction == "left" || direction == "right") {
              cell.dataset.dx =
                Number(cell.dataset.dx) + amount * coef[direction];
            }
            if (direction == "up" || direction == "down") {
              cell.dataset.dy =
                Number(cell.dataset.dy) + amount * coef[direction];
            }
            return `translate(${cell.dataset.dx}px, ${cell.dataset.dy}px )`;
          };

          cell.animate(
            { transform: cssTranslate(cell, direction) },
            { duration: duration, fill: "forwards" }
          );

          this.emptyCell.animate(
            { transform: cssTranslate(this.emptyCell, oppositeDirection) },
            { duration: duration, fill: "forwards" }
          );

          let temp = this.emptyCell.dataset.curpos;
          this.emptyCell.dataset.curpos = cell.dataset.curpos;
          cell.dataset.curpos = temp;

          this.historypos.push(Number(cell.dataset.curpos));

          if (this.undoing == false) this.undos = [...this.historypos];
          this.undoing = false;

          if (this.redoing == false) this.redos = [...this.undos];
          this.redoing = false;
        }

        createCells() {
          // fills cells array with cell element
          this.cells = [...Array(16)].map((_, i) => {
            let y = Math.trunc(i / 4);
            let x = i % 4;
            let options = {
              style: this.cssCell,
              ["data-pos"]: i,
              ["data-curpos"]: i,
              ["data-dx"]: 0,
              ["data-dy"]: 0
            };
            let cell = create("div", options);
            selectBase(cell);
            var canvas = canvas2D({ width: "100px", height: "100px" });
            canvas.ctx.drawImage(
              dove,
              100 * x,
              100 * y,
              100,
              100,
              0,
              0,
              100,
              100
            );
            unselectBase();
            cell.onclick = () => {
              this.moveCell(cell);
            };
            return cell;
          });

          // empty cell customisation
          this.emptyCell = this.cells[15];
          this.emptyCell.style.opacity = "0.25";
          this.emptyCell.style.zIndex = 0;
        }

        displayBoard() {
          selectBase(div(""));
          print("<h1 style='text-align:center'>Sliding Puzzle</h1>");
          unselectBase();

          this.board = selectBase(div("", { style: this.cssBoard }));
          this.cells.map(appendBase);
          unselectBase();

          selectBase(div("", "text-align:center;margin-top:20px"));
          button("Shuffle").onclick = () => this.shuffle();
          button("Reset").onclick = () => {
            this.board.innerHTML = "";
            selectBase(this.board);
            this.createCells();
            this.cells.map(appendBase);
            unselectBase();
          };
          button("undo").onclick = () => {
            if (this.undos.length > 0) {
              this.undoing = true;
              let lastpos = this.undos.splice(-1)[0];
              this.moveCellByCurpos(lastpos);
            }
          };
          button("redo").onclick = () => {
            if (this.redos.length > 0) {
              this.redoing = true;
              let lastpos = this.redos.splice(-1)[0];
              this.moveCellByCurpos(lastpos);
            }
          };
          unselectBase();
        }

        moveCellByCurpos(cellpos) {
          let cell = this.cells.find((cell) => cell.dataset.curpos == cellpos);
          this.moveCell(cell);
        }

        async shuffle() {
          for (let i = 0; i < 100; i++) {
            const emptyPos = Number(this.emptyCell.dataset.curpos);
            const validPos = [
              emptyPos - 1,
              emptyPos + 1,
              emptyPos - 4,
              emptyPos + 4
            ].filter((pos) => {
              return pos >= 0 && pos <= 15;
            });
            const randomPos =
              validPos[Math.floor(Math.random() * validPos.length)];
            await sleep(10);
            this.moveCellByCurpos(randomPos);
          }
        }

        start() {
          this.createCells();
          this.displayBoard();
        }
      }

      function main() {
        dove.onload = () => {
          window.b = new Board();
          b.start();
        };
      }

      main();
    </script>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)