diff --git a/modules/enums.mjs b/modules/enums.mjs new file mode 100644 index 0000000..1e5585c --- /dev/null +++ b/modules/enums.mjs @@ -0,0 +1,36 @@ + +// Define what kind of tiles exist +export 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; + } +} + +export class CanMove { + static Yes = new CanMove('Yes'); + static No = new CanMove('No'); + static Maybe = new CanMove('Maybe'); + + constructor(name) { + this.name = name; + } +} + +export 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; + } +} diff --git a/modules/levels.mjs b/modules/levels.mjs new file mode 100644 index 0000000..98d631b --- /dev/null +++ b/modules/levels.mjs @@ -0,0 +1,6 @@ +import { Square } from './enums.mjs'; + +// Blueprint for the first level +export 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 ]]; diff --git a/modules/playground.mjs b/modules/playground.mjs new file mode 100644 index 0000000..37a0880 --- /dev/null +++ b/modules/playground.mjs @@ -0,0 +1,117 @@ +import { Square, CanMove, MoveDirection } from './enums.mjs' +import { Position, copyPosition } from './position.mjs' +import { ForegroundTile, BackgroundTile } from './tiles.mjs' + +// define where the player can move +// generate a level Object from a blueprint +export 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); + } + } + }, + draw(ctx) { + for (let row of this.background) { + for (let tile of row) { + tile.draw(ctx); + } + } + for (let row of this.foreground) { + for (let tile of row) { + tile.draw(ctx); + } + } + } + }; +} diff --git a/modules/position.mjs b/modules/position.mjs new file mode 100644 index 0000000..71cfc39 --- /dev/null +++ b/modules/position.mjs @@ -0,0 +1,51 @@ +export 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; + } +} + +export const copyPosition = (pos) => { + return new Position(pos.x, pos.y); +} diff --git a/modules/ressources.mjs b/modules/ressources.mjs new file mode 100644 index 0000000..bcba855 --- /dev/null +++ b/modules/ressources.mjs @@ -0,0 +1,8 @@ +export const images = { + wall: 'wall.png', + floor: 'floor.png', + player: 'mario.png', + box: 'box.png', + destination: 'destination.png', + empty: 'empty.png', +}; diff --git a/modules/tiles.mjs b/modules/tiles.mjs new file mode 100644 index 0000000..c30a485 --- /dev/null +++ b/modules/tiles.mjs @@ -0,0 +1,101 @@ +import { images } from './ressources.mjs'; +import { CanMove, Square } from './enums.mjs'; + +class Tile { + constructor(x, y, width, height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.canMove = CanMove.No; + this.image = new Image(); + this.imageReady = false; + } + + isMovable() { + return this.canMove; + } + + draw(ctx) { + if (this.imageReady) { + ctx.drawImage(this.image, this.x, this.y, this.width, this.height); + } + } + + setImageSrc(src) { + this.image.src = src; + this.image.addEventListener('load', () => { + this.imageReady = true; + }, false); + } +} + +export class ForegroundTile extends Tile{ + constructor(square, x, y, width, height) { + super(x, y, width, height) + switch(square) { + case Square.Wall: + this.setImageSrc( images.empty ); + this.canMove = CanMove.Yes; + break; + case Square.Floor: + this.setImageSrc( images.empty ); + this.canMove = CanMove.Yes; + break; + case Square.Player: + this.setImageSrc( images.player ); + this.canMove = CanMove.Maybe; + break; + case Square.Box: + this.setImageSrc( images.box ); + this.canMove = CanMove.Maybe; + break; + case Square.Destination: + this.setImageSrc( images.empty ); + this.canMove = CanMove.Yes; + break; + case Square.PlayerOnDestination: + this.setImageSrc( images.player ); + this.canMove = CanMove.Maybe; + break; + case Square.BoxOnDestination: + this.setImageSrc( images.box ); + this.canMove = CanMove.Maybe; + break; + } + } +} + +export class BackgroundTile extends Tile{ + constructor(square, x, y, width, height) { + super(x, y, width, height) + switch(square) { + case Square.Wall: + this.setImageSrc( images.wall ); + break; + case Square.Floor: + this.setImageSrc( images.floor ); + break; + case Square.Player: + this.setImageSrc( images.floor ); + break; + case Square.Box: + this.setImageSrc( images.floor ); + break; + case Square.Destination: + this.setImageSrc( images.destination ); + break; + case Square.PlayerOnDestination: + this.setImageSrc( images.destination ); + break; + case Square.BoxOnDestination: + this.setImageSrc( images.destination ); + break; + } + if (square === Square.Wall) { + this.canMove = CanMove.No; + } else { + this.canMove = CanMove.Yes; + } + } +}