diff --git a/package-lock.json b/package-lock.json index 9b7f516..f782184 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5002,6 +5002,18 @@ "pinkie": "^2.0.0" } }, + "pixi-sound": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pixi-sound/-/pixi-sound-3.0.4.tgz", + "integrity": "sha512-e+BteT7KYAEs6SAAuqOFlXEarzMNzsVj6y14ecjQ7W7YzjgxQOUVgYFp6rJrDyEmDeSGvWDIR5x7bRMQZGRpzw==", + "dev": true, + "requires": { + "@pixi/core": "^5.0.2", + "@pixi/loaders": "^5.0.2", + "@pixi/ticker": "^5.0.1", + "@pixi/utils": "^5.0.1" + } + }, "pixi.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-5.2.2.tgz", diff --git a/package.json b/package.json index 4cf0867..22ed0f8 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "html-webpack-plugin": "4.2.0", "only-ttf-loader": "1.0.0", "pathfinding": "^0.4.18", + "pixi-sound": "^3.0.4", "pixi.js": "5.2.2", "source-map-loader": "0.2.4", "stats.js": "0.17.0", diff --git a/src/assets/assets.xcf b/src/assets/assets.xcf index 2bcc64a..155c91b 100644 Binary files a/src/assets/assets.xcf and b/src/assets/assets.xcf differ diff --git a/src/assets/gameover.mp3 b/src/assets/gameover.mp3 new file mode 100644 index 0000000..ee194f7 Binary files /dev/null and b/src/assets/gameover.mp3 differ diff --git a/src/assets/map.json b/src/assets/map.json index 624c030..4f07603 100644 --- a/src/assets/map.json +++ b/src/assets/map.json @@ -3,36 +3,192 @@ "x": 0, "y": 0, "tiles": [ - [ 6, 3, 1, 1, 0, 2, 1, 3, 8], - [ 6, 0, 0, 0, 0, 0, 1, 0, 3], - [ 6, 0, 0, 1, 1, 0, 1, 0, 0], - [ 6, 0, 0, 0, 0, 0, 0, 0, 12], - [ 11, 9, 0, 12, 5, 0, 5, 5, 10], - [ -1, 6, 0, 3, 1, 1, 1, 1, 1] - ] + [ 6, 3, 1, 1, 1, 1, 1, 2, 8 ], + [ 6, 0, 0, 0, 0, 0, 0, 0, 3 ], + [ 6, 0, 0, 0, 0, 0, 4, 0, 0 ], + [ 6, 0, 4, 0, 0, 0, 0, 0, 0 ], + [ 6, 0, 0, 0, 0, 0, 0, 0, 12 ], + [ 11, 5, 9, 0, 12, 5, 5, 5, 10 ] + ] }, { "x": 1, "y": 0, "tiles": [ - [ 6, 3, 1, 1, 1, 2, 0, 3, 8], - [ 6, 0, 0, 0, 0, 0, 0, 0, 3], - [ 0, 0, 0, 0, 1, 0, 0, 0, 0], - [ 6, 0, 0, 0, 0, 0, 0, 0, 12], - [ 10, 9, 0, 12, 5, 5, 5, 5, 11], - [ -1, 6, 0, 3, 1, 1, 1, 1, 1] - ] + [ 6, 3, 1, 1, 1, 1, 1, 2, 8 ], + [ 2, 0, 0, 0, 0, 0, 0, 0, 8 ], + [ 0, 0, 0, 0, 0, 0, 0, 0, 8 ], + [ 0, 0, 0, 3, 1, 1, 1, 1, 1 ], + [ 9, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 11, 5, 5, 5, 5, 5, 5, 5, 5 ] + ] + }, + { + "x": 2, + "y": 0, + "tiles": [ + [ -1, -1, -1, -1, -1, 6, 3, 1, 1 ], + [ 6, 3, 1, 2, 8, 6, 0, 0, 0 ], + [ 6, 0, 0, 0, 3, 2, 0, 4, 0 ], + [ 2, 0, 13, 0, 0, 0, 0, 0, 0 ], + [ 0, 0, 17, 0, 12, 9, 0, 0, 0 ], + [ 5, 5, 18, 5, 10, 11, 5, 5, 5 ] + ] + }, + { + "x": 3, + "y": 0, + "tiles": [ + [1,1,1,1,1,1,1,2,8], + [0,0,0,0,0,0,0,0,8], + [0,0,4,0,0,0,4,0,8], + [0,0,0,0,0,0,0,0,8], + [0,0,0,0,0,0,0,0,8], + [5,5,5,5,5,5,5,5,10] + ] }, { "x": 0, "y": 1, "tiles": [ - [ 6, 3, 0, 1, 1, 2, 0, 3, 8], - [ 6, 0, 0, 0, 0, 0, 0, 0, 3], - [ 0, 0, 0, 0, 1, 0, 0, 0, 0], - [ 6, 0, 0, 0, 0, 0, 0, 0, 12], - [ 10, 9, 0, 12, 5, 5, 5, 5, 11], - [ -1, 6, 0, 3, 1, 1, 1, 1, 1] + [ -1, -1, 6, 0, 3, 2, 8, -1, -1 ], + [ -1, -1, 6, 0, 0, 0, 8, -1, -1 ], + [ -1, -1, 6, 0, 13, 0, 8, -1, -1 ], + [ -1, -1, 6, 0, 17, 0, 3, 1, 1 ], + [ -1, -1, 6, 0, 17, 0, 0, 0, 0 ], + [ -1, -1, 6, 0, 8, 5, 5, 5, 5 ] + ] + }, + { + "x": 1, + "y": 1, + "tiles": [ + [ 6, 3, 1, 2, -1, 3, 1, 2, 8 ], + [ 6, 0, 0, 0, 17, 0, 0, 0, 8 ], + [ 6, 0, 0, 0, 17, 0, 0, 0, 8 ], + [ 1, 2, 0, 3, 1, 2, 0, 3, 1 ], + [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 5, 5, 5, 5, 5, 5, 5, 5, 5 ] + ] + }, + { + "x": 2, + "y": 1, + "tiles": [ + [ 6, 3, 1, 2, -1, 3, 1, 2, 8 ], + [ 6, 0, 0, 0, 17, 0, 0, 0, 8 ], + [ 6, 0, 0, 0, 17, 0, 0, 0, 8 ], + [ 1, 2, 0, 3, 1, 2, 0, 3, 1 ], + [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 5, 5, 5, 5, 5, 5, 5, 5, 5 ] + ] + }, + { + "x": 3, + "y": 1, + "tiles": [ + [-1,6,3,1,1,1,1,2,8], + [-1,6,0,0,0,0,0,0,8], + [-1,6,0,13,3,1,2,0,8], + [1,2,0,17,0,0,0,0,8], + [0,0,0,17,0,12,5,5,10], + [5,5,5,6,0,8,-1,-1,-1] + ] + }, + { + "x": 0, + "y": 2, + "tiles": [ + [-1,6,4,0,3,1,1,1,1], + [-1,6,0,0,0,0,0,0,0], + [-1,6,0,13,0,13,0,12,5], + [-1,6,0,4,0,4,0,8,-1], + [-1,6,0,0,0,0,0,8,-1], + [-1,6,0,12,5,9,0,8,-1] + ] + }, + { + "x": 1, + "y": 2, + "tiles": [ + [1,1,1,1,1,1,1,1,1], + [0,0,0,0,0,0,0,0,0], + [9,0,4,13,0,4,13,3,1], + [6,0,0,17,0,0,17,0,0], + [6,0,0,17,0,0,17,0,0], + [11,5,5,18,5,5,18,5,5] + ] + }, + { + "x": 2, + "y": 2, + "tiles": [ + [1,1,1,1,1,1,1,1,1], + [0,0,0,0,0,0,0,0,0], + [0,4,13,0,4,13,0,4,12], + [0,0,17,0,0,17,0,0,8], + [0,0,17,0,0,17,0,0,8], + [5,5,18,5,5,18,5,5,10] + ] + }, + { + "x": 3, + "y": 2, + "tiles": [ + [1,2,17,4,0,3,1,2,8], + [0,0,17,0,0,0,0,0,8], + [9,0,17,0,0,0,0,0,8], + [6,0,17,0,0,0,0,0,8], + [6,0,17,0,0,0,0,0,8], + [6,0,8,5,5,9,0,12,10] + ] + }, + { + "x": 0, + "y": 3, + "tiles": [ + [6,4,0,4,17,4,0,3,1], + [6,0,0,0,17,0,0,0,0], + [6,0,0,0,17,0,0,0,0], + [6,0,0,0,17,0,0,0,0], + [6,0,0,0,17,0,0,0,0], + [11,5,5,5,18,5,5,5,5] + ] + }, + { + "x": 1, + "y": 3, + "tiles": [ + [1,1,1,2,-1,-1,-1,-1,-1], + [0,0,0,0,3,1,2,8,-1], + [0,0,0,0,0,0,0,8,-1], + [0,0,0,0,0,0,0,8,-1], + [0,0,0,0,13,0,0,8,-1], + [5,5,5,5,6,0,0,8,-1] + ] + }, + { + "x": 2, + "y": 3, + "tiles": [ + [6,3,2,17,3,1,1,2,8], + [6,0,0,17,0,0,0,0,8], + [6,0,0,17,0,0,0,0,8], + [6,0,3,2,0,3,1,1,1], + [6,0,0,0,0,0,0,0,0], + [11,5,5,5,5,5,5,5,5] + ] + }, + { + "x": 3, + "y": 3, + "tiles": [ + [6,0,17,3,1,2,0,4,8], + [6,0,17,0,0,0,0,0,8], + [6,0,17,0,0,0,0,0,8], + [2,0,17,0,0,0,0,0,8], + [0,0,17,0,0,0,0,0,8], + [5,5,18,5,5,5,5,5,10] ] } ] \ No newline at end of file diff --git a/src/assets/map.xlsx b/src/assets/map.xlsx new file mode 100644 index 0000000..796fc9b Binary files /dev/null and b/src/assets/map.xlsx differ diff --git a/src/assets/object.mp3 b/src/assets/object.mp3 new file mode 100644 index 0000000..82df8a5 Binary files /dev/null and b/src/assets/object.mp3 differ diff --git a/src/assets/sprites.json b/src/assets/sprites.json index eac9825..c0d3fb6 100644 --- a/src/assets/sprites.json +++ b/src/assets/sprites.json @@ -128,6 +128,14 @@ "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "sourceSize": {"w":16,"h":16} }, + "tile_18": + { + "frame": {"x":144,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} + }, "p1": { @@ -293,6 +301,15 @@ "sourceSize": {"w":16,"h":16} }, + "uwu": + { + "frame": {"x":0,"y":52,"w":17,"h":12}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":17,"h":12}, + "sourceSize": {"w":17,"h":12} + }, + "text_score": { "frame": {"x":64,"y":128,"w":30,"h":7}, @@ -397,6 +414,14 @@ "spriteSourceSize": {"x":0,"y":0,"w":8,"h":9}, "sourceSize": {"w":8,"h":9} }, + "splash": + { + "frame": {"x":48,"y":48,"w":48,"h":15}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":15}, + "sourceSize": {"w":48,"h":15} + }, "text_marta": { diff --git a/src/assets/sprites.png b/src/assets/sprites.png index 2086918..60d3c56 100644 Binary files a/src/assets/sprites.png and b/src/assets/sprites.png differ diff --git a/src/assets/sprites.xcf b/src/assets/sprites.xcf index b962b0e..0b9c37e 100644 Binary files a/src/assets/sprites.xcf and b/src/assets/sprites.xcf differ diff --git a/src/assets/theme.mp3 b/src/assets/theme.mp3 new file mode 100644 index 0000000..656e2c5 Binary files /dev/null and b/src/assets/theme.mp3 differ diff --git a/src/assets/uwu.mp3 b/src/assets/uwu.mp3 new file mode 100644 index 0000000..5debb72 Binary files /dev/null and b/src/assets/uwu.mp3 differ diff --git a/src/game/Camera.ts b/src/game/Camera.ts index dc7b4a8..293d40b 100644 --- a/src/game/Camera.ts +++ b/src/game/Camera.ts @@ -22,6 +22,8 @@ export class Camera { canvas.stage().position.copyFrom(position); canvas.uiLayout.position.copyFrom(canvasPosition); + canvas.insertCoinInterface.position.copyFrom(canvasPosition); + canvas.gameOverInterface.position.copyFrom(canvasPosition); } } \ No newline at end of file diff --git a/src/game/Canvas.ts b/src/game/Canvas.ts index 7d25975..b9cdf79 100644 --- a/src/game/Canvas.ts +++ b/src/game/Canvas.ts @@ -1,5 +1,6 @@ import * as PIXI from 'pixi.js'; +import PIXISound from 'pixi-sound'; import * as Stats from "stats.js"; import {TextureLoader} from "./TextureLoader"; import {CanvasEvents} from "./types/CanvasEvents"; @@ -7,6 +8,8 @@ import {PlayGroundLayout} from "./layouts/PlayGroundLayout"; import {UILayout} from "./layouts/UILayout"; import {GlitchFilter} from '@pixi/filter-glitch'; import {Camera} from "./Camera"; +import {InsertCoinInterface} from "./layouts/interfaces/InsertCoinInterface"; +import {GameOverInterface} from "./layouts/interfaces/GameOverInterface"; export class Canvas extends PIXI.utils.EventEmitter { @@ -27,19 +30,22 @@ export class Canvas extends PIXI.utils.EventEmitter { private readonly statsList: Array; - // private readonly insertCoinScreen: InsertCoinScreen; + public readonly insertCoinInterface: InsertCoinInterface; public readonly uiLayout: UILayout; public readonly playGroundLayout: PlayGroundLayout; + public readonly gameOverInterface: GameOverInterface; private addedDelta4: number = 0; private addedDelta8: number = 0; + public soundTheme: any; + constructor() { super(); this.app = new PIXI.Application({ width: Canvas.SIZE.w * Canvas.SCREEN_SCALE.x, height: Canvas.SIZE.h * Canvas.SCREEN_SCALE.y, - backgroundColor: 0x000000, + backgroundColor: 0xFFFFFF, antialias: true, resolution: 1, autoDensity: true @@ -65,24 +71,62 @@ export class Canvas extends PIXI.utils.EventEmitter { this.statsList = new Array(); this.uiLayout = new UILayout(); - // this.insertCoinScreen = new InsertCoinScreen(); + this.insertCoinInterface = new InsertCoinInterface(); this.playGroundLayout = new PlayGroundLayout(); + this.gameOverInterface = new GameOverInterface(); + this.loadSplash(); + } + + private loadSplash = async () => { + this.app.ticker.add(this.loop); + + await this.textures.load(); - this.load(); + // this.load(); + const splash = new PIXI.Sprite(this.textures.getTexture('splash')); + splash.alpha = 0; + splash.position.set( + Math.trunc(Canvas.SCALED_SIZE.w / 2 - splash.width / 2), + Math.trunc(Canvas.SCALED_SIZE.h / 2 - splash.height / 2) + ) + let pos = 0; + const loop8 = () => { + switch (pos) { + case 0: + splash.alpha += 0.125; + if(splash.alpha > 3) + pos = 1; + break; + case 1: + splash.alpha -= 0.25; + if(splash.alpha < -3) + pos = 2; + break; + case 2: + this.removeListener('loop8', loop8); + this.renderer().backgroundColor = 0x000000; + this.load(); + break; + } + } + this.on('loop8', loop8); + this.stage().addChild(splash); } private load = async () => { - await this.textures.load(); + this.soundTheme = PIXISound.Sound.from(require('../assets/theme.mp3').default); + this.soundTheme.loop = true; + this.soundTheme.volume = 0.125; + this.soundTheme.play(); - this.loadStats(); - this.app.ticker.add(this.loop); + // this.loadStats(); this.uiLayout.load(); - this.playGroundLayout.load(); - this.stage().addChild( - this.playGroundLayout, - this.uiLayout - ); + this.playGroundLayout.firstLoad(); + this.insertCoinInterface.load(); + this.gameOverInterface.load(); + + this.stage().addChild(this.playGroundLayout, this.gameOverInterface); } private updateFilter = () => { diff --git a/src/game/layouts/PlayGroundLayout.ts b/src/game/layouts/PlayGroundLayout.ts index 7990c94..d7d2a0f 100644 --- a/src/game/layouts/PlayGroundLayout.ts +++ b/src/game/layouts/PlayGroundLayout.ts @@ -28,6 +28,8 @@ export class PlayGroundLayout extends PIXI.Container { private objectEntityList: Array; private zombieList: Array; + private firstTime: boolean; + constructor() { super(); this.map = require('../../assets/map.json'); @@ -35,23 +37,20 @@ export class PlayGroundLayout extends PIXI.Container { this.currentRoomPosition = new PIXI.Point(0, 0); this.objectEntityList = new Array(); this.zombieList = new Array(); + this.firstTime = true; } - public load = () => { - this.loadMap(); - - this.player1 = new Player('solo'); - this.player1.addPosition(20, 20, true); - - const cake = new CakeEntity(); - cake.setPosition(new PIXI.Point(30, 40)); - this.addObjectEntity(cake); - - this.addChild(this.player1); - + public firstLoad = () => { + this.requestedAddedPosition = this.getRandomRoom(); Game.instance.canvas.on("loop", this.loop); } + public load = () => { + this.firstTime = false; + this.requestedAddedPosition = this.getRandomRoom(); + Game.instance.canvas.uiLayout.show() + } + public addObjectEntity = (object: ObjectEntity) => { this.addChild(object); this.objectEntityList.push(object); @@ -71,7 +70,6 @@ export class PlayGroundLayout extends PIXI.Container { } public destroyAllZombiesAndPerks = () => { - console.log('zombies and perks dead') this.removeChild(...this.objectEntityList, ...this.zombieList); this.objectEntityList = []; this.zombieList = []; @@ -83,8 +81,8 @@ export class PlayGroundLayout extends PIXI.Container { let zombiefication = players.length === 0 ? 1 : players.map(p => p.getZombiefication()).reduce((c, z) => c + z) / players.length; // zombie - const zombiesNumber = GetRandomNumber(Math.trunc(zombiefication / 10), Math.trunc(zombiefication / 3)); - for (let i = 0; i < zombiesNumber; i++) { + const zombiesNumber = GetRandomNumber(Math.trunc(zombiefication / 7), Math.trunc(zombiefication / 3)); + for (let i = 0; i < (!this.firstTime ? zombiesNumber : 5); i++) { const zombie = new Zombie(Utils.GetRandomNumber(0, 3) === 1); const randomSpot = this.getRandomFreeSpot(); zombie.addPosition(randomSpot.x,randomSpot.y, true); @@ -92,33 +90,33 @@ export class PlayGroundLayout extends PIXI.Container { } // blood bags - const bloodBagNumber = GetRandomNumber(players.length + 1, 2 * players.length + 1); + const bloodBagNumber = GetRandomNumber(0, 2 * players.length + 1); const bloodMin = GetRandomNumber( Math.trunc((100 - zombiefication) / 10), Math.trunc(zombiefication / 5) ); - for (let i = 0; i < bloodBagNumber; i++) { + for (let i = 0; i < (!this.firstTime ? bloodBagNumber : 2); i++) { const bloodBag = new BloodBagEntity(bloodMin, 50); bloodBag.setPosition(this.getRandomFreeSpot()); this.addObjectEntity(bloodBag); } // cakes - if(GetRandomNumber(0, 100) === 4) { + if(GetRandomNumber(0, 100) === 4 || this.firstTime) { const cake = new CakeEntity(); cake.setPosition(this.getRandomFreeSpot()); this.addObjectEntity(cake); } // toilet paper - for (let i = 0; i < GetRandomNumber(0, 3); i++) { + for (let i = 0; i < (!this.firstTime ? GetRandomNumber(0, 3) : 10 ); i++) { const toiletPaper = new ToiletPaperEntity(); toiletPaper.setPosition(this.getRandomFreeSpot()); this.addObjectEntity(toiletPaper); } // voidpixel skull - if(GetRandomNumber(0, 50) === 4) { + if(GetRandomNumber(0, 50) === 4 || this.firstTime) { const cake = new SkullEntity(); cake.setPosition(this.getRandomFreeSpot()); this.addObjectEntity(cake); @@ -126,6 +124,16 @@ export class PlayGroundLayout extends PIXI.Container { } + private getRandomRoom = () => { + const room = new PIXI.Point( + GetRandomNumber(0, this.map.map(r => r.x).reduce((a, x) => a = a > x ? a : x)), + GetRandomNumber(0, this.map.map(r => r.y).reduce((a, y) => a = a > y ? a : y)) + ); + return this.firstTime + ? room + : new PIXI.Point(room.x - this.currentRoomPosition.x, room.y - this.currentRoomPosition.y) + } + private getRandomFreeSpot = () => { const initialPosition = this.getCurrentRoomPositionCorrected(); const currentRoomBounds = this.getCurrentRoomBounds(); @@ -157,30 +165,55 @@ export class PlayGroundLayout extends PIXI.Container { Game.instance.canvas.uiLayout.scoreInterface.removeSecondPlayerText(); } + private gameOver = () => { + this.player1 = null; + this.player2 = null; + + Game.instance.canvas.gameOverInterface.show(); + } + public loop = () => { - const requestChangeRoomPlayer1 = this.player1.getRequestChangeRoom(); - switch (this.player1.type) { - case "solo": - if(requestChangeRoomPlayer1) - this.loadRoom(requestChangeRoomPlayer1); - break; - case "p1": - const requestChangeRoomPlayer2 = this.player2.getRequestChangeRoom(); - if(this.player1.isDead() && this.player2.isDead()) - this.requestedAddedPosition = null; - else if((requestChangeRoomPlayer1 || this.player1.isDead()) && (requestChangeRoomPlayer2 || this.player2.isDead())) - this.loadRoom(this.player1.isDead() ? requestChangeRoomPlayer2 : requestChangeRoomPlayer1); - break; - } - if(this.requestedAddedPosition) { - this.currentRoomPosition = new PIXI.Point( - this.requestedAddedPosition.x + this.currentRoomPosition.x, - this.requestedAddedPosition.y + this.currentRoomPosition.y - ); - this.loadMap(); - Game.instance.canvas.camera.move(this.currentRoomPosition); - this.requestedAddedPosition = null; + if(this.player1 && this.arePlayersDead() && !this.firstTime) + return this.gameOver(); + + if(this.player1) { + const requestChangeRoomPlayer1 = this.player1.getRequestChangeRoom(); + switch (this.player1.type) { + case "solo": + if(requestChangeRoomPlayer1) + this.loadRoom(requestChangeRoomPlayer1); + break; + case "p1": + const requestChangeRoomPlayer2 = this.player2.getRequestChangeRoom(); + if(this.player1.isDead() && this.player2.isDead()) + this.requestedAddedPosition = null; + else if((requestChangeRoomPlayer1 || this.player1.isDead()) && (requestChangeRoomPlayer2 || this.player2.isDead())) + this.loadRoom(this.player1.isDead() ? requestChangeRoomPlayer2 : requestChangeRoomPlayer1); + break; + } } + if(!this.requestedAddedPosition) return; + + this.currentRoomPosition = new PIXI.Point( + this.requestedAddedPosition.x + this.currentRoomPosition.x, + this.requestedAddedPosition.y + this.currentRoomPosition.y + ); + this.loadMap(); + Game.instance.canvas.camera.move(this.currentRoomPosition); + this.requestedAddedPosition = null; + + if(this.player1 || this.firstTime) return; + + const randomPlayerPos = this.getRandomFreeSpot(); + + this.player1 = new Player('solo'); + this.player1.addPosition(randomPlayerPos.x, randomPlayerPos.y, true); + + const cake = new CakeEntity(); + cake.setPosition(this.getRandomFreeSpot()); + this.addObjectEntity(cake); + + this.addChild(this.player1); } private loadMap = () => { diff --git a/src/game/layouts/UILayout.ts b/src/game/layouts/UILayout.ts index e9de1c7..6bd0851 100644 --- a/src/game/layouts/UILayout.ts +++ b/src/game/layouts/UILayout.ts @@ -1,6 +1,7 @@ import * as PIXI from 'pixi.js'; import {ScoreInterface} from "./interfaces/ScoreInterface"; +import {Game} from "../Game"; export class UILayout extends PIXI.Container { @@ -16,4 +17,7 @@ export class UILayout extends PIXI.Container { this.addChild(this.scoreInterface); } + public hide = () => Game.instance.canvas.stage().removeChild(this); + public show = () => Game.instance.canvas.stage().addChild(this); + } \ No newline at end of file diff --git a/src/game/layouts/interfaces/GameOverInterface.ts b/src/game/layouts/interfaces/GameOverInterface.ts new file mode 100644 index 0000000..1870d47 --- /dev/null +++ b/src/game/layouts/interfaces/GameOverInterface.ts @@ -0,0 +1,43 @@ +import * as PIXI from "pixi.js"; +import {Game} from "../../Game"; +import {Canvas} from "../../Canvas"; +import PIXISound from 'pixi-sound'; + +export class GameOverInterface extends PIXI.Container { + + private gameOver: PIXI.Sprite; + + constructor() { + super(); + this.zIndex = Number.MAX_SAFE_INTEGER; + } + + public load = () => { + this.gameOver = new PIXI.Sprite(Game.instance.canvas.textures.getTexture('text_gameover')); + this.gameOver.position.set( + Math.trunc(Canvas.SCALED_SIZE.w / 2 - this.gameOver.width / 2), + Math.trunc(Canvas.SCALED_SIZE.h / 2 - this.gameOver.height / 2) + ) + } + + show() { + this.addChild(this.gameOver); + + Game.instance.canvas.soundTheme.pause(); + Game.instance.canvas.soundTheme.speed = 1; + + const gameOverSound = PIXISound.Sound.from(require('../../../assets/gameover.mp3').default); + gameOverSound.volume = 0.125; + gameOverSound.play(); + + setTimeout(() => { + this.removeChild(this.gameOver); + Game.instance.canvas.soundTheme.resume(); + Game.instance.canvas.insertCoinInterface.show(); + Game.instance.canvas.uiLayout.hide(); + Game.instance.canvas.uiLayout.scoreInterface.reset(); + }, 5000); + }; + + +} \ No newline at end of file diff --git a/src/game/layouts/interfaces/InsertCoinInterface.ts b/src/game/layouts/interfaces/InsertCoinInterface.ts index 4d34fc7..f75b629 100644 --- a/src/game/layouts/interfaces/InsertCoinInterface.ts +++ b/src/game/layouts/interfaces/InsertCoinInterface.ts @@ -2,6 +2,7 @@ import * as PIXI from 'pixi.js'; import {Canvas} from "../../Canvas"; import {Game} from "../../Game"; +import {Key} from "ts-key-enum"; export class InsertCoinInterface extends PIXI.Container { @@ -18,6 +19,7 @@ export class InsertCoinInterface extends PIXI.Container { this.logo = new PIXI.Sprite(); this.insertCoin = new PIXI.Sprite(); this.addChild(this.logo, this.insertCoin); + this.zIndex = Number.MAX_SAFE_INTEGER - 1; } public load = () => { @@ -33,8 +35,21 @@ export class InsertCoinInterface extends PIXI.Container { this.insertCoin.position.set(Canvas.SCALED_SIZE.w / 2, Canvas.SCALED_SIZE.h / 2 + 30) this.addChild(this.logo, this.insertCoin); + Game.instance.keyboard.on(this.onKeyboard); canvas.on('loop8', this.loop8); + Game.instance.canvas.stage().addChild(this); + } + + public show = () => { + Game.instance.keyboard.on(this.onKeyboard); + Game.instance.canvas.stage().addChild(this); + } + + public unload = () => { + Game.instance.canvas.playGroundLayout.destroyAllZombiesAndPerks(); + Game.instance.keyboard.removeListener(this.onKeyboard); + Game.instance.canvas.stage().removeChild(this); } private loop8 = (delta: number) => { @@ -65,5 +80,9 @@ export class InsertCoinInterface extends PIXI.Container { break; } } + private onKeyboard = (data: {code: string, key: Key | string, isDown: boolean}) => { + Game.instance.canvas.playGroundLayout.load(); + this.unload(); + } } \ No newline at end of file diff --git a/src/game/layouts/interfaces/ScoreInterface.ts b/src/game/layouts/interfaces/ScoreInterface.ts index 6837664..ff8c8c1 100644 --- a/src/game/layouts/interfaces/ScoreInterface.ts +++ b/src/game/layouts/interfaces/ScoreInterface.ts @@ -92,6 +92,21 @@ export class ScoreInterface extends PIXI.Container { Game.instance.canvas.on('loop4', this.onLoop4); } + public reset = () => { + this.addChild(this.pressPText, this.p2Text); + this.pressPTime = '8'; + this.pressPAlpha = 'show'; + this.pressPIterations = 0; + this.addChild(this.p2Text, this.pressPText); + this.score.reset(); + this.rightHeart.gotoAndStop(0); + this.leftHeart.gotoAndStop(0); + this.addChild(this.leftZombiefication); + this.removeChild(this.rightHeart, this.rightZombiefication); + this.setZombiefication('p1', 0); + this.setZombiefication('p2', 0); + } + private onLoop4 = () => { if(this.pressPTime === '4') this.p2TextLoop(); diff --git a/src/game/layouts/interfaces/ScoreText.ts b/src/game/layouts/interfaces/ScoreText.ts index 26c9a55..ed0603f 100644 --- a/src/game/layouts/interfaces/ScoreText.ts +++ b/src/game/layouts/interfaces/ScoreText.ts @@ -12,6 +12,8 @@ export class ScoreText extends PIXI.Container { this.addScore(0); } + public reset = () => this.addScore(- this.actualScore); + public addScore = (amount: number) => { this.actualScore += amount diff --git a/src/game/layouts/playground/entities/ObjectEntity.ts b/src/game/layouts/playground/entities/ObjectEntity.ts index 0623454..5fb93e8 100644 --- a/src/game/layouts/playground/entities/ObjectEntity.ts +++ b/src/game/layouts/playground/entities/ObjectEntity.ts @@ -1,4 +1,5 @@ import * as PIXI from "pixi.js"; +import PIXISound from 'pixi-sound'; import {Game} from "../../../Game"; import {Utils} from "../../../Utils"; import GetRandomString = Utils.GetRandomString; @@ -20,11 +21,15 @@ export class ObjectEntity extends PIXI.Sprite { point.x -= Math.trunc(this.width / 2); point.y -= this.height; this.position.copyFrom(point); - this.zIndex += point.y + 2; + this.zIndex += point.y + this.height; } public consume (player: Player) { - Game.instance.canvas.playGroundLayout.destroyObjectEntity(this) + Game.instance.canvas.playGroundLayout.destroyObjectEntity(this); + + const uwuSound = PIXISound.Sound.from(require('../../../../assets/object.mp3').default); + uwuSound.volume = 0.25; + uwuSound.play(); }; } \ No newline at end of file diff --git a/src/game/layouts/playground/entities/Player.ts b/src/game/layouts/playground/entities/Player.ts index 1d4083d..acfb22a 100644 --- a/src/game/layouts/playground/entities/Player.ts +++ b/src/game/layouts/playground/entities/Player.ts @@ -21,6 +21,7 @@ export class Player extends Entity { private requestChangeRoom: PIXI.Point; private _isDead: boolean; + private bitten: number; constructor(type: PlayerType = 'solo') { super( type === 'solo' || type === 'p1' ? 'marta' : 'pablo'); @@ -32,6 +33,7 @@ export class Player extends Entity { this.animatedSprite.animationSpeed = 0.125; this.zombiefication = 0; + this.bitten = 0; this.on('added', this.onAdded); this.on('removed', this.onRemoved); @@ -46,16 +48,18 @@ export class Player extends Entity { private onAdded = () => { Game.instance.canvas.on('loop4', this.onLoop4); + Game.instance.canvas.on('loop8', this.onLoop8); Game.instance.keyboard.on(this.onKeyboard); this.on('position_changed', this.onPositionChange); this.zombieficationInterval = setInterval(() => { const zombiefication = Math.random() * 2 this.addZombiefication(zombiefication); - this.addBlood(); if(this.getZombiefication() > 80) Game.instance.canvas.uiLayout.scoreInterface.score.addScore(Math.trunc(zombiefication * 100)); }, 500); + + } private onPositionChange = (position: PIXI.Point) => { @@ -92,6 +96,7 @@ export class Player extends Entity { this._isDead = true; clearInterval(this.zombieficationInterval); Game.instance.canvas.removeListener('loop4', this.onLoop4); + Game.instance.canvas.removeListener('loop8', this.onLoop8); Game.instance.keyboard.removeListener(this.onKeyboard); this.removeListener('position_changed', this.onPositionChange); @@ -102,11 +107,24 @@ export class Player extends Entity { Game.instance.canvas.playGroundLayout.addZombie(zombie) } + public bit = () => { + this.addZombiefication(GetRandomNumber(1, 2)); + if(this.bitten > 8) return; + this.bitten++; + } + public addZombiefication = (amount: number) => { + // this.zombiefication = 80; + // Game.instance.canvas.uiLayout.scoreInterface.setZombiefication(this.type, this.zombiefication); + // return; + if(0 > amount && this.bitten > 0) + this.bitten--; this.zombiefication += amount; if(this.zombiefication < 0) this.zombiefication = 0; Game.instance.canvas.uiLayout.scoreInterface.setZombiefication(this.type, this.zombiefication); + + Game.instance.canvas.soundTheme.speed = this.zombiefication > 80 ? 1.3 : 1; } public getZombiefication = () => this.zombiefication; @@ -132,6 +150,11 @@ export class Player extends Entity { this.addPosition(-delta, 0); } + private onLoop8 = () => { + if(GetRandomNumber(0, 10 - this.bitten) !== 0) return; + this.addBlood(); + } + public isDead = () => this._isDead; private isDown = (direction: PlayerDirection) => this.keyDownArray.some(k => k === direction); diff --git a/src/game/layouts/playground/entities/Zombie.ts b/src/game/layouts/playground/entities/Zombie.ts index 8563e08..b5e6663 100644 --- a/src/game/layouts/playground/entities/Zombie.ts +++ b/src/game/layouts/playground/entities/Zombie.ts @@ -1,3 +1,6 @@ + +import * as PIXI from 'pixi.js'; +import PIXISound from 'pixi-sound'; import {Entity} from "./Entity"; import {Game} from "../../../Game"; import {PathFinding} from "../../../PathFinding"; @@ -10,9 +13,11 @@ export class Zombie extends Entity { private findInterval: any; private goto: Array; - private difficulty: '8' |'4'; + private readonly difficulty: '8' |'4'; private currentDirection: PlayerDirection; + + private readonly uwu: PIXI.Sprite; constructor(hard: boolean = false) { super('zombie'); @@ -20,6 +25,11 @@ export class Zombie extends Entity { this.difficulty = hard ? '4' : '8'; this.goto = []; + this.uwu = new PIXI.Sprite(Game.instance.canvas.textures.getTexture('uwu')); + this.uwu.position.set(3, - Math.trunc(this.animatedSprite.height + (this.uwu.height / 1.6))); + this.uwu.alpha = 0; + this.addChild(this.uwu) + this.animatedSprite.onFrameChange = this._onFrameChange; this.animatedSprite.animationSpeed = 0.125; @@ -30,7 +40,8 @@ export class Zombie extends Entity { } private onAdded = () => { - Game.instance.canvas.on(`loop${this.difficulty}`, this.onLoop4.bind(this)); + Game.instance.canvas.on(`loop${this.difficulty}`, this.onLoop.bind(this)); + Game.instance.canvas.on(`loop8`, this.onLoop8Fixed.bind(this)); this.findInterval = setInterval(() => { const playGround = Game.instance.canvas.playGroundLayout; if(playGround.arePlayersDead()) return; @@ -45,10 +56,24 @@ export class Zombie extends Entity { private onRemoved = () => { clearInterval(this.findInterval); - Game.instance.canvas.removeListener(`loop${this.difficulty}`, this.onLoop4); + Game.instance.canvas.removeListener(`loop${this.difficulty}`, this.onLoop); + Game.instance.canvas.removeListener(`loop8`, this.onLoop8Fixed.bind(this)); + } + + private showUWU = () => { + this.uwu.alpha = 1; + + const uwuSound = PIXISound.Sound.from(require('../../../../assets/uwu.mp3').default); + uwuSound.volume = 0.125; + uwuSound.play(); + }; + + private onLoop8Fixed = () => { + if(0 >= this.uwu.alpha) return; + this.uwu.alpha -= 0.025; } - private onLoop4 = (delta) => { + private onLoop = (delta) => { if(this.goto.length === 0) { switch (this.currentDirection) { case PlayerDirection.DOWN: @@ -64,8 +89,10 @@ export class Zombie extends Entity { } const collidingPlayers = Game.instance.canvas.playGroundLayout .getCollidingPlayers(this.position); - if(collidingPlayers) - collidingPlayers.addZombiefication(GetRandomNumber(1, 2)); + if(collidingPlayers) { + collidingPlayers.bit(); + this.showUWU(); + } const targetPosition = this.goto[0]; const goX = this.position.x - targetPosition.x; diff --git a/src/index.ejs b/src/index.ejs index ea712aa..aaa95f9 100644 --- a/src/index.ejs +++ b/src/index.ejs @@ -7,10 +7,10 @@