// Define what kind of tiles exist class Square { static Wall = new Square('Wall'); static Floor = new Square('Floor'); static Player = new Square('Player'); static Box = new Square('Box'); static Destination = new Square('Destination'); static PlayerOnDestination = new Square('PlayerOnDestination'); static BoxOnDestination = new Square('BoxOnDestination'); constructor(name) { this.name = name; } } class CanMove { static Yes = new CanMove('Yes'); static No = new CanMove('No'); static Maybe = new CanMove('Maybe'); constructor(name) { this.name = name; } } const movePosition = (position, direction) => { } const images = { wall: 'wall.png', floor: 'floor.png', player: 'player.png', box: 'box.png', destination: 'destination.png', empty: 'empty.png', }; // Blueprint for the first level const level1Blueprint = [[ Square.Wall, Square.Wall, Square.Wall, Square.Wall, Square.Wall, Square.Wall ], [ Square.Wall, Square.Destination, Square.Box, Square.Floor, Square.Player, Square.Wall ], [ Square.Wall, Square.Wall, Square.Wall, Square.Wall, Square.Wall, Square.Wall ]]; // define where the player can move class MoveDirection { static Right = new MoveDirection('Right'); static Left = new MoveDirection('Left'); static Up = new MoveDirection('Up'); static Down = new MoveDirection('Down'); constructor(name) { this.name = name; } } class Position { constructor(x, y) { this.x = x; this.y = y; } move(direction) { switch (direction) { case MoveDirection.Right: this.x++; break; case MoveDirection.Left: this.x--; break; case MoveDirection.Up: this.y--; break; case MoveDirection.Down: this.y++; break; } } moveBackwards(direction) { switch (direction) { case MoveDirection.Right: this.x--; break; case MoveDirection.Left: this.x++; break; case MoveDirection.Up: this.y++; break; case MoveDirection.Down: this.y--; break; } } isWithin(pos) { return this.x < pos.x && this.y < pos.y; } isEqual(pos) { return this.x === pos.x && this.y === pos.y; } } const copyPosition = (pos) => { return new Position(pos.x, pos.y); } class Tile { constructor(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; this.canMove = CanMove.No; } isMovable() { return this.canMove; } } class ForegroundTile extends Tile{ constructor(square, x, y, width, height) { super(x, y, width, height) switch(square) { case Square.Wall: this.image = images.empty; this.canMove = CanMove.Yes; break; case Square.Floor: this.image = images.empty; this.canMove = CanMove.Yes; break; case Square.Player: this.image = images.player; this.canMove = CanMove.Maybe; break; case Square.Box: this.image = images.box; this.canMove = CanMove.Maybe; break; case Square.Destination: this.image = images.empty; this.canMove = CanMove.Yes; break; case Square.PlayerOnDestination: this.image = images.player; this.canMove = CanMove.Maybe; break; case Square.BoxOnDestination: this.image = images.box; this.canMove = CanMove.Maybe; break; } } } class BackgroundTile extends Tile{ constructor(square, x, y, width, height) { super(x, y, width, height) switch(square) { case Square.Wall: this.image = images.wall; break; case Square.Floor: this.image = images.floor; break; case Square.Player: this.image = images.floor; break; case Square.Box: this.image = images.floor; break; case Square.Destination: this.image = images.destination; break; case Square.PlayerOnDestination: this.image = images.destination; break; case Square.BoxOnDestination: this.image = images.destination; break; } if (square === Square.Wall) { this.canMove = CanMove.No; } else { this.canMove = CanMove.Yes; } } } // generate a level Object from a blueprint const generatePlayground = (levelBlueprint, canvasWidth, canvasHeight) => { let playerExists = false; let background = []; let foreground = []; let boxCount = 0; let destinationCount = 0; const playgroundWidth = levelBlueprint[0].length; const playgroundHeight = levelBlueprint.length; const tileWidth = canvasWidth / playgroundWidth; const tileHeight = canvasHeight / playgroundHeight; let playerPos = { x: NaN, y: NaN, }; levelBlueprint.forEach((levelRow, indexRow) => { background.push([]); foreground.push([]); levelRow.forEach((square, indexColumn) => { switch (square) { case Square.Player: case Square.PlayerOnDestination: if (playerExists) { alert("Player already exists."); } playerExists = true; playerPos = new Position(indexColumn, indexRow); break; case Square.Box: boxCount++; break; case Square.Destination: destinationCount++; break; default: break; } foreground[indexRow].push(new ForegroundTile(square, indexColumn * tileWidth, indexRow * tileHeight, tileWidth, tileHeight)); background[indexRow].push(new BackgroundTile(square, indexColumn * tileWidth, indexRow * tileHeight, tileWidth, tileHeight)); }); }); if (boxCount != destinationCount) { alert("boxCount != destinationCount") } return { foreground: foreground, background: background, width: playgroundWidth, height: playgroundHeight, playerPos: playerPos, canMove(pos) { const foregroundAnswer = this.foreground[pos.y][pos.x].isMovable(); const backgroundAnswer = this.background[pos.y][pos.x].isMovable(); if (backgroundAnswer == CanMove.No) { return CanMove.No; } else { return foregroundAnswer; } }, move(direction) { let aux = copyPosition(this.playerPos); let willMove = false; let finishedChecking = false; let moveCount = 0; while (aux.isWithin({x: this.width, y: this.height}) && !finishedChecking) { console.log("checking at position:"); console.log(aux); console.log("answer"); console.log(this.canMove(aux)); switch(this.canMove(aux)) { case CanMove.Yes: willMove = true; finishedChecking = true; break; case CanMove.No: willMove = false; finishedChecking = true; break; case CanMove.Maybe: aux.move(direction); moveCount++; break; } } console.log(this.playerPos); console.log("in playground.move"); if (willMove) { this.playerPos.move(direction); let posOfObjectToMove = copyPosition(aux); for (let i = 0; i < moveCount; i++) { posOfObjectToMove.moveBackwards(direction); console.log("I try to move"); [this.foreground[aux.y][aux.x], this.foreground[posOfObjectToMove.y][posOfObjectToMove.x]] = [this.foreground[posOfObjectToMove.y][posOfObjectToMove.x], this.foreground[aux.y][aux.x]]; aux.moveBackwards(direction); } } } }; } let playground = generatePlayground(level1Blueprint, 500, 500);