2022-01-29 01:37:01 -08:00
|
|
|
import { ContextI } from "../ContextI"
|
2022-01-29 03:44:34 -08:00
|
|
|
import { segments } from "../shared/segments"
|
2022-01-29 01:37:01 -08:00
|
|
|
import { StateI } from "./StateI"
|
2022-01-29 03:44:34 -08:00
|
|
|
import * as PIXI from 'pixi.js'
|
|
|
|
import { DecorationInstance } from "../shared/decors"
|
2022-01-29 04:57:01 -08:00
|
|
|
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
|
|
|
|
}
|
2022-01-29 01:37:01 -08:00
|
|
|
|
|
|
|
export function GameState(ctx: ContextI): StateI {
|
|
|
|
|
2022-01-29 03:44:34 -08:00
|
|
|
let rootContainer = new PIXI.Container()
|
|
|
|
let decorations: DecorationInstance[] = []
|
2022-01-29 04:57:01 -08:00
|
|
|
let entities: Entity[] = []
|
2022-01-29 03:44:34 -08:00
|
|
|
|
2022-01-29 01:37:01 -08:00
|
|
|
let enter = () => {
|
2022-01-29 04:57:01 -08:00
|
|
|
hookKeyboard()
|
2022-01-29 03:44:34 -08:00
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2022-01-29 04:57:01 -08:00
|
|
|
// Add bogus entity
|
|
|
|
addEntity(new PlayerEntity('animals.deer.animal.west.0'))
|
|
|
|
|
2022-01-29 03:44:34 -08:00
|
|
|
ctx.app.stage.addChild(rootContainer)
|
2022-01-29 01:37:01 -08:00
|
|
|
}
|
|
|
|
let leave = () => {
|
2022-01-29 04:57:01 -08:00
|
|
|
unhookKeyboard()
|
|
|
|
for (let entity of entities) {
|
|
|
|
removeEntity(entity)
|
|
|
|
}
|
2022-01-29 03:44:34 -08:00
|
|
|
ctx.app.stage.removeChild(rootContainer)
|
2022-01-29 01:37:01 -08:00
|
|
|
}
|
|
|
|
let update = (delta: number) => {
|
2022-01-29 03:44:34 -08:00
|
|
|
for (let decoration of decorations) {
|
|
|
|
decoration.update(delta)
|
|
|
|
}
|
2022-01-29 04:57:01 -08:00
|
|
|
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))
|
2022-01-29 05:18:51 -08:00
|
|
|
rootContainer.pivot.set(Math.max(rootContainer.width/6, Math.min(entity.x, rootContainer.width/3)), Math.max(rootContainer.height/6, Math.min(entity.y, rootContainer.height/3)))
|
2022-01-29 04:57:01 -08:00
|
|
|
}
|
|
|
|
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)
|
2022-01-29 01:37:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
enter,
|
|
|
|
leave,
|
|
|
|
update,
|
|
|
|
}
|
|
|
|
}
|