import Matter = require("matter-js");
import { byId, createAppEvent, htmlHeader } from "../../../libs/class/system";
import SpriteTextureComponent from "../../../libs/class/visual-methods/sprite-animation";
import { DEFAULT_GAMEPLAY_ROLES, DEFAULT_PLAYER_DATA } from "../../../libs/defaults";
import { IGamePlayModel, IPoint, ISelectedPlayer } from "../../../libs/interface/global";
import Starter from "../../../libs/starter";
import { worldElement } from "../../../libs/types/global";
import Level1 from "./packs/level1";
import Level2 from "./packs/level2";
import Level3 from "./packs/level3";
import Level4 from "./packs/level4";
import Level5 from "./packs/level5";
import Level6 from "./packs/level6";
// Prepare audios
require("../audios/map-themes/mishief-stroll.mp4");
/**
* @author Nikola Lukic
* @class Platformer Single player solution.
* @param Starter
* @description This is game logic part
* we stil use class based methodology.
* About resource we use requir
*/
class Platformer implements IGamePlayModel {
public gameName: string = "platformer";
public version: number = 0.3;
public playerCategory = 0x0002;
public staticCategory = 0x0004;
public starter: Starter;
public grounds: worldElement[] = [];
public enemys: worldElement[] = [];
public deadLines: worldElement[] = [];
public labels: worldElement[] = [];
public v: any;
public player: Matter.Body | any = undefined;
// move to maps 'labels text'
public hudLives: Matter.Body | any = null;
public selectedPlayer: ISelectedPlayer;
private selectPlayerArray: ISelectedPlayer[] = [];
private lives: number = DEFAULT_PLAYER_DATA.INITIAL_LIVES;
private preventDoubleExecution: boolean = false;
private playerStartPositions: IPoint[] = [{x: 120, y: 200}];
private playerDeadPauseInterval: number = 550;
private UIPlayerBoard: HTMLDivElement;
private UIPlayAgainBtn: HTMLDivElement;
private UISoundOptionDom: HTMLDivElement;
private levelMaps: any = {
generatedMap: Level1,
Level1,
Level2,
Level3,
Level4,
Level5,
Level6,
};
constructor(starter: Starter) {
this.starter = starter;
// this.starter.getEngine().enableSleeping = true;
this.initSelectPlayer();
this.addUIPlayerBoard();
this.showPlayerBoardUI();
this.attachUpdateLives();
// this.starter.ioc.get.Sound.audioBox['surfaceLevel'].play();
}
public initSelectPlayer() {
// Create UI for basic select player features.
// Register
/*
this.selectPlayerArray.push({
labelName: "robot",
poster: require("../imgs/players/robot/poster.png"),
resource: [
require("../imgs/players/robot/1.png"),
require("../imgs/players/robot/2.png"),
require("../imgs/players/robot/3.png"),
require("../imgs/players/robot/4.png"),
require("../imgs/players/robot/5.png"),
require("../imgs/players/robot/6.png"),
require("../imgs/players/robot/7.png"),
require("../imgs/players/robot/8.png"),
],
type: "frameByFrame"
});
*/
this.selectPlayerArray.push({
labelName: "nidzica",
poster: require("../imgs/players/nidzica/posterNidzica.png"),
resource: [
require("../imgs/players/nidzica/nidzica-running.png"),
require("../imgs/explosion/explosion.png"),
require("../imgs/players/nidzica/nidzica-idle.png"),
],
type: "sprite",
spriteTile: {run: { byX: 5, byY: 1 }, idle: { byX: 3, byY: 1 }},
spriteTileCurrent: "run",
setCurrentTile(key: string) {
this.spriteTileCurrent = key;
},
});
this.selectPlayerArray.push({
labelName: "smartGirl",
poster: require("../imgs/players/smart-girl/poster.png"),
resource: [
require("../imgs/players/smart-girl/smart-girl.png"),
require("../imgs/explosion/explosion.png"),
require("../imgs/players/smart-girl/smart-girl-idle.png"),
],
type: "sprite",
spriteTile: {run: { byX: 5, byY: 1 }, idle: { byX: 5, byY: 1 }},
spriteTileCurrent: "idle",
setCurrentTile(key: string) {
this.spriteTileCurrent = key;
},
});
}
public createPlayer(addToScene: boolean) {
const sptTexCom = new SpriteTextureComponent(
"playerImage",
(this.selectedPlayer.resource as any),
( { byX: 5, byY: 1 } as any),
);
this.preventDoubleExecution = false;
const playerRadius = 50;
this.player = Matter.Bodies.circle(
this.playerStartPositions[0].x,
this.playerStartPositions[0].y,
playerRadius, {
label: "player",
density: 0.0005,
friction: 0.01,
frictionAir: 0.06,
restitution: 0.3,
ground: true,
jumpCD: 0,
jumpAmp: 0.35,
portal: -1,
collisionFilter: {
category: this.playerCategory,
} as any,
render: {
visualComponent: sptTexCom,
fillStyle: "blue",
sprite: {
xScale: 1,
yScale: 1,
},
} as any,
} as Matter.IBodyDefinition);
this.player.collisionFilter.group = -1;
if (this.player.render.visualComponent instanceof SpriteTextureComponent) {
this.player.render.visualComponent.assets.SeqFrame.setNewSeqFrameRegimeType("CONST");
this.player.render.visualComponent.keepAspectRatio = true;
} else {
this.player.render.visualComponent.keepAspectRatio = true;
// hardcode for now
this.player.render.sprite.xScale = 0.2;
this.player.render.sprite.yScale = 0.2;
}
this.player.render.visualComponent.setHorizontalFlip(false);
if (addToScene) {
this.player.id = 2;
this.starter.AddNewBodies(this.player as worldElement);
console.info("Player body created from 'dead'.");
}
}
public playerSpawn(recreatePlayer: boolean) {
if (this.player === null || this.player === undefined) {
this.createPlayer(recreatePlayer);
} else if (this.player.type === "body") {
// empty for now
}
}
public collisionCheck(event, ground: boolean) {
const myInstance = this;
const pairs = event.pairs;
for (let i = 0, j = pairs.length; i !== j; ++i) {
const pair = pairs[i];
if (pair.activeContacts) {
// single player teleport
// collectItemPoint used , this is next type :
// nextLevelItem or teleport
// Destroy world , player create next game play
if (pair.bodyA.label === "player" && pair.bodyB.label.indexOf("Level") !== -1) {
const nextLevelItem = pair.bodyB.label;
myInstance.nextLevel(nextLevelItem);
}
if (pair.bodyA.label === "player" && pair.bodyB.label === "collectItemPoint") {
const collectitem = pair.bodyB;
this.starter.destroyBody(collectitem);
this.starter.ioc.get.Sound.playById('collectItem');
}
if (pair.bodyA.label === "player" && pair.bodyB.label === "crapmunch") {
const collectitem = pair.bodyA;
this.playerDie(collectitem);
} else if (pair.bodyB.label === "player" && pair.bodyA.label === "crapmunch") {
const collectitem = pair.bodyB;
this.playerDie(collectitem);
}
pair.activeContacts.forEach((element) => {
if (element.vertex.body.label === "player" &&
element.vertex.index > 5 && element.vertex.index < 8 &&
this.player !== null) {
(this.player as any).ground = ground;
} else if (element.vertex.body.label === "player") {
if (this.player === null) { return; }
(this.player as any).ground = false;
}
});
}
}
}
public showPlayerBoardUI = () => {
const myInstance = this;
fetch("./templates/ui/single-player-board.html", {
headers: htmlHeader,
}).
then(function (res) {
return res.text();
}).then(function (html) {
myInstance.UIPlayerBoard = byId("UIPlayerBoard") as HTMLDivElement;
myInstance.UIPlayerBoard.innerHTML = html;
myInstance.UIPlayerBoard.style.display = "block";
myInstance.UIPlayAgainBtn = byId("playAgainBtn") as HTMLDivElement;
myInstance.UISoundOptionDom = byId("soundOptionDom") as HTMLDivElement;
/**
* @description In gameplay Enable od disable sounds.
* New aproach `()=>` next migration.
*/
myInstance.UISoundOptionDom.addEventListener("click", function(e) {
if ((e.currentTarget as HTMLElement).innerHTML == "Sound:Off") {
myInstance.starter.ioc.get.Sound.audioBox.bgMusic.pause();
myInstance.starter.ioc.get.Sound.audioBox.noSound = true;
(e.currentTarget as HTMLElement).innerText = "Sound:On";
} else {
myInstance.starter.ioc.get.Sound.audioBox.noSound = false;
myInstance.starter.ioc.get.Sound.playById('bgMusic');
(e.currentTarget as HTMLElement).innerText = "Sound:Off";
}
});
myInstance.UIPlayAgainBtn.addEventListener("click", function () {
// hard
myInstance.destroyGamePlayPlatformer();
(this as any).disabled = true;
byId("UIPlayerLives").innerText = "3";
myInstance.lives = DEFAULT_PLAYER_DATA.INITIAL_LIVES;
const appStartGamePlay = createAppEvent("game-init",
{
mapName: "Level1",
game: myInstance.levelMaps.Level1,
});
(window as any).dispatchEvent(appStartGamePlay);
myInstance.player.render.visualComponent.assets.SeqFrame.setNewValue(0);
myInstance.selectedPlayer.spriteTileCurrent = "run";
myInstance.player.render.visualComponent.setNewShema(myInstance.selectedPlayer);
myInstance.player.render.visualComponent.seqFrameX.setDelay(8);
}, false);
});
// Select Player feature - Load UI
fetch("./templates/ui/select-player.html", {
headers: htmlHeader,
}).
then(function (res) {
return res.text();
}).then(function (html) {
const popup = byId("popup") as HTMLDivElement;
popup.innerHTML = html;
popup.style.display = "block";
myInstance.selectPlayerArray.forEach(function (itemPlayer) {
const local = document.createElement("div");
local.id = "" + itemPlayer.labelName;
local.className = "bounceIn selectPlayerBox";
// local.setAttribute("style", "width:30%;display:inline-block;cursor:pointer;text-align:center;padding: 9px;");
local.innerHTML = " Name:" +
itemPlayer.labelName +
"
";
local.addEventListener("click", function () {
myInstance.selectPlayer(itemPlayer.labelName);
const appStartGamePlay = createAppEvent(
"game-init",
{
mapName: "Level1",
game: myInstance.levelMaps.Level1,
},
);
(window as any).dispatchEvent(appStartGamePlay);
popup.innerHTML = "";
document.body.removeChild(popup);
// Play music in background
myInstance.starter.ioc.get.Sound.createAudio("./audios/sb_indreams.mp3", "bgMusic");
myInstance.starter.ioc.get.Sound.createAudio("./audios/collect-item.mp3", "collectItem");
myInstance.starter.ioc.get.Sound.createAudio("./audios/dead.mp3", "dead");
myInstance.starter.ioc.get.Sound.createAudio("./audios/jump.mp3", "jump");
// Correct bg Music
myInstance.starter.ioc.get.Sound.audioBox.bgMusic.volume = 0.3;
}, false);
byId("listOfPlayers").appendChild(local);
// popup.appendChild(local);
});
});
}
protected selectPlayer(labelName: string = "nidzica") {
this.selectPlayerArray.forEach((element) => {
if (element.labelName === labelName) {
this.selectedPlayer = element;
}
});
}
protected playerDie(collectitem) {
if (!this.preventDoubleExecution) {
const root = this;
this.preventDoubleExecution = true;
// Hard dead
// this.starter.destroyBody(collectitem);
console.info("What is destroyed : ", collectitem);
this.player.render.visualComponent.shema = { byX: 4, byY: 4 };
this.player.render.visualComponent.assets.SeqFrame.setNewValue(1);
this.lives = this.lives - 1;
(this.UIPlayerBoard.getElementsByClassName("UIPlayerLives")[0] as HTMLSpanElement).innerText = this.lives.toString();
if (this.lives === 0 || this.lives < 0) {
this.starter.destroyBody(collectitem);
this.player = null;
if ((byId("playAgainBtn") as HTMLButtonElement)) {
(byId("playAgainBtn") as HTMLButtonElement).disabled = false;
}
this.starter.ioc.get.Sound.playById('dead');
/*
Re born from hard dead
hard dead - body removed from scene
setTimeout(function () {
root.playerSpawn();
}, this.playerDeadPauseInterval);
*/
return;
}
setTimeout(function () {
root.player.render.visualComponent.assets.SeqFrame.setNewValue(0);
root.selectedPlayer.spriteTileCurrent = "run";
// create general method !
root.player.render.visualComponent.setNewShema(root.selectedPlayer);
root.starter.ioc.get.Sound.playById('dead');
setTimeout(function () {
// Soft dead for now
Matter.Body.setPosition(root.player, root.playerStartPositions[0]);
root.playerSpawn(false);
root.preventDoubleExecution = false;
}, this.playerDeadPauseInterval * 10);
}, this.playerDeadPauseInterval);
}
}
protected destroyGamePlayPlatformer() {
this.starter.destroyGamePlay();
this.starter.deattachMatterEvents();
this.grounds = [];
this.enemys = [];
this.deadLines = [];
this.labels = [];
}
private attachUpdateLives = () => {
const root = this;
window.addEventListener("update-lives", function (e) {
root.lives = (e as any).detail.data.lives;
});
}
private addUIPlayerBoard = () => {
this.UIPlayerBoard = document.createElement("div");
this.UIPlayerBoard.id = "UIPlayerBoard";
this.UIPlayerBoard.className = "leftPanelUni";
document.getElementsByTagName("body")[0].appendChild(this.UIPlayerBoard);
}
/**
* @description Jump intro new wourld.
* @param data
* @type Void
*/
private nextLevel(data) {
const root = this;
if (data.indexOf("Level") !== -1) {
const appEndGamePlay = createAppEvent("game-end", { game: "Level1" });
(window as any).dispatchEvent(appEndGamePlay);
// this.player = null;
root.player.render.visualComponent.assets.SeqFrame.setNewValue(0);
root.selectedPlayer.spriteTileCurrent = "run";
root.player.render.visualComponent.setNewShema(root.selectedPlayer);
root.player.render.visualComponent.seqFrameX.setDelay(8);
Matter.Body.setPosition(root.player, root.playerStartPositions[0]);
setTimeout(function () {
const appStartGamePlay = createAppEvent("game-init", {
mapName: data,
game: root.levelMaps[data],
});
(window as any).dispatchEvent(appStartGamePlay);
}, DEFAULT_GAMEPLAY_ROLES.RESPAWN_INTERVAL);
}
}
}
export default Platformer;