diff --git a/src/shattered_sword/Player/PlayerController.ts b/src/shattered_sword/Player/PlayerController.ts index 5f2111d..a9373d4 100644 --- a/src/shattered_sword/Player/PlayerController.ts +++ b/src/shattered_sword/Player/PlayerController.ts @@ -3,6 +3,23 @@ import GameNode, { TweenableProperties } from "../../Wolfie2D/Nodes/GameNode"; import Vec2 from "../../Wolfie2D/DataTypes/Vec2"; import Sprite from "../../Wolfie2D/Nodes/Sprites/Sprite"; import OrthogonalTilemap from "../../Wolfie2D/Nodes/Tilemaps/OrthogonalTilemap"; +import { Player_Events } from "../sword_enums"; +import Fall from "./PlayerStates/Fall"; +import Idle from "./PlayerStates/Idle"; +import InAir from "./PlayerStates/InAir"; +import Jump from "./PlayerStates/Jump"; +import Walk from "./PlayerStates/Walk"; +import Debug from "../../Wolfie2D/Debug/Debug"; + + +export enum PlayerStates { + IDLE = "idle", + WALK = "walk", + RUN = "run", + JUMP = "jump", + FALL = "fall", + PREVIOUS = "previous" +} export enum BuffType { ATK = "attack", @@ -22,6 +39,9 @@ type Buffs = [ export default class PlayerController extends StateMachineAI { protected owner: GameNode; + velocity: Vec2 = Vec2.ZERO; + speed: number = 200; + MIN_SPEED: number = 200; MAX_SPEED: number = 300; BASE_HP: number = 100; MAX_HP: number = 100; @@ -32,6 +52,7 @@ export default class PlayerController extends StateMachineAI { BASE_DEF: number = 100; MAX_DEF: number = 100; CURRENT_DEF: number = 100; + tilemap: OrthogonalTilemap; CURRENT_BUFFS: { atk: 0; @@ -39,8 +60,8 @@ export default class PlayerController extends StateMachineAI { def: 0; speed: 0; } - velocity: Vec2 = Vec2.ZERO; - tilemap: OrthogonalTilemap; + + /** * Returns three legal random generate buffs based on current state @@ -58,4 +79,55 @@ export default class PlayerController extends StateMachineAI { setBuff(buff: Buff): void { // TODO } + + //TODO - get the correct tilemap + initializeAI(owner: GameNode, options: Record){ + this.owner = owner; + + this.initializePlatformer(); + + this.tilemap = this.owner.getScene().getTilemap(options.tilemap) as OrthogonalTilemap; + + + } + + initializePlatformer(): void { + this.speed = 400; + + let idle = new Idle(this, this.owner); + this.addState(PlayerStates.IDLE, idle); + let walk = new Walk(this, this.owner); + this.addState(PlayerStates.WALK, walk); + let jump = new Jump(this, this.owner); + this.addState(PlayerStates.JUMP, jump); + let fall = new Fall(this, this.owner); + this.addState(PlayerStates.FALL, fall); + + this.initialize(PlayerStates.IDLE); + } + + changeState(stateName: string): void { + // If we jump or fall, push the state so we can go back to our current state later + // unless we're going from jump to fall or something + if((stateName === PlayerStates.JUMP || stateName === PlayerStates.FALL) && !(this.stack.peek() instanceof InAir)){ + this.stack.push(this.stateMap.get(stateName)); + } + + super.changeState(stateName); + } + + update(deltaT: number): void { + super.update(deltaT); + + if(this.currentState instanceof Jump){ + Debug.log("playerstate", "Player State: Jump"); + } else if (this.currentState instanceof Walk){ + Debug.log("playerstate", "Player State: Walk"); + } else if (this.currentState instanceof Idle){ + Debug.log("playerstate", "Player State: Idle"); + } else if(this.currentState instanceof Fall){ + Debug.log("playerstate", "Player State: Fall"); + } + + } } \ No newline at end of file diff --git a/src/shattered_sword/Player/PlayerStates/Fall.ts b/src/shattered_sword/Player/PlayerStates/Fall.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/shattered_sword/Player/PlayerStates/Idle.ts b/src/shattered_sword/Player/PlayerStates/Idle.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/shattered_sword/Player/PlayerStates/InAir.ts b/src/shattered_sword/Player/PlayerStates/InAir.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/shattered_sword/Player/PlayerStates/Jump.ts b/src/shattered_sword/Player/PlayerStates/Jump.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/shattered_sword/Player/PlayerStates/OnGround.ts b/src/shattered_sword/Player/PlayerStates/OnGround.ts new file mode 100644 index 0000000..f421dd8 --- /dev/null +++ b/src/shattered_sword/Player/PlayerStates/OnGround.ts @@ -0,0 +1,35 @@ +import GameEvent from "../../../Wolfie2D/Events/GameEvent"; +import Input from "../../../Wolfie2D/Input/Input"; +import Sprite from "../../../Wolfie2D/Nodes/Sprites/Sprite"; +import MathUtils from "../../../Wolfie2D/Utils/MathUtils"; +import PlayerState from "./PlayerState"; + +export default class OnGround extends PlayerState { + onEnter(options: Record): void {} + + update(deltaT: number): void { + if(this.parent.velocity.y > 0){ + this.parent.velocity.y = 0; + } + super.update(deltaT); + + let direction = this.getInputDirection(); + + if(direction.x !== 0){ + (this.owner).invertX = MathUtils.sign(direction.x) < 0; + } + + // If we jump, move to the Jump state, give a burst of upwards velocity + if(Input.isJustPressed("jump")){ + this.finished("jump"); + this.parent.velocity.y = -500; + + } else if(!this.owner.onGround){ + this.finished("fall"); + } + } + + onExit(): Record { + return {}; + } +} \ No newline at end of file diff --git a/src/shattered_sword/Player/PlayerStates/PlayerState.ts b/src/shattered_sword/Player/PlayerStates/PlayerState.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/shattered_sword/Player/PlayerStates/Walk.ts b/src/shattered_sword/Player/PlayerStates/Walk.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/shattered_sword/Scenes/GameLevel.ts b/src/shattered_sword/Scenes/GameLevel.ts new file mode 100644 index 0000000..d275123 --- /dev/null +++ b/src/shattered_sword/Scenes/GameLevel.ts @@ -0,0 +1,229 @@ +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 Input from "../../Wolfie2D/Input/Input"; +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 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 { Player_Events } from "../sword_enums"; + +// 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; + + startScene(): void { + + // Do the game level standard initializations + this.initLayers(); + this.initViewport(); + this.initPlayer(); + this.subscribeToEvents(); + this.addUI(); + + // 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"); + + // Initially disable player movement + Input.disableInput(); + } + + + updateScene(deltaT: number){ + // Handle events and update the UI if needed + while(this.receiver.hasNextEvent()){ + let event = this.receiver.getNextEvent(); + + switch(event.type){ + + } + } + + } + + /** + * 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); + } + + /** + * 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 + ]); + } + + // TODO - + /** + * Adds in any necessary UI to the game + */ + protected addUI(){ + // In-game labels + + // End of level label (start off screen) + this.levelEndLabel =