import { ContextI } from "../ContextI" import { segments } from "../shared/segments" import { StateI } from "./StateI" import * as PIXI from 'pixi.js' import { DecorationInstance } from "../shared/decors" import { SpriteInstance } from "../shared/sprites" interface Action { type: string priority: number } class Entity { sprite: SpriteInstance constructor(ctor: string) { this.sprite = new SpriteInstance(ctor) } update(delta: number) { // TODO: Update sprite. } get x(): number { return this.sprite.container.x } set x(v: number) { this.sprite.container.x = v } get y(): number { return this.sprite.container.y } set y(v: number) { this.sprite.container.y = v } } class PlayerEntity extends Entity { action?: Action constructor(ctor: string) { super(ctor) this.x = 100 this.y = 100 // TODO: Hooks for key state check input, perhaps? } act(actions: Action[]) { this.action = actions.sort((a, b) => { if (a.priority < b.priority) { return -1 } if (a.priority > b.priority) { return 1 } return 0 })[0] } update(delta: number) { if (this.action) { // FIXME: Use physics. switch(this.action.type) { case 'west': this.x-- break case 'east': this.x++ break case 'north': this.y-- break case 'south': this.y++ break } } } } function isPlayerEntity(o: any): o is PlayerEntity { return o.act } export function GameState(ctx: ContextI): StateI { let rootContainer = new PIXI.Container() let decorations: DecorationInstance[] = [] let entities: Entity[] = [] let enter = () => { hookKeyboard() // Load the world segment. let w = segments.world if (!w) return ctx.pop() rootContainer.width = w.width rootContainer.height = w.height rootContainer.scale.set(2, 2) for (let l of w.layers) { let container = new PIXI.Container() container.width = w.width container.height = w.height for (let d of l.decorations) { let di = new DecorationInstance(d.decor, d.decoration) di.elapsed = d.timeOffset di.container.x = d.x di.container.y = d.y if (d.flip) { di.container.pivot.y = 1 di.container.scale.y *= -1 di.container.position.y-- } if (d.mirror) { di.container.pivot.x = 1 di.container.scale.x *= -1 di.container.position.x-- } container.addChild(di.container) decorations.push(di) } rootContainer.addChild(container) } // Add bogus entity addEntity(new PlayerEntity('animals.deer.animal.west.0')) ctx.app.stage.addChild(rootContainer) } let leave = () => { unhookKeyboard() for (let entity of entities) { removeEntity(entity) } ctx.app.stage.removeChild(rootContainer) } let update = (delta: number) => { for (let decoration of decorations) { decoration.update(delta) } for (let entity of entities) { if (isPlayerEntity(entity)) { entity.act(desiredActions) // FIXME: This isn't the right place for this. rootContainer.position.set(Math.round(ctx.app.renderer.width/2), Math.round(ctx.app.renderer.height/2)) rootContainer.pivot.set(entity.x, entity.y) } entity.update(delta) } } let addEntity = (entity: Entity) => { if (entities.find(v=>v===entity)) return entities.push(entity) rootContainer.addChild(entity.sprite.container) } let removeEntity = (entity: Entity) => { entities = entities.filter(v=>v!==entity) rootContainer.removeChild(entity.sprite.container) } let desiredActions: Action[] = [] let adjustAction = (type: string, v: number) => { let action = desiredActions.find(v=>v.type===type) if (!action) { desiredActions.push({ type: type, priority: v, }) } else { action.priority += v if (action.priority <= 0) { desiredActions = desiredActions.filter(v=>v!==action) } } } let keyup = (e: KeyboardEvent) => { if (e.key === 'ArrowLeft') { adjustAction('west', -1) } else if (e.key === 'ArrowRight') { adjustAction('east', -1) } else if (e.key === 'ArrowUp') { adjustAction('north', -1) } else if (e.key === 'ArrowDown') { adjustAction('south', -1) } } let keydown = (e: KeyboardEvent) => { if (e.repeat) return if (e.key === 'ArrowLeft') { adjustAction('west', 1) } else if (e.key === 'ArrowRight') { adjustAction('east', 1) } else if (e.key === 'ArrowUp') { adjustAction('north', 1) } else if (e.key === 'ArrowDown') { adjustAction('south', 1) } } let hookKeyboard = () => { window.addEventListener('keyup', keyup) window.addEventListener('keydown', keydown) } let unhookKeyboard = () => { window.removeEventListener('keyup', keyup) window.removeEventListener('keydown', keydown) } return { enter, leave, update, } }