Файловый менеджер - Редактировать - /home/jogoso94/public_html/static/img/logo/src.zip
�азад
PK �Zl���1 �1 Utils.jsnu �[��� "use strict"; PrinceJS.Utils = { convertX: function (x) { return Math.floor((x * 320) / 140); }, convertXtoBlockX: function (x) { return Math.floor((x - 7) / 14); }, convertYtoBlockY: function (y) { return Math.floor(y / PrinceJS.BLOCK_HEIGHT); }, convertBlockXtoX: function (block) { return block * 14 + 7; }, convertBlockYtoY: function (block) { return (block + 1) * PrinceJS.BLOCK_HEIGHT - 10; }, delayed: function (fn, millis) { return new Promise((resolve) => { setTimeout(() => { Promise.resolve() .then(() => { return fn && fn(); }) .then((result) => { resolve(result); }); }, millis); }); }, delayedCancelable: function (fn, millis) { let timeout; return { cancel: () => { clearTimeout(timeout); }, promise: new Promise((resolve) => { timeout = setTimeout(() => { Promise.resolve() .then(() => { return fn && fn(); }) .then((result) => { resolve(result); }); }, millis); }) }; }, perform: function (fn, millis) { return new Promise((resolve) => { let result = fn && fn(); setTimeout(() => { resolve(result); }, millis); }); }, flashScreen: function (game, count, color, time) { for (let i = 0; i < count * 2; i++) { PrinceJS.Utils.delayed(() => { game.stage.backgroundColor = i % 2 === 0 ? color : 0x000000; PrinceJS.InterfaceCurrent.flash(game.stage.backgroundColor); }, time * i); } }, flashPattern: function (game, color, pattern) { return pattern.reduce((promise, time) => { return promise.then(() => { PrinceJS.Utils.flashScreen(game, 1, color, time); return PrinceJS.Utils.delayed(undefined, 4 * time); }); }, Promise.resolve()); }, flashRedDamage: function (game) { PrinceJS.Utils.flashPattern(game, PrinceJS.Level.FLASH_RED, [25]); }, flashRedPotion: function (game) { PrinceJS.Utils.flashPattern(game, PrinceJS.Level.FLASH_RED, [50, 25, 25]); }, flashGreenPotion: function (game) { PrinceJS.Utils.flashPattern(game, PrinceJS.Level.FLASH_GREEN, [50, 25, 25]); }, flashYellowSword: function (game) { PrinceJS.Utils.flashPattern(game, PrinceJS.Level.FLASH_YELLOW, [50, 25, 25, 50, 25, 25, 25]); }, flashWhiteShadowMerge: function (game) { PrinceJS.Utils.flashPattern( game, PrinceJS.Level.FLASH_WHITE, [50, 25, 25, 50, 25, 25, 25, 50, 25, 25, 50, 25, 25, 25] ); }, flashWhiteVizierVictory: function (game) { PrinceJS.Utils.flashPattern(game, PrinceJS.Level.FLASH_WHITE, [25, 25, 100, 100, 50, 50, 25, 25, 50]); }, random: function (max) { return Math.floor(Math.random() * Math.floor(max)); }, continueGame: function (game) { return PrinceJS.Utils.pointerPressed(game) || PrinceJS.Utils.gamepadAnyPressed(game); }, gamepadButtonPressedCheck: function (game, buttons, name = "default") { if (this[`_${name}Pressed`]) { return false; } let pressed = false; let pad = game.input.gamepad.pad1; if (pad && pad.connected) { if (!buttons) { buttons = Object.keys(pad._rawPad.buttons).map((button) => parseInt(button)); } for (let button of buttons) { if (pad.justPressed(button)) { pressed = true; } } } if (pressed) { this[`_${name}Pressed`] = true; PrinceJS.Utils.delayed(() => { this[`_${name}Pressed`] = false; }, 500); } return pressed; }, gamepadButtonDownCheck: function (game, buttons) { let pad = game.input.gamepad.pad1; if (pad && pad.connected) { if (!buttons) { buttons = Object.keys(pad._rawPad.buttons).map((button) => parseInt(button)); } for (let button of buttons) { if (pad.isDown(button)) { return true; } } } return false; }, gamepadAxisCheck: function (game, axes, comparison) { let pad = game.input.gamepad.pad1; if (pad && pad.connected) { for (let axis of axes) { if (comparison === "<" && pad.axis(axis) < -0.75) { return true; } else if (comparison === ">" && pad.axis(axis) > 0.75) { return true; } } } return false; }, gamepadAnyPressed: function (game) { return PrinceJS.Utils.gamepadButtonPressedCheck(game); }, gamepadUpPressed: function (game) { return ( PrinceJS.Utils.gamepadButtonDownCheck(game, [ PrinceJS.Gamepad.A, PrinceJS.Gamepad.R, PrinceJS.Gamepad.ZR, PrinceJS.Gamepad.DPadU ]) || PrinceJS.Utils.gamepadAxisCheck(game, [PrinceJS.Gamepad.Axis.LY, PrinceJS.Gamepad.Axis.RY], "<") ); }, gamepadDownPressed: function (game) { return ( PrinceJS.Utils.gamepadButtonDownCheck(game, [PrinceJS.Gamepad.DPadD]) || PrinceJS.Utils.gamepadAxisCheck(game, [PrinceJS.Gamepad.Axis.LY, PrinceJS.Gamepad.Axis.RY], ">") ); }, gamepadLeftPressed: function (game) { return ( PrinceJS.Utils.gamepadButtonDownCheck(game, [PrinceJS.Gamepad.DPadL]) || PrinceJS.Utils.gamepadAxisCheck(game, [PrinceJS.Gamepad.Axis.LX, PrinceJS.Gamepad.Axis.RX], "<") ); }, gamepadRightPressed: function (game) { return ( PrinceJS.Utils.gamepadButtonDownCheck(game, [PrinceJS.Gamepad.DPadR]) || PrinceJS.Utils.gamepadAxisCheck(game, [PrinceJS.Gamepad.Axis.LX, PrinceJS.Gamepad.Axis.RX], ">") ); }, gamepadActionPressed: function (game) { return PrinceJS.Utils.gamepadButtonDownCheck(game, [ PrinceJS.Gamepad.B, PrinceJS.Gamepad.Y, PrinceJS.Gamepad.L, PrinceJS.Gamepad.ZL ]); }, gamepadInfoPressed: function (game) { return PrinceJS.Utils.gamepadButtonPressedCheck(game, [PrinceJS.Gamepad.X], "info"); }, gamepadPreviousPressed: function (game) { return PrinceJS.Utils.gamepadButtonPressedCheck(game, [PrinceJS.Gamepad.Minus], "previous"); }, gamepadNextPressed: function (game) { return PrinceJS.Utils.gamepadButtonPressedCheck(game, [PrinceJS.Gamepad.Plus], "next"); }, pointerPressed: function (game) { let pointerPressed = this._pointerPressed; this._pointerPressed = PrinceJS.Utils.pointerDown(game); return pointerPressed && !this._pointerPressed; }, pointerDown: function (game) { if (game.input.activePointer.leftButton && game.input.activePointer.leftButton.isDown) { return true; } if (game.input.activePointer.isDown) { return true; } if (game.input.pointer1.isDown) { return true; } return game.input.pointer2.isDown; }, effectivePointer: function (game) { let width = document.getElementsByTagName("canvas")[0].getBoundingClientRect().width; let height = document.getElementsByTagName("canvas")[0].getBoundingClientRect().height; let size = PrinceJS.Utils.effectiveScreenSize(game); let x = game.input.activePointer.x || (game.input.pointer1.isDown && game.input.pointer1.x) || (game.input.pointer2.isDown && game.input.pointer2.x) || 0; let y = game.input.activePointer.y || (game.input.pointer1.isDown && game.input.pointer1.y) || (game.input.pointer2.isDown && game.input.pointer2.y) || 0; return { x: x - (width - size.width) / 2, y: y - (height - size.height) / 2 }; }, effectiveScreenSize: function (game) { let width = document.getElementsByTagName("canvas")[0].getBoundingClientRect().width; let height = document.getElementsByTagName("canvas")[0].getBoundingClientRect().height; if (width / height >= PrinceJS.WORLD_RATIO) { return { width: height * PrinceJS.WORLD_RATIO, height }; } else { return { width, height: width / PrinceJS.WORLD_RATIO }; } }, gameContainer: function () { return document.getElementById("gameContainer"); }, resetFlipScreen: function () { PrinceJS.Utils.gameContainer().classList.remove("flipped"); }, toggleFlipScreen: function () { PrinceJS.Utils.gameContainer().classList.toggle("flipped"); }, isScreenFlipped: function () { return PrinceJS.Utils.gameContainer().classList.contains("flipped"); }, setRemainingMinutesTo15() { if (PrinceJS.Utils.getRemainingMinutes() > 15) { PrinceJS.Utils.minutes = 15; let date = new Date(); date.setMinutes(date.getMinutes() - (60 - PrinceJS.Utils.minutes)); PrinceJS.startTime = date; PrinceJS.Utils.updateQuery(); } }, resetRemainingMinutesTo60() { PrinceJS.Utils.minutes = 60; PrinceJS.startTime = undefined; PrinceJS.endTime = undefined; PrinceJS.Utils.updateQuery(); }, getDeltaTime: function () { if (!PrinceJS.startTime) { return { minutes: -1, seconds: -1 }; } let diff = (PrinceJS.endTime || new Date()).getTime() - PrinceJS.startTime.getTime(); let minutes = Math.floor(diff / 60000); let seconds = Math.floor(diff / 1000) % 60; return { minutes, seconds }; }, getRemainingMinutes: function () { let deltaTime = PrinceJS.Utils.getDeltaTime(); return Math.min(60, Math.max(0, 60 - deltaTime.minutes)); }, getRemainingSeconds: function () { let deltaTime = PrinceJS.Utils.getDeltaTime(); return Math.min(60, Math.max(0, 60 - deltaTime.seconds)); }, applyStrength: function (value) { if (PrinceJS.strength >= 0 && PrinceJS.strength < 100) { return Math.ceil((value * PrinceJS.strength) / 100); } return value; }, applyQuery: function () { let query = new URLSearchParams(window.location.search); if (query.get("level") || query.get("l")) { let queryLevel = parseInt(query.get("level") || query.get("l"), 10); if ((!isNaN(queryLevel) && queryLevel >= 1 && queryLevel <= 14) || queryLevel >= 90) { PrinceJS.currentLevel = queryLevel; } } if (query.get("health") || query.get("h")) { let queryHealth = parseInt(query.get("health") || query.get("h"), 10); if (!isNaN(queryHealth) && queryHealth >= 3 && queryHealth <= 10) { PrinceJS.maxHealth = queryHealth; } } if (query.get("time") || query.get("t")) { let queryTime = parseInt(query.get("time") || query.get("t"), 10); if (!isNaN(queryTime) && queryTime >= 1 && queryTime <= 60) { PrinceJS.minutes = queryTime; } } if (query.get("strength") || query.get("s")) { let queryStrength = parseInt(query.get("strength") || query.get("s"), 10); if (!isNaN(queryStrength) && queryStrength >= 0 && queryStrength <= 100) { PrinceJS.strength = queryStrength; } } if (query.get("width") || query.get("w")) { let queryWidth = parseInt(query.get("width") || query.get("w"), 10); if (!isNaN(queryWidth) && queryWidth > 0) { PrinceJS.screenWidth = queryWidth; } } if (query.get("shortcut") || query.get("_")) { PrinceJS.shortcut = (query.get("shortcut") || query.get("_")) === "true"; } }, applyScreenWidth() { if (PrinceJS.screenWidth > 0) { PrinceJS.Utils.gameContainer().style["max-width"] = PrinceJS.screenWidth + "px"; } }, updateQuery: function () { PrinceJS.minutes = PrinceJS.Utils.getRemainingMinutes(); if (PrinceJS.shortcut) { PrinceJS.Utils.setHistoryState({ l: PrinceJS.currentLevel, h: PrinceJS.maxHealth, t: PrinceJS.minutes, s: PrinceJS.strength, w: PrinceJS.screenWidth, _: true }); } else { PrinceJS.Utils.setHistoryState({ level: PrinceJS.currentLevel, health: PrinceJS.maxHealth, time: PrinceJS.minutes, strength: PrinceJS.strength, width: PrinceJS.screenWidth }); } }, restoreQuery: function () { if (PrinceJS.Utils.getRemainingMinutes() < PrinceJS.minutes) { let date = new Date(); date.setMinutes(date.getMinutes() - (60 - PrinceJS.minutes)); PrinceJS.startTime = date; } }, clearQuery: function () { if (PrinceJS.shortcut) { PrinceJS.Utils.setHistoryState({ s: PrinceJS.strength, w: PrinceJS.screenWidth, _: true }); } else { PrinceJS.Utils.setHistoryState({ strength: PrinceJS.strength, width: PrinceJS.screenWidth }); } }, setHistoryState(state) { history.replaceState( null, null, "?" + Object.keys(state) .map((key) => key + "=" + state[key]) .join("&") ); } }; PK �Zl6���/ �/ Enemy.jsnu �[��� "use strict"; PrinceJS.Enemy = function (game, level, location, direction, room, skill, color, key, id) { this.baseCharName = key; if (key === "guard") { key = "guard-" + color; } PrinceJS.Fighter.call(this, game, level, location, direction, room, key, key === "shadow" ? "shadow" : "fighter"); this.id = id; this.charX += direction * 7; this.strikeProbability = PrinceJS.Utils.applyStrength(PrinceJS.Enemy.STRIKE_PROBABILITY[skill]); this.restrikeProbability = PrinceJS.Utils.applyStrength(PrinceJS.Enemy.RESTRIKE_PROBABILITY[skill]); this.blockProbability = PrinceJS.Utils.applyStrength(PrinceJS.Enemy.BLOCK_PROBABILITY[skill]); this.impairblockProbability = PrinceJS.Utils.applyStrength(PrinceJS.Enemy.IMPAIRBLOCK_PROBABILITY[skill]); this.advanceProbability = PrinceJS.Utils.applyStrength(PrinceJS.Enemy.ADVANCE_PROBABILITY[skill]); this.refracTimer = 0; this.blockTimer = 0; this.strikeTimer = 0; this.lookBelow = false; this.startFight = false; this.health = PrinceJS.Enemy.EXTRA_STRENGTH[skill] + PrinceJS.Enemy.STRENGTH[this.level.number]; this.charSkill = skill; this.charColor = color; this.onDamageLife.add(this.resetRefracTimer, this); this.onStrikeBlocked.add(this.resetBlockTimer, this); this.onEnemyStrike.add(this.resetStrikeTimer, this); if (this.charColor > 0) { this.tintSplash(PrinceJS.Enemy.COLOR[this.charColor - 1]); } }; PrinceJS.Enemy.STRIKE_PROBABILITY = [61, 100, 61, 61, 61, 40, 100, 150, 0, 48, 32, 48]; // 220 -> 150 PrinceJS.Enemy.RESTRIKE_PROBABILITY = [0, 0, 0, 5, 5, 175, 16, 8, 0, 255, 255, 150]; PrinceJS.Enemy.BLOCK_PROBABILITY = [0, 150, 150, 200, 200, 255, 200, 250, 0, 255, 255, 255]; PrinceJS.Enemy.IMPAIRBLOCK_PROBABILITY = [0, 61, 61, 100, 100, 145, 100, 250, 0, 145, 255, 175]; PrinceJS.Enemy.ADVANCE_PROBABILITY = [255, 200, 200, 200, 255, 255, 200, 0, 0, 255, 100, 100]; PrinceJS.Enemy.REFRAC_TIMER = [16, 16, 16, 16, 8, 8, 8, 8, 0, 8, 0, 0]; PrinceJS.Enemy.EXTRA_STRENGTH = [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]; PrinceJS.Enemy.STRENGTH = [4, 3, 3, 3, 3, 4, 5, 4, 4, 5, 5, 5, 4, 6, 10, 0]; PrinceJS.Enemy.COLOR = [0x4890fc, 0xa83000, 0xfc5000, 0x0c9000, 0x5a00fc, 0xc858fc, 0xfcfc00]; PrinceJS.Enemy.prototype = Object.create(PrinceJS.Fighter.prototype); PrinceJS.Enemy.prototype.constructor = PrinceJS.Enemy; PrinceJS.Enemy.prototype.updateActor = function () { this.updateSplash(); this.updateBehaviour(); this.processCommand(); this.updateAcceleration(); this.updateVelocity(); this.checkFight(); this.checkSpikes(); this.checkChoppers(); this.checkBarrier(); this.checkButton(); this.checkFloor(); this.checkRoomChange(); this.updateCharPosition(); this.updateSwordPosition(); this.maskAndCrop(); }; PrinceJS.Enemy.prototype.CMD_TAP = function (data) { if (this.charName !== "shadow" || !this.visible) { return; } if (["softLand"].includes(this.action)) { return; } if (data.p1 === 1) { this.game.sound.play("Footsteps"); } else if (data.p1 === 2) { this.game.sound.play("BumpIntoWallHard"); } }; PrinceJS.Enemy.prototype.updateBehaviour = function () { if (this.opponent === null || !this.alive) { return; } if (!this.opponent.alive) { return; } if (this.willStartFight()) { PrinceJS.Utils.delayed( () => { if (this.willStartFight()) { this.startFight = true; } }, this.baseCharName === "jaffar" ? 2300 : 500 ); } if (this.refracTimer > 0) { this.refracTimer--; } if (this.blockTimer > 0) { this.blockTimer--; } if (this.strikeTimer > 0) { this.strikeTimer--; } if ( this.action === "stabbed" || this.action === "stabkill" || this.action === "dropdead" || this.action === "stepfall" ) { return; } let distance = this.opponentDistance(); if (distance === -999) { return; } if (this.swordDrawn) { if (distance >= 35) { this.oppTooFar(distance); } else if (distance < -20) { this.turnengarde(); } else if (distance < 12) { this.oppTooClose(distance); } else { this.oppInRange(distance); } } else { if (this.canReachOpponent(this.lookBelow) || this.canSeeOpponent(this.lookBelow)) { if (!this.sneakUp || this.facingOpponent()) { this.engarde(); } } } }; PrinceJS.Enemy.prototype.willStartFight = function () { return ( this.active && !this.startFight && (this.opponentCloseRoom(this.opponent, this.room) || Math.abs(this.opponentDistance()) < 35) ); }; PrinceJS.Enemy.prototype.enemyAdvance = function () { if (!this.startFight) { return; } if (!this.canReachOpponent(this.lookBelow) && !this.canSeeOpponent(this.lookBelow)) { this.swordDrawn = false; this.stand(); return; } let tile = this.level.getTileAt(this.charBlockX, this.charBlockY, this.room); if (tile.isSpace() && !["advance", "retreat", "strike"].includes(this.action)) { this.startFall(); return; } let tileF = this.level.getTileAt(this.charBlockX + this.charFace, this.charBlockY, this.room); let tileR = this.level.getTileAt(this.charBlockX - this.charFace, this.charBlockY, this.room); if (this.canWalkSafely(tileF, true)) { this.advance(); } else { if (this.canWalkSafely(tileR)) { this.retreat(); } } }; PrinceJS.Enemy.prototype.canWalkSafely = function (tile, below = false) { if (tile.isSafeWalkable()) { return true; } if (below && tile.isSpace() && tile.roomY < 2 && this.opponent.charBlockY === tile.roomY + 1) { tile = this.level.getTileAt(tile.roomX, tile.roomY + 1, tile.room); return tile.isSafeWalkable(); } return false; }; PrinceJS.Enemy.prototype.engarde = function () { if (!this.hasSword) { return; } if (!this.startFight) { return; } this.lookBelow = true; PrinceJS.Fighter.prototype.engarde.call(this); }; PrinceJS.Enemy.prototype.retreat = function () { if (!this.canReachOpponent(this.lookBelow)) { return; } if (this.nearBarrier(this.charBlockX, this.charBlockY, true)) { return; } if (!this.opponent.opponent) { this.opponent.opponent = this; } if ( !this.action.includes("turn") && !this.opponent.action.includes("turn") && !this.facingOpponent() && this.charFace === this.opponent.charFace && this.opponentOnSameLevel() ) { this.turnengarde(); return; } let tileR = this.level.getTileAt(this.charBlockX - this.charFace, this.charBlockY, this.room); if (this.canWalkSafely(tileR)) { PrinceJS.Fighter.prototype.retreat.call(this); } }; PrinceJS.Enemy.prototype.advance = function () { if (!this.canReachOpponent(this.lookBelow)) { return; } if (this.nearBarrier(this.charBlockX, this.charBlockY, true)) { return; } if (!this.opponent.opponent) { this.opponent.opponent = this; } let tileF = this.level.getTileAt(this.charBlockX + this.charFace, this.charBlockY, this.room); let tileFF = this.level.getTileAt(this.charBlockX + 2 * this.charFace, this.charBlockY, this.room); if (this.canWalkSafely(tileF, true) && (!this.opponent.isHanging() || this.canWalkSafely(tileFF, true))) { PrinceJS.Fighter.prototype.advance.call(this); } }; PrinceJS.Enemy.prototype.oppTooFar = function (distance) { if (this.refracTimer !== 0) { return; } if (this.opponent.action === "running" && distance < 40) { this.strike(); return; } if (this.opponent.action === "runjump" && distance < 50) { this.strike(); return; } this.enemyAdvance(); }; PrinceJS.Enemy.prototype.oppTooClose = function () { if (this.charFace === this.opponent.charFace || !["engarde", "advance", "retreat"].includes(this.opponent.action)) { this.retreat(); } else { this.advance(); } }; PrinceJS.Enemy.prototype.oppInRange = function (distance) { if (!this.opponent.swordDrawn) { if (this.refracTimer === 0) { if (distance <= 25) { this.strike(); } else { this.advance(); } } } else { this.oppInRangeArmed(distance); } }; PrinceJS.Enemy.prototype.oppInRangeArmed = function (distance) { if (!this.opponentOnSameLevel()) { return; } if (distance < 10 || distance >= 28) { this.tryAdvance(); } else { this.tryBlock(); if (this.refracTimer === 0) { if (distance < 12) { this.tryAdvance(); } else { this.tryStrike(); } } } }; PrinceJS.Enemy.prototype.tryAdvance = function () { if (this.charSkill === 0 || this.strikeTimer === 0) { if (this.advanceProbability > this.game.rnd.between(0, 254)) { this.advance(); } } }; PrinceJS.Enemy.prototype.tryBlock = function () { if ( this.opponent.frameID(152, 153) || this.opponent.frameID(162) || this.opponent.frameID(2, 3) || this.opponent.frameID(12) ) { if (this.blockTimer !== 0) { if (this.impairblockProbability > this.game.rnd.between(0, 254)) { this.block(); } } else { if (this.blockProbability > this.game.rnd.between(0, 254)) { this.block(); } } } }; PrinceJS.Enemy.prototype.tryStrike = function () { if ( this.opponent.frameID(169) || this.opponent.frameID(151) || this.opponent.frameID(19) || this.opponent.frameID(1) ) { return; } if (this.frameID(150)) { if (this.restrikeProbability > this.game.rnd.between(0, 254)) { this.strike(); } } else { if (this.strikeProbability > this.game.rnd.between(0, 254)) { this.strike(); } } }; PrinceJS.Enemy.prototype.resetRefracTimer = function () { this.refracTimer = PrinceJS.Enemy.REFRAC_TIMER[this.charSkill]; }; PrinceJS.Enemy.prototype.resetBlockTimer = function () { this.blockTimer = 4; }; PrinceJS.Enemy.prototype.resetStrikeTimer = function () { this.strikeTimer = 15; }; PrinceJS.Enemy.prototype.fastsheathe = function () { if (this.charName === "shadow") { this.setInactive(); this.action = "fastsheathe"; this.swordDrawn = false; } }; PrinceJS.Enemy.prototype.setVisible = function () { this.visible = true; this.sword.visible = true; }; PrinceJS.Enemy.prototype.setInvisible = function () { this.visible = false; this.sword.visible = false; }; PrinceJS.Enemy.prototype.setActive = function () { this.setVisible(); this.active = true; if (this.charName === "skeleton") { this.action = "arise"; } }; PrinceJS.Enemy.prototype.setInactive = function () { this.active = false; this.startFight = false; if (this.charName === "skeleton") { this.action = "laydown"; } }; PrinceJS.Enemy.prototype.checkBarrier = function () { if (!this.alive || this.charName === "shadow") { return; } if (["stand", "turn", "stepfall", "freefall"].includes(this.action)) { return; } let tile = this.level.getTileAt(this.charBlockX, this.charBlockY, this.room); if (this.moveR() && tile.isBarrier()) { if (tile.intersects(this.getCharBounds())) { this.bump(tile); } } else { let blockX = PrinceJS.Utils.convertXtoBlockX(this.charX + this.charFdx * this.charFace - 12); let tileNext = this.level.getTileAt(blockX, this.charBlockY, this.room); if (tileNext.isBarrier()) { switch (tileNext.element) { case PrinceJS.Level.TILE_WALL: this.bump(tileNext); break; case PrinceJS.Level.TILE_GATE: case PrinceJS.Level.TILE_TAPESTRY: case PrinceJS.Level.TILE_TAPESTRY_TOP: if (tileNext.intersects(this.getCharBounds())) { this.bump(tileNext); } break; } } } }; PrinceJS.Enemy.prototype.bump = function (tile) { if (this.moveR()) { this.charX -= 2; } else if (this.moveL()) { this.charX += 10; } else { this.charX += 5 * (this.centerX > tile.centerX ? 1 : -1); } this.updateBlockXY(); this.action = "bump"; }; PrinceJS.Enemy.prototype.appearOutOfMirror = function (mirror) { this.charX = PrinceJS.Utils.convertBlockXtoX(mirror.roomX) + 20; this.charY = PrinceJS.Utils.convertBlockYtoY(mirror.roomY) - 14; this.action = "runjumpdown"; this.charFrame = 42; this.updateBlockXY(); this.updateCharPosition(); this.processCommand(); this.setVisible(); }; PK �Z!Z�<�g �g Game.jsnu �[��� "use strict"; PrinceJS.Game = function (game) { this.kid; this.level; this.ui; this.currentRoom; this.enemies = []; }; PrinceJS.Game.prototype = { preload: function () { this.game.load.audio("TheShadow", "assets/music/15_The_Shadow.mp3"); this.game.load.audio("Float", "assets/music/16_Float.mp3"); this.game.load.audio("Jaffar2", "assets/music/19_Jaffar_2.mp3"); this.game.load.audio("JaffarDead", "assets/music/20_Jaffar_Dead.mp3"); this.game.load.audio("HeroicDeath", "assets/music/13_Heroic_Death.mp3"); let levelBasePath = PrinceJS.currentLevel < 90 ? "assets/maps/" : "assets/maps/custom/"; this.load.json("level", levelBasePath + "level" + PrinceJS.currentLevel + ".json"); }, create: function () { this.game.sound.stopAll(); this.continueTimer = -1; this.pressButtonToContinueTimer = -1; this.pressButtonToNext = false; if (!PrinceJS.startTime) { let date = new Date(); date.setMinutes(date.getMinutes() - (60 - PrinceJS.minutes)); PrinceJS.startTime = date; } let json = this.game.cache.getJSON("level"); if (!json) { this.restartGame(); return; } this.level = new PrinceJS.LevelBuilder(this.game, this).buildFromJSON(json); this.specialEvents = json.prince.specialEvents !== false; this.playDanger = json.prince.danger !== false; this.shadow = null; this.mouse = null; for (let i = 0; i < json.guards.length; i++) { let data = json.guards[i]; let enemy = new PrinceJS.Enemy( this.game, this.level, data.location + (data.bias || 0), data.direction * (data.reverse || 1), data.room, data.skill, data.colors, data.type, i + 1 ); if (data.visible === false) { enemy.setInvisible(); } if (data.active === false) { enemy.setInactive(); } if (data.sneak === false) { enemy.setSneakUp(false); } enemy.onInitLife.add((fighter) => { this.ui.setOpponentLive(fighter); }, this); this.enemies.push(enemy); if (enemy.charName === "shadow") { this.shadow = enemy; } } let turn = json.prince.turn !== false; let direction = json.prince.direction * (json.prince.reverse || 1); if (turn) { direction = -direction; } this.kid = new PrinceJS.Kid( this.game, this.level, json.prince.location + (json.prince.bias || 0), direction, json.prince.room ); if (typeof json.prince.sword === "boolean") { this.kid.hasSword = json.prince.sword; } if (turn) { this.kid.charX += 7; PrinceJS.Utils.delayed(() => { this.kid.action = "turn"; }, 100); } this.kid.charX += json.prince.offset || 0; this.game.onPause.add(this.onPause, this); this.game.onResume.add(this.onResume, this); this.kid.onChangeRoom.add(this.changeRoom, this); this.kid.onDead.add(this.handleDead, this); this.kid.onFlipped.add(this.handleFlipped, this); this.kid.onNextLevel.add(this.nextLevel, this); this.kid.onLevelFinished.add(this.levelFinished, this); PrinceJS.Tile.Gate.reset(); this.visitedRooms = {}; this.currentRoom = json.prince.room; this.blockCamera = false; this.world.sort("z"); this.world.alpha = 1; this.ui = new PrinceJS.Interface(this.game, this); this.ui.setPlayerLive(this.kid); this.setupCamera(json.prince.room, json.prince.cameraRoom); this.game.time.events.loop(80, this.updateWorld, this); this.input.keyboard.addKey(Phaser.Keyboard.R).onDown.add(this.restartGameEvent, this); this.input.keyboard.addKey(Phaser.Keyboard.A).onDown.add(this.restartLevelEvent, this); this.input.keyboard.addKey(Phaser.Keyboard.L).onDown.add(this.nextLevelEvent, this); this.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR).onDown.add(this.showRemainingMinutes, this); this.input.keyboard.onDownCallback = this.buttonPressed.bind(this); this.firstUpdate = true; if (PrinceJS.danger === null) { PrinceJS.danger = this.level.number === 1 && this.playDanger; } PrinceJS.Utils.resetFlipScreen(); PrinceJS.Utils.updateQuery(); }, update: function () { if (PrinceJS.Utils.continueGame(this.game)) { this.buttonPressed(); let pos = PrinceJS.Utils.effectivePointer(this.game); let size = PrinceJS.Utils.effectiveScreenSize(this.game); if ( (PrinceJS.Utils.isScreenFlipped() && pos.y >= 0 && pos.y <= 0.04 * size.height) || (!PrinceJS.Utils.isScreenFlipped() && pos.y >= 0.96 * size.height && pos.y <= size.height) ) { if (this.isRemainingMinutesShown() || this.isLevelShown()) { if (pos.x >= 0 && pos.x <= 0.2 * size.width) { this.previousLevel(PrinceJS.currentLevel, true); } else if (pos.x >= 0.8 * size.width && pos.x <= size.width) { this.nextLevel(PrinceJS.currentLevel, true, true); } else if (pos.x >= 0.4 * size.width && pos.x <= 0.6 * size.width) { this.restartLevel(true); } } if (pos.x >= 0 && pos.x <= size.width) { this.showRemainingMinutes(); } } if (PrinceJS.Utils.gamepadInfoPressed(this.game)) { if (this.isRemainingMinutesShown() || this.isLevelShown()) { this.restartLevel(true); } else { this.showRemainingMinutes(); } } else if (PrinceJS.Utils.gamepadPreviousPressed(this.game)) { this.previousLevel(PrinceJS.currentLevel, true); } else if (PrinceJS.Utils.gamepadNextPressed(this.game)) { this.nextLevel(PrinceJS.currentLevel, true, true); } } }, updateWorld: function () { this.level.update(); this.kid.updateActor(); for (let i = 0; i < this.enemies.length; i++) { this.enemies[i].updateActor(); } if (this.mouse) { this.mouse.updateActor(); } this.checkLevelLogic(); this.ui.updateUI(); this.checkTimers(); this.firstUpdate = false; }, checkLevelLogic: function () { if (!this.specialEvents) { return; } let jaffar; let skeleton; let tile; switch (this.level.number) { case 1: if (this.firstUpdate) { this.level.fireEvent(8, PrinceJS.Level.TILE_DROP_BUTTON); if (PrinceJS.danger) { PrinceJS.Utils.delayed(() => { this.game.sound.play("Danger"); }, 800); } } break; case 2: if (this.firstUpdate) { for (let i = 0; i < this.enemies.length; i++) { let enemy = this.enemies[i]; if (enemy && enemy.room === 24 && enemy.charBlockX === 0 && enemy.charBlockY === 1) { enemy.charX -= 12; enemy.updateBlockXY(); } } } break; case 3: skeleton = this.kid.opponent && this.kid.opponent.charName === "skeleton" ? this.kid.opponent : null; if (skeleton) { if ( this.level.exitDoorOpen && this.kid.room === skeleton.room && Math.abs(this.kid.opponentDistance()) < 999 ) { let tile = this.level.getTileAt(skeleton.charBlockX, skeleton.charBlockY, skeleton.room); if (tile.element === PrinceJS.Level.TILE_SKELETON) { tile.removeObject(); skeleton.setActive(); this.game.sound.play("BonesLeapToLife"); } } if (skeleton.room === 3 && skeleton.setCharForRoom !== skeleton.room) { skeleton.setCharForRoom = skeleton.room; PrinceJS.Utils.delayed(() => { if (skeleton.charFace === -1) { skeleton.turn(); } skeleton.room = 3; skeleton.charX = PrinceJS.Utils.convertBlockXtoX(4); skeleton.charY = PrinceJS.Utils.convertBlockYtoY(1); skeleton.action = "stand"; this.kid.sheathe(); }, 100); } if (skeleton.room === 3 && skeleton.charBlockY === 1 && skeleton.charX <= 45 && !skeleton.inFallDown) { skeleton.charX = 55; skeleton.updateBlockXY(); skeleton.startFall(); } if (skeleton.room === 8 && !skeleton.defeated) { skeleton.defeated = true; this.game.sound.play("Victory"); this.kid.sheathe(); } } break; case 4: if (this.level.exitDoorOpen && this.kid.room === 11 && this.kid.charBlockY === 0) { tile = this.level.getTileAt(4, 0, 4); if (tile instanceof PrinceJS.Tile.Mirror) { tile.addObject(); this.kid.delegate = tile; this.level.mirror = tile; } } else if ( this.level.exitDoorOpen && this.currentCameraRoom === 4 && this.kid.charBlockY === 0 && this.level.mirror && !this.level.mirrorDetected ) { this.level.mirrorDetected = true; PrinceJS.Utils.delayed(() => { this.game.sound.play("Danger"); }, 100); } tile = this.level.getTileAt(this.kid.charBlockX - this.kid.charFace, this.kid.charBlockY, this.kid.room); if ( tile && tile.element === PrinceJS.Level.TILE_MIRROR && this.kid.action === "runjump" && this.kid.faceL() && !this.level.shadowOutOfMirror ) { if (this.kid.distanceToFloor() === 0) { this.kid.bump(); } else { tile.hideReflection(); this.shadow && this.shadow.appearOutOfMirror(tile); this.level.shadowOutOfMirror = true; this.game.sound.play("Mirror"); this.kid.stealLife(); } } if (this.level.mirror && this.kid.room === 4 && this.kid.charBlockX <= 3 && this.kid.charBlockY === 1) { tile = this.level.getTileAt(4, 0, 4); if (tile && tile.element === PrinceJS.Level.TILE_MIRROR) { tile.hideReflection(); } } if (this.shadow && this.shadow.visible && this.shadow.charBlockY > 0) { this.shadow.action = "stand"; this.shadow.setInvisible(); } break; case 5: if (this.shadow) { tile = this.level.getTileAt(1, 0, 24); if (tile.state === PrinceJS.Tile.Gate.STATE_RAISING && !this.shadow.visible && this.shadow.faceR()) { this.shadow.visible = true; this.performProgram( [ { i: "ACTION", p1: 2600, p2: "running" }, { i: "ACTION", p1: 700, p2: "runstop" }, { i: "ACTION", p1: 0, p2: "drinkpotion" }, { i: "SOUND", p1: 0, p2: "DrinkPotionGlugGlug" }, { i: "REM_OBJECT" }, { i: "WAIT", p1: 1500 }, { i: "ACTION", p1: 500, p2: "turn" }, { i: "ACTION", p1: 3000, p2: "running" } ], this.shadow ); } if ( this.shadow.visible && (this.currentCameraRoom === 11 || (this.shadow.room === 11 && this.shadow.charBlockX === 8 && this.shadow.faceL())) ) { this.shadow.action = "stand"; this.shadow.setInvisible(); } } break; case 6: if (this.shadow) { if (this.firstUpdate) { this.shadow.charX += 8; } if (this.currentCameraRoom === 1) { if (!this.level.shadowDetected) { this.level.shadowDetected = true; this.game.sound.play("Danger"); } if (this.kid.charBlockX === 6) { this.shadow.action = "step11"; } } } if (this.currentCameraRoom === 1 && this.kid.charBlockY === 2 && this.kid.charY >= 185) { this.blockCamera = true; PrinceJS.Utils.delayed(() => { this.nextLevel(PrinceJS.currentLevel); }, 100); } break; case 8: if (this.level.exitDoorOpen && this.currentCameraRoom === 16 && this.kid.charBlockY === 0) { if (!this.level.waitForMouse) { this.level.waitForMouse = true; PrinceJS.Utils.delayed(() => { this.level.waitedForMouse = true; }, 12500); } if (this.level.waitedForMouse && !this.mouse) { this.mouse = new PrinceJS.Mouse(this.game, this.level, 16, 9, -1); this.performProgram( [ { i: "ACTION", p1: 625, p2: "scurry" }, { i: "ACTION", p1: 0, p2: "stop" }, { i: "ACTION", p1: 1000, p2: "raise" }, { i: "ACTION", p1: 0, p2: "stop" }, { i: "TURN", p1: 0 }, { i: "ACTION", p1: 600, p2: "scurry" }, { i: "REM_ACTOR" } ], this.mouse ); } } break; case 12: if ( this.kid.room === 20 && this.kid.charBlockY === 1 && this.level.getTileAt(1, 0, 15).element === PrinceJS.Level.TILE_SWORD ) { this.level.removeObject(1, 0, 15); } if (!this.shadow) { this.level.leapOfFaith = true; } else { if ( this.kid.room === 15 && (this.kid.charBlockX === 5 || this.kid.charBlockX === 6) && !this.shadow.visible && !this.level.shadowMerge ) { this.shadow.charX = PrinceJS.Utils.convertBlockXtoX(1); this.shadow.charY = PrinceJS.Utils.convertBlockYtoY(1); this.shadow.setVisible(); this.shadow.setActive(); PrinceJS.Utils.delayed(() => { this.shadow.refracTimer = 9; this.shadow.opponent = this.kid; this.kid.opponent = this.shadow; this.kid.opponentSync = true; }, 1000); } if ( !this.shadow.active && this.kid.opponent && Math.abs(this.kid.opponentDistance()) <= (this.kid.action.includes("jump") ? 15 : 7) && !this.level.shadowMerge ) { this.level.shadowMerge = true; this.level.leapOfFaith = true; this.ui.resetOpponentLive(); this.kid.addLife(); this.kid.mergeShadowPosition(); this.kid.showShadowOverlay(); this.kid.flashShadowOverlay(); PrinceJS.Utils.flashWhiteShadowMerge(this.game); PrinceJS.Utils.delayed(() => { this.game.sound.play("Prince"); }, 2000); } } if (this.level.leapOfFaith && !this.level.leapOfFaithSetup && this.level.rooms[2]) { this.level.leapOfFaithSetup = true; for (let i = 0; i < 10; i++) { tile = this.level.getTileAt(i, 0, 2); if (tile && tile.element === PrinceJS.Level.TILE_SPACE) { tile.element = PrinceJS.Level.TILE_FLOOR; tile.hidden = true; } if (i >= 6) { tile = this.level.getTileAt(i, 0, this.level.rooms[2].links.left); if (tile && tile.element === PrinceJS.Level.TILE_SPACE) { tile.element = PrinceJS.Level.TILE_FLOOR; tile.hidden = true; } } } } if (this.currentCameraRoom === 23) { this.nextLevel(PrinceJS.currentLevel); } break; case 13: if (this.firstUpdate) { this.kid.action = "startrun"; } Object.keys(this.visitedRooms).forEach((visitedRoom) => { if (!["16", "23"].includes(visitedRoom)) { return; } let tiles = [2, 3, 4, 5, 6, 7].sort(() => Math.random() - 0.5); for (let i = 0; i < tiles.length; i++) { let tile = this.kid.level.getTileAt(tiles[i], 2, this.level.rooms[visitedRoom].links.up); if (tile.element === PrinceJS.Level.TILE_LOOSE_BOARD && !tile.fallStarted()) { tile.shake(true); break; } } }); jaffar = this.kid.opponent && this.kid.opponent.baseCharName === "jaffar" ? this.kid.opponent : null; if (jaffar) { if (!jaffar.alive && !PrinceJS.endTime) { PrinceJS.endTime = new Date(); this.showRemainingMinutes(); } if (!jaffar.alive && !this.level.triggerOpenExitDoor) { this.level.triggerOpenExitDoor = true; PrinceJS.Utils.delayed(() => { let button = this.level.getTileAt(0, 0, 24); if (button.element === PrinceJS.Level.TILE_RAISE_BUTTON) { button.mute = true; button.push(); } }, 7000); } } break; case 14: if (this.currentCameraRoom === 5) { this.nextLevel(PrinceJS.currentLevel); } break; } }, fireEvent: function (event, type, stuck) { this.level.fireEvent(event, type, stuck); }, performProgram: function (program, actor) { return program.reduce((promise, operation) => { return promise.then(() => { let object = operation.o || actor; let fn; switch (operation.i) { case "ACTION": fn = () => { object.action = operation.p2; }; break; case "WAIT": fn = () => {}; break; case "TURN": fn = () => { object.turn(); }; break; case "SOUND": fn = () => { this.game.sound.play(operation.p2); }; break; case "REM_OBJECT": fn = () => { this.level.removeObject(object.charBlockX, object.charBlockY, object.room); }; break; case "REM_ACTOR": fn = () => { object.visible = false; object.kill(); }; break; default: fn = operation.i; break; } return PrinceJS.Utils.perform(fn, operation.p1); }); }, Promise.resolve()); }, checkTimers: function () { if (this.continueTimer > -1) { this.continueTimer--; if (this.continueTimer === 0) { this.continueTimer = -1; this.ui.showPressButtonToContinue(); this.pressButtonToContinueTimer = 260; } } if (this.pressButtonToContinueTimer > -1) { this.pressButtonToContinueTimer--; if (this.pressButtonToContinueTimer === 0) { this.pressButtonToContinueTimer = -1; this.restartGame(); } } }, showRemainingMinutes: function (force) { this.ui.showRemainingMinutes(force); }, isRemainingMinutesShown: function () { return this.ui.isRemainingMinutesShown(); }, isLevelShown: function () { return this.ui.isLevelShown(); }, restartGameEvent(event) { if (!event.ctrlKey && !event.shiftKey) { return; } this.restartGame(); }, restartLevelEvent(event) { if (!event.ctrlKey && !event.shiftKey) { return; } this.restartLevel(true); }, nextLevelEvent: function (event) { if (!event.ctrlKey && !event.shiftKey) { return; } if (PrinceJS.currentLevel > 3 && PrinceJS.currentLevel < 90) { return; } this.nextLevel(undefined, true); }, restartGame() { this.input.keyboard.onDownCallback = null; PrinceJS.Restart(); this.state.start("Title"); }, restartLevel(skipped = true) { this.reset(true); PrinceJS.skipShowLevel = [13, 14].includes(PrinceJS.currentLevel) && !skipped; }, levelFinished() { this.pressButtonToNext = true; }, nextLevel: function (triggerLevel, skipped = false, keepRemainingTime = false) { if (triggerLevel !== undefined && triggerLevel !== PrinceJS.currentLevel) { return; } PrinceJS.danger = null; PrinceJS.currentLevel++; PrinceJS.currentHealth = PrinceJS.currentLevel === 13 ? this.kid.health : null; PrinceJS.maxHealth = this.kid.maxHealth; if (PrinceJS.currentLevel > 15 && PrinceJS.currentLevel < 90) { this.restartGame(); return; } if (skipped && !keepRemainingTime) { PrinceJS.Utils.setRemainingMinutesTo15(); } if (PrinceJS.currentLevel >= 100 && this.level.number === 14) { PrinceJS.Utils.resetRemainingMinutesTo60(); } this.reset(); PrinceJS.skipShowLevel = [13, 14].includes(PrinceJS.currentLevel) && !skipped; }, previousLevel: function (triggerLevel, skipped = false) { if (triggerLevel !== undefined && triggerLevel !== PrinceJS.currentLevel) { return; } PrinceJS.danger = null; if (PrinceJS.currentLevel > 1) { PrinceJS.currentLevel--; } this.reset(); PrinceJS.skipShowLevel = [13, 14].includes(PrinceJS.currentLevel) && !skipped; }, handleDead: function () { this.continueTimer = 10; }, handleFlipped: function () { this.ui.flipped(); }, handleChop: function (tile) { tile.chop(tile.room === this.currentCameraRoom); }, timeUp() { PrinceJS.Utils.delayed(() => { PrinceJS.currentLevel = 16; this.state.start("Cutscene"); }, 1000); }, outOfRoom() { this.kid.die(); this.handleDead(); }, buttonPressed: function () { if (this.pressButtonToContinueTimer > -1) { this.reset(true); } if (this.pressButtonToNext) { this.nextLevel(PrinceJS.currentLevel); } }, reset: function (suppressCutscene) { this.game.sound.stopAll(); this.continueTimer = -1; this.pressButtonToContinueTimer = -1; this.pressButtonToNext = false; this.enemies = []; if (!suppressCutscene && [2, 4, 6, 8, 9, 12, 15].indexOf(PrinceJS.currentLevel) > -1) { this.state.start("Cutscene"); } else { this.state.start("Game"); } PrinceJS.skipShowLevel = [13, 14].includes(PrinceJS.currentLevel); }, onPause: function () { PrinceJS.Utils.updateQuery(); this.ui.showGamePaused(); }, onResume: function () { PrinceJS.Utils.restoreQuery(); this.showRemainingMinutes(true); }, changeRoom: function (room, cameraRoom) { this.setupCamera(room, cameraRoom); if (this.currentRoom === room) { return; } this.currentRoom = room; this.kid.flee = false; }, setupCamera: function (room, cameraRoom) { if (this.blockCamera) { return; } if (this.currentRoom > 0 && room <= 0) { this.outOfRoom(); return; } if (cameraRoom === 0) { return; } room = cameraRoom || room; if (this.level.rooms[room]) { this.game.camera.x = this.level.rooms[room].x * PrinceJS.SCREEN_WIDTH * PrinceJS.SCALE_FACTOR; this.game.camera.y = this.level.rooms[room].y * PrinceJS.ROOM_HEIGHT * PrinceJS.SCALE_FACTOR; this.checkForOpponent(room); this.level.checkGates(room, this.currentCameraRoom); this.currentCameraRoom = room; this.visitedRooms[this.currentCameraRoom] = true; } }, checkGateFastDropped: function (gate) { for (let i = 0; i < this.enemies.length; i++) { let enemy = this.enemies[i]; if (enemy.room === gate.room) { if (enemy.faceL() && enemy.charBlockX <= gate.roomX) { enemy.turn(); } else if (enemy.faceR() && enemy.charBlockX >= gate.roomX) { enemy.turn(); } } } }, recheckCurrentRoom: function () { this.checkForOpponent(this.currentCameraRoom); }, checkForOpponent: function (room) { let currentEnemy; // Same Room / Same BlockY for (let i = 0; i < this.enemies.length; i++) { let enemy = this.enemies[i]; if (enemy.alive && this.kid.charBlockY === enemy.charBlockY && this.kid.opponentInSameRoom(enemy, room)) { currentEnemy = enemy; break; } } // Near Room / Same BlockY if (!currentEnemy) { for (let i = 0; i < this.enemies.length; i++) { let enemy = this.enemies[i]; if (enemy.alive && this.kid.charBlockY === enemy.charBlockY && this.kid.opponentNearRoom(enemy, room)) { currentEnemy = enemy; break; } } } // Same Room if (!currentEnemy) { for (let i = 0; i < this.enemies.length; i++) { let enemy = this.enemies[i]; if (enemy.alive && this.kid.opponentInSameRoom(enemy, room)) { currentEnemy = enemy; break; } } } // Near Room if (!currentEnemy) { for (let i = 0; i < this.enemies.length; i++) { let enemy = this.enemies[i]; if (enemy.alive && this.kid.opponentNearRoom(enemy, room)) { currentEnemy = enemy; break; } } } if (currentEnemy) { if (currentEnemy.baseCharName === "jaffar" && currentEnemy.alive && !currentEnemy.meet) { this.game.sound.play("Jaffar2"); } if (this.kid.opponent !== currentEnemy) { this.kid.opponent = currentEnemy; this.kid.flee = false; } currentEnemy.opponent = this.kid; currentEnemy.meet = true; } let opponentSameRoom = false; let opponentNextRoom = false; if (this.kid.opponent) { if (this.kid.opponentInSameRoom(this.kid.opponent, room)) { opponentSameRoom = true; } if (this.kid.opponentNextRoom(this.kid.opponent, room)) { opponentNextRoom = true; } } if (this.ui) { if (opponentSameRoom) { this.ui.setOpponentLive(this.kid.opponent); } else if ( !this.kid.opponent || this.kid.opponent !== this.ui.opp || !this.kid.opponentOnSameLevel() || !opponentNextRoom ) { this.ui.resetOpponentLive(); } } }, floorStartFall: function (tile) { this.level.floorStartFall(tile); }, floorStopFall: function (tile) { this.level.floorStopFall(tile); this.kid.checkLooseFloor(tile); for (let i = 0; i < this.enemies.length; i++) { this.enemies[i].checkLooseFloor(tile); } } }; PK �Z<t�j) ) Preloader.jsnu �[��� "use strict"; PrinceJS.Preloader = function (game) {}; PrinceJS.Preloader.prototype = { preload: function () { this.text = this.game.add.bitmapText( PrinceJS.SCREEN_WIDTH * 0.5, PrinceJS.SCREEN_HEIGHT * 0.5, "font", "Loading. . . .", 16 ); this.text.anchor.setTo(0.5, 0.5); this.load.atlasJSONHash("kid", "assets/gfx/kid.png", "assets/gfx/kid.json"); this.load.atlasJSONHash("princess", "assets/gfx/princess.png", "assets/gfx/princess.json"); this.load.atlasJSONHash("vizier", "assets/gfx/vizier.png", "assets/gfx/vizier.json"); this.load.atlasJSONHash("mouse", "assets/gfx/mouse.png", "assets/gfx/mouse.json"); this.load.atlasJSONHash("guard-1", "assets/gfx/guard-1.png", "assets/gfx/guard-1.json"); this.load.atlasJSONHash("guard-2", "assets/gfx/guard-2.png", "assets/gfx/guard-2.json"); this.load.atlasJSONHash("guard-3", "assets/gfx/guard-3.png", "assets/gfx/guard-3.json"); this.load.atlasJSONHash("guard-4", "assets/gfx/guard-4.png", "assets/gfx/guard-4.json"); this.load.atlasJSONHash("guard-5", "assets/gfx/guard-5.png", "assets/gfx/guard-5.json"); this.load.atlasJSONHash("guard-6", "assets/gfx/guard-6.png", "assets/gfx/guard-6.json"); this.load.atlasJSONHash("guard-7", "assets/gfx/guard-7.png", "assets/gfx/guard-7.json"); this.load.atlasJSONHash("fatguard", "assets/gfx/fatguard.png", "assets/gfx/fatguard.json"); this.load.atlasJSONHash("jaffar", "assets/gfx/jaffar.png", "assets/gfx/jaffar.json"); this.load.atlasJSONHash("skeleton", "assets/gfx/skeleton.png", "assets/gfx/skeleton.json"); this.load.atlasJSONHash("shadow", "assets/gfx/shadow.png", "assets/gfx/shadow.json"); this.load.atlasJSONHash("dungeon", "assets/gfx/dungeon.png", "assets/gfx/dungeon.json"); this.load.atlasJSONHash("palace", "assets/gfx/palace.png", "assets/gfx/palace.json"); this.load.atlasJSONHash("general", "assets/gfx/general.png", "assets/gfx/general.json"); this.load.atlasJSONHash("sword", "assets/gfx/sword.png", "assets/gfx/sword.json"); this.load.atlasJSONHash("title", "assets/gfx/title.png", "assets/gfx/title.json"); this.load.atlasJSONHash("cutscene", "assets/gfx/cutscene.png", "assets/gfx/cutscene.json"); this.load.json("kid-anims", "assets/anims/kid.json"); this.load.json("sword-anims", "assets/anims/sword.json"); this.load.json("fighter-anims", "assets/anims/fighter.json"); this.load.json("princess-anims", "assets/anims/princess.json"); this.load.json("shadow-anims", "assets/anims/shadow.json"); this.load.json("vizier-anims", "assets/anims/vizier.json"); this.load.json("mouse-anims", "assets/anims/mouse.json"); // Music this.game.load.audio("PrologueA", "assets/music/01_Prologue_A.mp3"); this.game.load.audio("PrologueB", "assets/music/02_Prologue_B.mp3"); this.game.load.audio("Danger", "assets/music/06_Danger.mp3"); this.game.load.audio("Accident", "assets/music/07_Accident.mp3"); this.game.load.audio("Potion1", "assets/music/08_Potion_1.mp3"); this.game.load.audio("Victory", "assets/music/09_Victory.mp3"); this.game.load.audio("Prince", "assets/music/11_Prince.mp3"); this.game.load.audio("Potion2", "assets/music/14_Potion_2.mp3"); // SFX this.game.load.audio("FreeFallLand", "assets/sfx/01_Free_fall_land.mp3"); this.game.load.audio("LooseFloorLands", "assets/sfx/02_Loose_floor_lands.mp3"); this.game.load.audio("LooseFloorShakes1", "assets/sfx/03_Loose_floor_shakes.mp3"); this.game.load.audio("GateComingDownSlow", "assets/sfx/04_Gate_coming_down_slow.mp3"); this.game.load.audio("GateRising", "assets/sfx/05_Gate_rising.mp3"); this.game.load.audio("GateReachesBottomClang", "assets/sfx/06_Gate_reaches_bottom_clang.mp3"); this.game.load.audio("GateStopsAtTop", "assets/sfx/07_Gate_stops_at_top.mp3"); this.game.load.audio("BumpIntoWallSoft", "assets/sfx/08_Bump_into_wall_soft.mp3"); this.game.load.audio("BumpIntoWallHard", "assets/sfx/09_Bump_into_wall_hard.mp3"); this.game.load.audio("SwordClash", "assets/sfx/10_Sword_clash.mp3"); this.game.load.audio("StabAir", "assets/sfx/11_Stab_air.mp3"); this.game.load.audio("StabOpponent", "assets/sfx/12_Stab_opponent.mp3"); this.game.load.audio("StabbedByOpponent", "assets/sfx/13_Stabbed_by_opponent.mp3"); this.game.load.audio("MediumLandingOof", "assets/sfx/14_Medium_landing_oof.mp3"); this.game.load.audio("SoftLanding", "assets/sfx/15_Soft_landing.mp3"); this.game.load.audio("UnsheatheSword", "assets/sfx/16_Unsheathe_sword.mp3"); this.game.load.audio("LooseFloorShakes3", "assets/sfx/17_Loose_floor_shakes_3.mp3"); this.game.load.audio("LooseFloorShakes2", "assets/sfx/18_Loose_floor_shakes_2.mp3"); this.game.load.audio("FloorButton", "assets/sfx/19_Floor_button.mp3"); this.game.load.audio("Footsteps", "assets/sfx/20_Footsteps.mp3"); this.game.load.audio("BonesLeapToLife", "assets/sfx/21_Bones_leap_to_life.mp3"); this.game.load.audio("Mirror", "assets/sfx/22_Mirror.mp3"); this.game.load.audio("HalvedByChopper", "assets/sfx/23_Halved_by_chopper.mp3"); this.game.load.audio("SlicerBladesClash", "assets/sfx/24_Slicer_blades_clash.mp3"); this.game.load.audio("HardLandingSplat", "assets/sfx/25_Hard_landing_splat.mp3"); this.game.load.audio("ImpaledBySpikes", "assets/sfx/26_Impaled_by_spikes.mp3"); this.game.load.audio("DoorSqueak", "assets/sfx/27_Door_squeak.mp3"); this.game.load.audio("FallingFloorLands", "assets/sfx/28_Falling_floor_lands.mp3"); this.game.load.audio("EntranceDoorCloses", "assets/sfx/29_Entrance_door_closes.mp3"); this.game.load.audio("ExitDoorOpening", "assets/sfx/30_Exit_door_opening.mp3"); this.game.load.audio("DrinkPotionGlugGlug", "assets/sfx/31_Drink_potion_glug_glug.mp3"); this.game.load.audio("Beep", "assets/sfx/32_Beep.mp3"); this.game.load.audio("SpikedBySpikes", "assets/sfx/33_Spiked_by_spikes.mp3"); }, create: function () { this.text.setText("Press to Start"); this.input.keyboard.onDownCallback = this.start.bind(this); this.game.input.onDown.addOnce(() => { this.game.sound.context.resume(); }); this.game.input.mouse.capture = true; this.game.input.addPointer(); this.game.input.addPointer(); this.game.input.gamepad.start(); this.game.canvas.oncontextmenu = function (event) { event.preventDefault(); }; }, update: function () { if (PrinceJS.Utils.pointerPressed(this.game)) { this.start(); } }, start: function () { if (PrinceJS.SKIP_TITLE) { this.state.start("Game"); } else { this.state.start("Title"); } } }; PK �Zv�(�3 3 Mouse.jsnu �[��� "use strict"; PrinceJS.Mouse = function (game, level, room, location, direction) { this.level = level; this.room = room; this.charBlockX = location % 10; this.charBlockY = Math.floor(location / 10); let x = PrinceJS.Utils.convertBlockXtoX(this.charBlockX); let y = PrinceJS.Utils.convertBlockYtoY(this.charBlockY); PrinceJS.Actor.call(this, game, x, y, direction, "mouse"); this.action = "stop"; this.updateBase(); }; PrinceJS.Mouse.prototype = Object.create(PrinceJS.Actor.prototype); PrinceJS.Mouse.prototype.constructor = PrinceJS.Mouse; PrinceJS.Mouse.prototype.updateActor = function () { this.processCommand(); this.checkButton(); this.updateCharPosition(); }; PrinceJS.Mouse.prototype.CMD_FRAME = function (data) { this.charFrame = data.p1; this.updateCharFrame(); this.updateBlockXY(); this.processing = false; }; PrinceJS.Mouse.prototype.updateBlockXY = function () { let footX = this.charX + this.charFdx * this.charFace - this.charFfoot * this.charFace; let footY = this.charY + this.charFdy; this.charBlockX = PrinceJS.Utils.convertXtoBlockX(footX); this.charBlockY = Math.min(PrinceJS.Utils.convertYtoBlockY(footY), 2); }; PrinceJS.Mouse.prototype.updateBase = function () { this.baseX = this.level.rooms[this.room].x * PrinceJS.ROOM_WIDTH; this.baseY = this.level.rooms[this.room].y * PrinceJS.ROOM_HEIGHT + 3; }; PrinceJS.Mouse.prototype.checkButton = function () { if (!this.visible) { return; } let tile = this.level.getTileAt(this.charBlockX, this.charBlockY, this.room); if (tile) { switch (tile.element) { case PrinceJS.Level.TILE_RAISE_BUTTON: case PrinceJS.Level.TILE_DROP_BUTTON: tile.push(); break; } } }; PrinceJS.Mouse.prototype.turn = function () { this.changeFace(); this.charX += this.charFace * 5; }; PK �Zh�� � Cutscene.jsnu �[��� "use strict"; PrinceJS.Cutscene = function (game) { this.scene; }; PrinceJS.Cutscene.STATE_SETUP = 0; PrinceJS.Cutscene.STATE_READY = 1; PrinceJS.Cutscene.STATE_WAITING = 2; PrinceJS.Cutscene.STATE_RUNNING = 3; PrinceJS.Cutscene.prototype = { preload: function () { this.game.load.image("cover", "assets/gfx/cover.png"); switch (PrinceJS.currentLevel) { case 1: this.game.load.audio("Princess", "assets/music/03_Princess.mp3"); this.game.load.audio("Jaffar", "assets/music/04_Jaffar.mp3"); this.game.load.audio("Heartbeat", "assets/music/05_Heartbeat.mp3"); break; case 2: case 4: case 6: case 12: this.game.load.audio("Heartbeat2", "assets/music/12_Heartbeat_2.mp3"); break; case 8: case 9: this.game.load.audio("Timer", "assets/music/17_Timer.mp3"); break; case 15: this.game.load.audio("Embrace", "assets/music/21_Embrace.mp3"); break; case 16: this.game.load.audio("TragicEnd", "assets/music/18_Tragic_End.mp3"); break; } this.load.json("cutscene", "assets/cutscenes/scene" + PrinceJS.currentLevel + ".json"); }, create: function () { this.reset(); let cutscene = this.game.cache.getJSON("cutscene"); if (!cutscene) { this.next(); return; } this.program = cutscene.program; this.scene = new PrinceJS.Scene(this.game); this.cover = this.game.add.sprite(0, 0, "cover"); this.scene.front.addChild(this.cover); this.executeProgram(); this.input.keyboard.onDownCallback = null; PrinceJS.Utils.delayed(() => { this.input.keyboard.onDownCallback = this.continue.bind(this); }, 1000); this.game.time.events.loop(120, this.updateScene, this); }, executeProgram: function () { if (this.sceneState === PrinceJS.Cutscene.STATE_WAITING) { this.waitingTime--; if (this.waitingTime === 0) { this.sceneState = PrinceJS.Cutscene.STATE_READY; } return; } while (this.sceneState === PrinceJS.Cutscene.STATE_SETUP || this.sceneState === PrinceJS.Cutscene.STATE_RUNNING) { let opcode = this.program[this.pc]; let actor; switch (opcode.i) { case "START": this.world.sort("z"); this.sceneState = PrinceJS.Cutscene.STATE_READY; if (opcode.p1 === 0) { this.fadeOut(1); } else { this.fadeIn(); } break; case "END": this.endCutscene(opcode.p1 !== 0); this.sceneState = PrinceJS.Cutscene.STATE_WAITING; this.waitingTime = 1000; break; case "ACTION": actor = this.actors[opcode.p1]; actor.action = opcode.p2; break; case "ADD_ACTOR": actor = new PrinceJS.Actor(this.game, opcode.p3, opcode.p4, opcode.p5, opcode.p2); this.actors[opcode.p1] = actor; break; case "REM_ACTOR": this.actors[opcode.p1].kill(); break; case "ADD_OBJECT": this.objects[opcode.p1] = new PrinceJS.Tile.Clock(this.game, opcode.p3, opcode.p4, opcode.p2); this.scene.addObject(this.objects[opcode.p1]); break; case "START_OBJECT": this.objects[opcode.p1].activate(); break; case "EFFECT": this.scene.effect(); break; case "WAIT": this.sceneState = PrinceJS.Cutscene.STATE_WAITING; this.waitingTime = opcode.p1; break; case "MUSIC": this.stopMusic(); this.game.sound.play(opcode.p2); break; case "SOUND": this.game.sound.play(opcode.p2); break; case "FADEIN": this.fadeIn(opcode.p1 * 120); break; case "FADEOUT": this.fadeOut(opcode.p1 * 120); break; } this.pc++; } }, update: function () { if (PrinceJS.Utils.continueGame(this.game)) { this.continue(); } }, updateScene: function () { if (this.sceneState === PrinceJS.Cutscene.STATE_RUNNING) { return; } else if (this.sceneState === PrinceJS.Cutscene.STATE_READY) { this.sceneState = PrinceJS.Cutscene.STATE_RUNNING; } this.executeProgram(); this.scene.update(); for (let i = 0; i < this.actors.length; i++) { this.actors[i].updateActor(); } }, endCutscene: function (fadeOut = true) { if (fadeOut) { this.fadeOut(2000, () => { this.next(); }); } else { this.next(); } }, continue: function () { if (PrinceJS.currentLevel < 15) { this.play(); } else { this.next(); } }, play: function () { this.stopMusic(); this.input.keyboard.onDownCallback = null; this.state.start("Game"); }, next: function () { this.input.keyboard.onDownCallback = null; if (PrinceJS.currentLevel === 1) { this.state.start("Credits"); } else if (PrinceJS.currentLevel === 15) { PrinceJS.Restart(); this.state.start("EndTitle"); } else if (PrinceJS.currentLevel === 16) { PrinceJS.Restart(); this.state.start("Title"); } else { this.play(); } }, reset: function () { this.actors = []; this.objects = []; this.pc = 0; this.waitingTime = 0; this.sceneState = PrinceJS.Cutscene.STATE_SETUP; }, stopMusic: function () { this.game.sound.stopAll(); }, fadeIn: function (duration = 2000, callback) { this.game.add.tween(this.cover).to({ alpha: 0 }, 2000, Phaser.Easing.Linear.None, true, 0, 0, false); PrinceJS.Utils.delayed(() => { if (callback) { callback(); } }, duration); }, fadeOut: function (duration = 2000, callback) { this.game.add.tween(this.cover).to({ alpha: 1 }, 2000, Phaser.Easing.Linear.None, true, 0, 0, false); PrinceJS.Utils.delayed(() => { if (callback) { callback(); } }, duration); } }; PK �Z)pv�} } Boot.jsnu �[��� "use strict"; let PrinceJS = {}; PrinceJS.SCALE_FACTOR = 2; PrinceJS.SCREEN_WIDTH = 320; PrinceJS.SCREEN_HEIGHT = 200; PrinceJS.WORLD_WIDTH = PrinceJS.SCREEN_WIDTH * PrinceJS.SCALE_FACTOR; PrinceJS.WORLD_HEIGHT = PrinceJS.SCREEN_HEIGHT * PrinceJS.SCALE_FACTOR; PrinceJS.WORLD_RATIO = PrinceJS.WORLD_WIDTH / PrinceJS.WORLD_HEIGHT; PrinceJS.BLOCK_WIDTH = 32; PrinceJS.BLOCK_HEIGHT = 63; PrinceJS.ROOM_HEIGHT = PrinceJS.BLOCK_HEIGHT * 3; PrinceJS.ROOM_WIDTH = PrinceJS.SCREEN_WIDTH; PrinceJS.UI_HEIGHT = 8; PrinceJS.SKIP_TITLE = false; PrinceJS.SKIP_CUTSCENES = false; PrinceJS.Init = function () { PrinceJS.currentLevel = 1; PrinceJS.maxHealth = 3; PrinceJS.currentHealth = null; PrinceJS.minutes = 60; PrinceJS.startTime = undefined; PrinceJS.endTime = undefined; PrinceJS.strength = 100; PrinceJS.screenWidth = 0; PrinceJS.shortcut = false; PrinceJS.danger = null; PrinceJS.skipShowLevel = false; }; PrinceJS.Gamepad = { A: 0, B: 1, X: 2, Y: 3, L: 4, R: 5, ZL: 6, ZR: 7, Minus: 8, Plus: 9, DPadU: 12, DPadD: 13, DPadL: 14, DPadR: 15, Axis: { LX: 0, LY: 1, RX: 2, RY: 3 } }; PrinceJS.Restart = function () { PrinceJS.Utils.clearQuery(); PrinceJS.Init(); PrinceJS.Utils.applyQuery(); }; PrinceJS.Boot = function () { PrinceJS.Init(); }; PrinceJS.Boot.prototype = { preload: function () { this.load.bitmapFont("font", "assets/font/prince_0.png", "assets/font/prince.fnt"); }, create: function () { this.world.scale.set(PrinceJS.SCALE_FACTOR); this.state.start("Preloader"); PrinceJS.Utils.applyQuery(); PrinceJS.Utils.applyScreenWidth(); } }; PK �Z�C��� � Scene.jsnu �[��� "use strict"; PrinceJS.Scene = function (game) { this.game = game; this.back = this.game.add.group(); this.back.z = 10; this.front = this.game.add.group(); this.front.z = 30; this.trobs = []; this.flash = false; this.tick = 0; this._build(); }; PrinceJS.Scene.prototype = { _build: function () { this.game.add.image(0, 0, "cutscene", "room", this.back); this.game.add.image(0, 142, "cutscene", "room_bed", this.back); let torchPos = [ { x: 53, y: 81 }, { x: 171, y: 81 } ]; let i; for (i = 0; i < torchPos.length; i++) { let torch = new PrinceJS.Tile.Torch(this.game, PrinceJS.Level.TILE_TORCH, 0, PrinceJS.Level.TYPE_PALACE); torch.x = torchPos[i].x; torch.y = torchPos[i].y; torch.back.frameName = "palace_0"; this.addObject(torch); } let starPos = [ { x: 20, y: 97 }, { x: 16, y: 104 }, { x: 23, y: 110 }, { x: 17, y: 116 }, { x: 24, y: 120 }, { x: 18, y: 128 } ]; for (i = 0; i < starPos.length; i++) { let star = new PrinceJS.Tile.Star(this.game, starPos[i].x, starPos[i].y); this.addObject(star); } this.game.add.image(59, 120, "cutscene", "room_pillar", this.front); this.game.add.image(240, 120, "cutscene", "room_pillar", this.front); }, addTrob: function (trob) { this.trobs.push(trob); }, update: function () { let i = this.trobs.length; while (i--) { this.trobs[i].update(); } if (this.flash) { if (this.tick === 7) { this.flash = false; return; } if (this.tick % 2) { this.game.stage.backgroundColor = "#FFFFFF"; } else { this.game.stage.backgroundColor = "#000000"; } this.tick++; } }, effect: function () { this.flash = true; }, addObject: function (object) { this.back.add(object.back); this.addTrob(object); } }; PrinceJS.Scene.prototype.constructor = PrinceJS.Scene; PK �Z�Wv v Title.jsnu �[��� "use strict"; PrinceJS.Title = function (game) { this.tick = 0; }; PrinceJS.Title.prototype = { preload: function () {}, create: function () { this.stopMusic(); this.tick = 0; this.game.world.setBounds(0, 0, PrinceJS.SCREEN_WIDTH, PrinceJS.SCREEN_HEIGHT); this.back = this.game.add.image(0, 0, "title", "main_background"); this.back.alpha = 0; this.tween1 = this.game.add.tween(this.back).to({ alpha: 1 }, 2000, Phaser.Easing.Linear.None, false, 0, 0, false); this.tween1.onComplete.add(() => { this.game.sound.play("PrologueA"); }); this.presents = this.game.add.image(this.world.centerX, this.world.centerY + 29.5, "title", "presents"); this.presents.anchor.setTo(0.5, 0.5); this.presents.visible = false; this.author = this.game.add.image(this.world.centerX - 3, this.world.centerY + 37, "title", "author"); this.author.anchor.setTo(0.5, 0.5); this.author.visible = false; this.prince = this.game.add.image(0, 0, "title", "prince"); this.prince.visible = false; this.textBack = this.game.add.image(0, this.world.height, "title", "in_the_absence"); this.textBack.anchor.setTo(0, 1); this.cropRect = new Phaser.Rectangle(0, 0, 0, this.textBack.height); this.tween2 = this.game.add .tween(this.cropRect) .to({ width: this.textBack.width }, 200, Phaser.Easing.Linear.None, false, 0, 0, false); this.textBack.crop(this.cropRect); this.tween3 = this.game.add .tween(this.textBack) .to({ alpha: 0 }, 2000, Phaser.Easing.Linear.None, false, 0, 0, false); this.tween3.onComplete.add(() => { PrinceJS.Utils.delayed(() => { this.cutscene(); }, 3500); }); this.input.keyboard.onDownCallback = this.play.bind(this); }, update: function () { switch (this.tick) { case 0: this.tween1.start(); break; case 250: this.presents.visible = true; break; case 450: this.presents.visible = false; break; case 530: this.author.visible = true; break; case 730: this.author.visible = false; break; case 1030: this.prince.visible = true; break; case 1600: this.tween2.start(); this.game.sound.play("PrologueB"); break; case 2250: this.back.visible = false; this.prince.visible = false; this.tween3.start(); break; } this.tick++; this.textBack.updateCrop(); if (PrinceJS.Utils.continueGame(this.game)) { this.play(); } }, play: function () { this.stopMusic(); this.input.keyboard.onDownCallback = null; this.state.start("Game"); }, cutscene: function () { this.stopMusic(); this.input.keyboard.onDownCallback = null; this.state.start("Cutscene"); }, stopMusic: function () { this.game.sound.stopAll(); } }; PK �Z�x'�&