<file_sep>const enemyImage = new Image();
enemyImage.src = './images/0_Golem_Walking_000.png';
enemyImage.id = 'enemy';

class Enemy {
  constructor(game, x, y) {
    this.game = game;
    this.x = x;
    this.y = y;
    this.enemyAlive = true;
  }

  runLogic() {
    this.x = this.x - 0.7;
  }

  checkIntersection(element) {
    //check if enemy has overlapping coordinates with player
    return (
      element.x >= this.x &&
      element.x <= this.x + 50 &&
      element.y >= this.y &&
      element.y - 50 <= this.y
    );
  }

  paint() {
    const context = this.game.context;
    context.save();
    context.drawImage(enemyImage, game.enemy.x, game.enemy.y, 100, 100);
    context.restore();
  }
}
<file_sep>const wallMap = [
  [
    0,
    0,
    0,
    0,
    'leftUpperCorner',
    'middle',
    'middle',
    'middle',
    'rightUpperCorner',
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0
  ],
  [0, 0, 0, 0, 'sides', 1, 1, 1, 'sides', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 'sides', 'B', 1, 1, 'sides', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [
    0,
    0,
    'leftUpperCorner',
    'middle',
    'rightLowerCorner',
    1,
    1,
    'B',
    'leftLowerCorner',
    'rightUpperCorner',
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0
  ],
  [0, 0, 'sides', 1, 1, 'B', 1, 'B', 1, 'sides', 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [
    'leftUpperCorner',
    'middle',
    'rightLowerCorner',
    1,
    'upperCorner',
    1,
    'leftUpperCorner',
    'rightUpperCorner',
    1,
    'sides',
    0,
    0,
    0,
    'leftUpperCorner',
    'middle',
    'middle',
    'middle',
    'middle',
    'rightUpperCorner'
  ],
  [
    'sides',
    1,
    1,
    1,
    'lowerCorner',
    1,
    'leftLowerCorner',
    'rightLowerCorner',
    1,
    'leftLowerCorner',
    'middle',
    'middle',
    'middle',
    'rightLowerCorner',
    1,
    1,
    'G',
    'G',
    'sides'
  ],
  ['sides', 1, 'B', 1, 1, 'B', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 'G', 'G', 'sides'],
  [
    'leftLowerCorner',
    'middle',
    'middle',
    'middle',
    'rightUpperCorner',
    1,
    'left',
    'middle',
    'right',
    1,
    'upperCorner',
    1,
    'leftUpperCorner',
    'rightUpperCorner',
    1,
    1,
    'G',
    'G',
    'sides'
  ],
  [
    0,
    0,
    0,
    0,
    'sides',
    1,
    1,
    1,
    1,
    1,
    'leftSide',
    'middle',
    'lowerLeft',
    'lower',
    'middle',
    'middle',
    'middle',
    'middle',
    'rightLowerCorner'
  ],
  [
    0,
    0,
    0,
    0,
    'leftLowerCorner',
    'middle',
    'middle',
    'middle',
    'middle',
    'middle',
    'rightLowerCorner',
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0
  ]
];

class Game {
  constructor(canvas, screens) {
    this.canvas = canvas;
    this.context = canvas.getContext('2d');
    this.screens = screens;
    this.running = false;
    this.enableControls();
  }

  /*drawGrid() {
    for (let x = 0; x <= 950; x += 50) {
      for (let y = 0; y <= 550; y += 50) {
        this.context.beginPath();
        this.context.moveTo(x, 0);
        this.context.lineTo(x, 550);
        this.context.strokeStyle = 'black';
        this.context.stroke();
        this.context.closePath();
        this.context.beginPath();
        this.context.moveTo(0, y);
        this.context.lineTo(950, y);
        this.context.strokeStyle = 'black';
        this.context.stroke();
        this.context.closePath();
      }
    }
  }*/

  drawMap() {
    for (const wall of this.walls) {
      wall.draw();
    }

    for (const background of this.backgrounds) {
      background.draw();
    }

    const backgroundImg = new Image();
    backgroundImg.src = './images/Tile_12.png';
    this.context.drawImage(backgroundImg, 50 * 5, 50 * 2, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 7, 50 * 3, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 5, 50 * 4, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 7, 50 * 4, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 2, 50 * 7, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 5, 50 * 7, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 16, 50 * 8, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 16, 50 * 7, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 17, 50 * 7, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 16, 50 * 6, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 17, 50 * 6, 50, 50);
    this.context.drawImage(backgroundImg, 50 * 17, 50 * 8, 50, 50);

    this.context.fillStyle = '#6a9423';
    this.context.beginPath();
    this.context.arc(50 * 16 + 25, 50 * 8 + 25, 10, 0, 2 * Math.PI);
    this.context.fill();
    this.context.closePath();
    this.context.beginPath();
    this.context.arc(50 * 17 + 25, 50 * 8 + 25, 10, 0, 2 * Math.PI);
    this.context.fill();
    this.context.closePath();
    this.context.beginPath();
    this.context.arc(50 * 16 + 25, 50 * 7 + 25, 10, 0, 2 * Math.PI);
    this.context.fill();
    this.context.closePath();
    this.context.beginPath();
    this.context.arc(50 * 17 + 25, 50 * 7 + 25, 10, 0, 2 * Math.PI);
    this.context.fill();
    this.context.closePath();
    this.context.beginPath();
    this.context.arc(50 * 16 + 25, 50 * 6 + 25, 10, 0, 2 * Math.PI);
    this.context.fill();
    this.context.closePath();
    this.context.beginPath();
    this.context.arc(50 * 17 + 25, 50 * 6 + 25, 10, 0, 2 * Math.PI);
    this.context.fill();
    this.context.closePath();
  }

  drawBoxes() {
    for (const box of this.boxes) {
      box.draw();
    }
  }

  addMapBorders() {
    this.walls = [];
    const GRID_SIZE = 50;

    for (let row = 0; row < wallMap.length; row++) {
      for (let column = 0; column < wallMap[row].length; column++) {
        const value = wallMap[row][column];
        if (value !== 0 && value !== 1 && value !== 'G' && value !== 'B') {
          const wall = new Wall(
            this,
            column * GRID_SIZE,
            row * GRID_SIZE,
            value
          );
          this.walls.push(wall);
        }
      }
    }
  }

  addBackground() {
    this.backgrounds = [];
    const GRID_SIZE = 50;

    for (let row = 0; row < wallMap.length; row++) {
      for (let column = 0; column < wallMap[row].length; column++) {
        const value = wallMap[row][column];
        if (value === 1) {
          const background = new Wall(
            this,
            column * GRID_SIZE,
            row * GRID_SIZE,
            'background'
          );
          this.backgrounds.push(background);
        }
      }
    }
  }

  addBoxes() {
    this.boxes = [];
    const GRID_SIZE = 50;

    for (let row = 0; row < wallMap.length; row++) {
      for (let column = 0; column < wallMap[row].length; column++) {
        const value = wallMap[row][column];
        if (value === 'B') {
          const box = new Box(this, column * GRID_SIZE, row * GRID_SIZE, 'box');
          this.boxes.push(box);
        }
      }
    }
  }

  addGoals() {
    this.goals = [];
    const GRID_SIZE = 50;

    for (let row = 0; row < wallMap.length; row++) {
      for (let column = 0; column < wallMap[row].length; column++) {
        const value = wallMap[row][column];
        if (value === 'G') {
          const goal = new Wall(
            this,
            column * GRID_SIZE,
            row * GRID_SIZE,
            'background'
          );
          this.goals.push(goal);
        }
      }
    }
  }

  displayScreen(name) {
    const screenThatShouldBeDisplayed = this.screens[name];
    const screensThatShouldBeHidden = Object.values(this.screens).filter(
      (screen) => screen !== screenThatShouldBeDisplayed
    );
    screenThatShouldBeDisplayed.style.display = '';
    for (const screen of screensThatShouldBeHidden)
      screen.style.display = 'none';
  }

  start() {
    this.running = true;
    this.addMapBorders();
    this.addBoxes();
    this.addBackground();
    this.addGoals();
    this.player = new Player(this, 550, 400);
    this.enemy = new Enemy(this, 700, 320);
    this.paint();
    this.loop();
    this.displayScreen('playing');
  }

  runLogic() {
    this.player.playerEnemyIntersect();
    this.enemy.runLogic();
    for (let m = 0; m < this.boxes.length; m++) {
      //if any box is in a corner spot
      if (
        (this.boxes[m].x === 50 && this.boxes[m].y === 300) ||
        (this.boxes[m].x === 50 && this.boxes[m].y === 350) ||
        (this.boxes[m].x === 150 && this.boxes[m].y === 200) ||
        (this.boxes[m].x === 250 && this.boxes[m].y === 50) ||
        (this.boxes[m].x === 350 && this.boxes[m].y === 50) ||
        (this.boxes[m].x === 400 && this.boxes[m].y === 200) ||
        (this.boxes[m].x === 450 && this.boxes[m].y === 450) ||
        (this.boxes[m].x === 250 && this.boxes[m].y === 450) ||
        (this.boxes[m].x === 700 && this.boxes[m].y === 300) ||
        (this.boxes[m].x === 700 && this.boxes[m].y === 400)
      ) {
        this.lose();
      }
    }
    //if all boxes are on all circles, game won
    this.boxesongoal = [];
    for (const box of this.boxes) {
      for (const goal of this.goals) {
        if (box.x === goal.x && box.y === goal.y) {
          this.boxesongoal.push(box);
        }
      }
    }
    if (this.boxesongoal.length === 6) {
      this.win();
    }
  }

  loop() {
    if (this.running) {
      this.runLogic();
      this.paint();
      window.requestAnimationFrame(() => {
        this.loop();
      });
    }
  }

  enableControls() {
    window.addEventListener('keydown', (event) => {
      const key = event.code;
      switch (key) {
        case 'ArrowUp':
          this.player.move('up');
          console.log('up');
          console.log(this.player.x, this.player.y);
          break;

        case 'ArrowDown':
          this.player.move('down');
          console.log('down');
          console.log(this.player.x, this.player.y);
          break;

        case 'ArrowRight':
          this.player.move('right');
          console.log('right');
          console.log(this.player.x, this.player.y);
          break;

        case 'ArrowLeft':
          this.player.move('left');
          console.log('left');
          console.log(this.player.x, this.player.y);
          break;

        case 'Space':
          this.player.move('space');
          console.log('attack');
          console.log(this.player.x, this.player.y);
          break;
      }
    });
  }

  clearScreen() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }

  paint() {
    this.clearScreen();
    //this.drawGrid();
    this.drawMap();
    this.drawBoxes();
    this.player.paint();
    if (this.enemy.enemyAlive) {
      this.enemy.paint();
    }
  }

  win() {
    this.running = false;
    this.displayScreen('gameWon');
  }

  lose() {
    this.running = false;
    this.displayScreen('gameOver');
  }
}
<file_sep>const attackImage = new Image();
attackImage.src = './images/Woodcutter_attack1.png';

const pushImage = new Image();
pushImage.src = './images/Woodcutter_push.png';

const playerImage = new Image();
playerImage.src = './images/Woodcutter.png';

class Player {
  constructor(game, x, y) {
    this.game = game;
    this.x = x;
    this.y = y;
    this.frame = 0;
    this.paintPlayer = true;
  }

  move(direction) {
    let newX = this.x;
    let newY = this.y;
    switch (direction) {
      case 'up':
        this.paintPlayer = true;
        this.direction = 'up';
        newY -= 50;
        break;
      case 'down':
        this.paintPlayer = true;
        this.direction = 'down';
        newY += 50;
        break;
      case 'right':
        this.paintPlayer = true;
        this.direction = 'right';
        newX += 50;
        break;
      case 'left':
        this.paintPlayer = true;
        this.direction = 'left';
        newX -= 50;
        break;
      case 'space':
        this.paintPlayer = false;
        if (this.x < this.game.enemy.x && this.x + 20 >= this.game.enemy.x) {
          this.game.enemy.enemyAlive = false;
        }
        if (this.game.enemy.x < this.x && this.x - 100 <= this.game.enemy.x) {
          this.game.enemy.enemyAlive = false;
        }
        if (!this.game.enemy.enemyAlive) {
          this.game.enemy.x = 0;
          this.game.enemy.y = 0;
        }
        break;
    }

    let playerCanMove = true;

    for (const wall of this.game.walls) {
      const playerAndWallIntersect = wall.checkIntersection({
        x: newX,
        y: newY
      });
      if (playerAndWallIntersect) {
        playerCanMove = false;
      }
    }

    const boxes = this.game.boxes;
    for (const box of boxes) {
      const playerAndBoxIntersect = box.checkIntersection({ x: newX, y: newY });
      if (playerAndBoxIntersect) {
        const boxMoved = box.move(direction);
        if (!boxMoved) {
          playerCanMove = false;
        }
      }
    }

    if (playerCanMove) {
      this.x = newX;
      this.y = newY;
    }
  }

  playerBoxIntersect() {
    const boxes = this.game.boxes;
    for (const box of boxes) {
      const playerAndBoxIntersect = box.checkIntersection(this);
      if (playerAndBoxIntersect) {
        switch (this.direction) {
          case 'up':
            box.y -= 50;
            break;

          case 'down':
            box.y += 50;
            break;

          case 'right':
            box.x += 50;
            break;

          case 'left':
            box.x -= 50;
            break;
        }
      }
    }
  }

  playerEnemyIntersect() {
    if (this.game.enemy.checkIntersection(this)) {
      this.game.lose();
    }
  }

  paintAttack() {
    const context = this.game.context;
    context.save();
    context.drawImage(
      attackImage,
      0 + 49 * Math.round(this.frame / 10),
      6,
      49,
      43,
      this.x,
      this.y,
      50,
      50
    );
    context.restore();
    this.frame++;
    this.frame %= 50;
  }

  paint() {
    if (this.paintPlayer) {
      const context = this.game.context;
      context.save();
      context.drawImage(playerImage, 0, 12, 40, 37, this.x, this.y, 50, 50);
      context.restore();
    } else {
      this.paintAttack();
    }
  }
}
<file_sep>const boxImg = new Image();
boxImg.src = './images/2.png';

class Box {
  constructor(game, x, y) {
    this.game = game;
    this.x = x;
    this.y = y;
    this.boxCanMoveUp = true;
    this.boxCanMoveDown = true;
    this.boxCanMoveLeft = true;
    this.boxCanMoveRight = true;
  }

  draw() {
    this.game.context.drawImage(boxImg, this.x, this.y, 50, 50);
  }

  checkIntersection(element) {
    return (
      element.x >= this.x &&
      element.x <= this.x + 49 &&
      element.y >= this.y &&
      element.y <= this.y + 49
    );
  }

  move(direction) {
    let intersects = false;
    let newX = this.x;
    let newY = this.y;
    switch (direction) {
      case 'up':
        newY -= 50;
        break;
      case 'down':
        newY += 50;
        break;
      case 'right':
        newX += 50;
        break;
      case 'left':
        newX -= 50;
        break;
    }
    for (const box of this.game.boxes) {
      if (box.checkIntersection({ x: newX, y: newY })) {
        intersects = true;
      }
    }
    for (const wall of this.game.walls) {
      if (wall.checkIntersection({ x: newX, y: newY })) {
        intersects = true;
      }
    }
    if (intersects) {
      return false;
    } else {
      this.x = newX;
      this.y = newY;
      return true;
    }
  }
}
<file_sep>const leftUpperCornerImage = new Image();
leftUpperCornerImage.src = './images/Tile_01.png';

const rightUpperCornerImage = new Image();
rightUpperCornerImage.src = './images/Tile_03.png';

const leftLowerCornerImage = new Image();
leftLowerCornerImage.src = './images/Tile_21.png';

const rightLowerCornerImage = new Image();
rightLowerCornerImage.src = './images/Tile_23.png';

const rightEdgeImage = new Image();
rightEdgeImage.src = './images/Tile_13.png';

const leftImage = new Image();
leftImage.src = './images/Tile_32.png';

const middleImage = new Image();
middleImage.src = './images/Tile_33.png';

const rightImage = new Image();
rightImage.src = './images/Tile_34.png';

const upperCornerImage = new Image();
upperCornerImage.src = './images/Tile_54.png';

const lowerCornerImage = new Image();
lowerCornerImage.src = './images/Tile_56.png';

const sidesImage = new Image();
sidesImage.src = './images/Tile_55.png';

const lowerImage = new Image();
lowerImage.src = './images/Tile_53.png';

const lowerLeftImage = new Image();
lowerLeftImage.src = './images/Tile_51.png';

const leftSideImage = new Image();
leftSideImage.src = './images/Tile_37.png';

const backgroundImg = new Image();
backgroundImg.src = './images/Tile_12.png';

const allImages = {
  leftUpperCorner: leftUpperCornerImage,
  rightUpperCorner: rightUpperCornerImage,
  leftLowerCorner: leftLowerCornerImage,
  rightLowerCorner: rightLowerCornerImage,
  rightEdge: rightEdgeImage,
  left: leftImage,
  middle: middleImage,
  right: rightImage,
  upperCorner: upperCornerImage,
  lowerCorner: lowerCornerImage,
  sides: sidesImage,
  lower: lowerImage,
  lowerLeft: lowerLeftImage,
  leftSide: leftSideImage,
  background: backgroundImg,
  box: boxImg
};

class Wall {
  constructor(game, x, y, imageName) {
    this.game = game;
    this.x = x;
    this.y = y;
    this.imageName = imageName;
  }

  draw() {
    const imageName = this.imageName;
    const image = allImages[imageName];

    this.game.context.drawImage(image, this.x, this.y, 50, 50);
  }

  checkIntersection(element) {
    return (
      element.x + 49 >= this.x &&
      //disable moving right
      element.x <= this.x + 49 &&
      //disable moving left
      element.y + 49 >= this.y &&
      //disable moving down
      element.y <= this.y + 49
      //disable moving up
    );
  }
}
