import AABB from "../../Wolfie2D/DataTypes/Shapes/AABB"; import Vec2 from "../../Wolfie2D/DataTypes/Vec2"; import Debug from "../../Wolfie2D/Debug/Debug"; import { GameEventType } from "../../Wolfie2D/Events/GameEventType"; import { TweenableProperties } from "../../Wolfie2D/Nodes/GameNode"; import { GraphicType } from "../../Wolfie2D/Nodes/Graphics/GraphicTypes"; import Point from "../../Wolfie2D/Nodes/Graphics/Point"; import Rect from "../../Wolfie2D/Nodes/Graphics/Rect"; import AnimatedSprite from "../../Wolfie2D/Nodes/Sprites/AnimatedSprite"; import Label, { HAlign } from "../../Wolfie2D/Nodes/UIElements/Label"; import { UIElementType } from "../../Wolfie2D/Nodes/UIElements/UIElementTypes"; import Scene from "../../Wolfie2D/Scene/Scene"; import Timer from "../../Wolfie2D/Timing/Timer"; import Color from "../../Wolfie2D/Utils/Color"; import { EaseFunctionType } from "../../Wolfie2D/Utils/EaseFunctions"; import PlayerController from "../Player/PlayerController"; import MainMenu from "./MainMenu"; import { GameState, Player_Events, Statuses } from "../sword_enums"; import RegistryManager from "../../Wolfie2D/Registry/RegistryManager"; import WeaponType from "../GameSystems/items/WeaponTypes/WeaponType"; import Weapon from "../GameSystems/items/Weapon"; import BattleManager from "../GameSystems/BattleManager"; import EnemyAI from "../AI/EnemyAI"; import BattlerAI from "../AI/BattlerAI"; import InventoryManager from "../GameSystems/InventoryManager"; import Item from "../GameSystems/items/Item"; import Layer from "../../Wolfie2D/Scene/Layer"; import Button from "../../Wolfie2D/Nodes/UIElements/Button"; import { Buff } from "../Player/PlayerController"; import CanvasNode from "../../Wolfie2D/Nodes/CanvasNode"; import { Enemy } from "../Tools/RandomMapGenerator"; import Stack from "../../Wolfie2D/DataTypes/Stack"; import InputWrapper from "../Tools/InputWrapper"; import Story from "../Tools/DataTypes/Story"; import Sprite from "../../Wolfie2D/Nodes/Sprites/Sprite"; // TODO /** * Add in some level music. * This can be done here in the base GameLevel class or individual level files */ export default class GameLevel extends Scene { // Every level will have a player, which will be an animated sprite protected playerSpawn: Vec2; protected player: AnimatedSprite; protected respawnTimer: Timer; // Labels for the UI protected static livesCount: number = 3; protected livesCountLabel: Label; // Stuff to end the level and go to the next level protected levelEndArea: Rect; protected nextLevel: new (...args: any) => GameLevel; protected levelEndTimer: Timer; protected levelEndLabel: Label; // Screen fade in/out for level start and end protected levelTransitionTimer: Timer; protected levelTransitionScreen: Rect; // The battle manager for the scene protected battleManager: BattleManager; // Health UI protected healthLabel: Label; //may need exp label //may need mp label //seed UI protected seedLabel: Label; // A list of items in the scene protected items: Array; // A list of enemies protected enemies: Array; protected gameStateStack: Stack; // Story private storytextLabel: Label; private storyLayer: Layer; private story: Story; private storyProgress: number; private storySprites: Array; private storyBGMs: Array; private currentSpeaker: string; private currentContent: string; //buffs layer buffLayer: Layer; buffButton1 : Button; buffButton2 : Button; buffButton3 : Button; buffs: Array; randomSeed: number; loadScene(): void { //can load player sprite here //can load enemy sprite here //sprites obtained from cse380 sprite wesbite this.load.spritesheet("Tiger","shattered_sword_assets/spritesheets/Tiger.json"); this.load.spritesheet("remus_werewolf","shattered_sword_assets/spritesheets/remus_werewolf.json"); this.load.spritesheet("black_pudding","shattered_sword_assets/spritesheets/black_pudding.json"); // Load the scene info this.load.object("weaponData", "shattered_sword_assets/data/weaponData.json"); // Load in the enemy info //this.load.object("enemyData", "shattered_sword_assets/data/enemy.json"); // Load in item info //this.load.object("itemData", "shattered_sword_assets/data/items.json"); this.load.image("knife", "shattered_sword_assets/sprites/knife.png"); this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json"); this.load.image("inventorySlot", "shattered_sword_assets/sprites/inventory.png"); this.load.spritesheet("test_dummy","shattered_sword_assets/spritesheets/test_dummy.json") this.enemies = new Array(); this.battleManager = new BattleManager(); } startScene(): void { //call super after extending story with scene // Do the game level standard initializations this.initViewport(); this.initLayers(); // Create the battle manager // TODO this.initializeWeapons(); // Initialize the items array - this represents items that are in the game world this.items = new Array(); this.initPlayer(); //subscribe to relevant events this.subscribeToEvents(); this.addUI(); // Create an enemies array // Send the player and enemies to the battle manager this.battleManager.setPlayers([this.player._ai]); // Initialize all enemies //this.initializeEnemies(); this.battleManager.setEnemies(this.enemies.map(enemy => enemy._ai)); // Initialize the timers this.respawnTimer = new Timer(1000, () => { if(GameLevel.livesCount === 0){ this.sceneManager.changeToScene(MainMenu); } else { this.respawnPlayer(); this.player.enablePhysics(); this.player.unfreeze(); } }); /* this.levelTransitionTimer = new Timer(500); this.levelEndTimer = new Timer(3000, () => { // After the level end timer ends, fade to black and then go to the next scene this.levelTransitionScreen.tweens.play("fadeIn"); }); */ // Start the black screen fade out /* this.levelTransitionScreen.tweens.play("fadeOut"); */ //TODO - uncomment when done testing // Initially disable player movement //Input.disableInput(); this.gameStateStack = new Stack(); this.setGameState(GameState.GAMING); InputWrapper.enableInput(); } updateScene(deltaT: number){ // Handle events and update the UI if needed while(this.receiver.hasNextEvent()){ let event = this.receiver.getNextEvent(); if (this.gameStateStack.peek() === GameState.GAMING) { switch(event.type){ case Player_Events.ENEMY_KILLED: let node = this.sceneGraph.getNode(event.data.get("owner"));//get enemy id //remove enemy from enemies this.enemies = this.enemies.filter(item => item !== event.data.get("ai")); this.battleManager.removeEnemy(event.data.get("ai")); node.destroy(); //TODO - this is for testing, add some chance here later this.emitter.fireEvent(Player_Events.GIVE_BUFF); break; case Player_Events.GIVE_BUFF: this.buffs = PlayerController.generateBuffs(); this.buffButton1.text = "Increase "+this.buffs[0].type.toString() + " by "+this.buffs[0].value; this.buffButton2.text = "Increase "+this.buffs[1].type + " by "+this.buffs[1].value; this.buffButton3.text = "Increase "+this.buffs[2].type + " by "+this.buffs[2].value; //pause game here this.setGameState(GameState.BUFF); this.buffLayer.enable(); break; } } else if (this.gameStateStack.peek() === GameState.BUFF) { switch(event.type){ case "buff1": (this.player._ai).addBuff(this.buffs[0]); this.buffLayer.disable(); this.setGameState(); break; case "buff2": (this.player._ai).addBuff(this.buffs[1]); this.buffLayer.disable(); this.setGameState(); break; case "buff3": (this.player._ai).addBuff(this.buffs[2]); this.buffLayer.disable(); this.setGameState(); break; } } } if (this.gameStateStack.peek() === GameState.STORY) { if (InputWrapper.isNextJustPressed() && this.gameStateStack.peek() === GameState.STORY) { this.updateStory(); } } //update health UI let playerAI = (this.player.ai); this.healthLabel.text = "Player Health: "+ playerAI.CURRENT_HP +'/' + (playerAI.MAX_HP +playerAI.CURRENT_BUFFS.hp ); //handle collisions - may be in battle manager instead //move background // Get the viewport center and padded size const viewportCenter = this.viewport.getCenter().clone(); const baseViewportSize = this.viewport.getHalfSize().scaled(2); //check position of player this.playerFalloff(viewportCenter, baseViewportSize); //TODO - this is for testing if(InputWrapper.isSpawnJustPressed()){ console.log("trying to spawn enemy"); this.addEnemy("test_dummy",this.player.position,{player: this.player, health :100, tilemap: "Main", //actions:actions, goal: Statuses.REACHED_GOAL, }); } if (InputWrapper.isInventoryJustPressed()) { console.log("LoadingStory"); this.storyLoader("shattered_sword_assets/jsons/story.json"); } } // TODO put UI changes in here protected setGameState(gameState?: GameState) { if (gameState) { this.gameStateStack.push(gameState); InputWrapper.setState(gameState); } else { this.gameStateStack.pop(); InputWrapper.setState(this.gameStateStack.peek()); } } /** * Initialzes the layers */ protected initLayers(): void { // Add a layer for UI this.addUILayer("UI"); // Add a layer for players and enemies this.addLayer("primary", 1); this.buffLayer = this.addUILayer("buffLayer"); //TODO - test depth later, may be just a regular Layer this.storyLayer = this.addUILayer("story"); this.storyLayer.disable(); this.receiver.subscribe("loadStory"); } /** * Initializes the viewport */ protected initViewport(): void { this.viewport.setZoomLevel(2); } /** * Handles all subscriptions to events */ protected subscribeToEvents(){ this.receiver.subscribe([ Player_Events.PLAYER_HIT_ENEMY, Player_Events.ENEMY_KILLED, Player_Events.LEVEL_START, Player_Events.LEVEL_END, Player_Events.PLAYER_KILLED, Player_Events.GIVE_BUFF, ]); this.receiver.subscribe("buff1"); this.receiver.subscribe("buff2"); this.receiver.subscribe("buff3"); } // TODO - /** * Adds in any necessary UI to the game */ protected addUI(){ // In-game labels this.healthLabel =