Too many changes
This commit is contained in:
parent
a87d44aa82
commit
581da1473d
|
@ -1,5 +1,7 @@
|
||||||
import * as planck from 'planck'
|
import * as planck from 'planck'
|
||||||
import { SpriteInstance } from '../shared/sprites'
|
import { SpriteInstance } from '../shared/sprites'
|
||||||
|
import { WorldContext } from './World'
|
||||||
|
import { Zone } from './Zone'
|
||||||
|
|
||||||
export class Entity {
|
export class Entity {
|
||||||
sprite: SpriteInstance
|
sprite: SpriteInstance
|
||||||
|
@ -9,13 +11,15 @@ export class Entity {
|
||||||
maxSpeed: number = 4
|
maxSpeed: number = 4
|
||||||
direction: number = 0
|
direction: number = 0
|
||||||
turnRate: number = 10
|
turnRate: number = 10
|
||||||
|
zones: Zone[] = []
|
||||||
|
contacts: Entity[] = []
|
||||||
|
|
||||||
constructor(ctor: string) {
|
constructor(ctor: string) {
|
||||||
this.sprite = new SpriteInstance(ctor)
|
this.sprite = new SpriteInstance(ctor)
|
||||||
}
|
}
|
||||||
|
|
||||||
update(delta: number) {
|
update(delta: number, ctx?: WorldContext) {
|
||||||
// TODO: Update sprite.
|
this.sprite.update(delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
get position(): [number, number] {
|
get position(): [number, number] {
|
||||||
|
@ -65,4 +69,18 @@ export class Entity {
|
||||||
this.sprite.container.y = v
|
this.sprite.container.y = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
addZoneContact(zone: Zone) {
|
||||||
|
if (this.zones.find(v=>v===zone)) return
|
||||||
|
this.zones.push(zone)
|
||||||
|
}
|
||||||
|
removeZoneContact(zone: Zone) {
|
||||||
|
this.zones = this.zones.filter(v=>v!==zone)
|
||||||
|
}
|
||||||
|
addEntityContact(entity: Entity) {
|
||||||
|
if (this.contacts.find(v=>v===entity)) return
|
||||||
|
this.contacts.push(entity)
|
||||||
|
}
|
||||||
|
removeEntityContact(entity: Entity) {
|
||||||
|
this.contacts = this.contacts.filter(v=>v!==entity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import * as planck from 'planck'
|
import * as planck from 'planck'
|
||||||
import { Action } from "./Action"
|
import { Action } from "./Action"
|
||||||
import { Entity } from "./Entity"
|
import { Entity } from "./Entity"
|
||||||
|
import { PuddleEntity } from './PuddleEntity'
|
||||||
|
import { WorldContext } from './World'
|
||||||
|
|
||||||
export class PlayerEntity extends Entity {
|
export class PlayerEntity extends Entity {
|
||||||
action?: Action
|
action?: Action
|
||||||
|
puddleTimer: number = 0
|
||||||
constructor(ctor: string) {
|
constructor(ctor: string) {
|
||||||
super(ctor)
|
super(ctor)
|
||||||
}
|
}
|
||||||
|
@ -18,10 +21,23 @@ export class PlayerEntity extends Entity {
|
||||||
return 0
|
return 0
|
||||||
})[0]
|
})[0]
|
||||||
}
|
}
|
||||||
update(delta: number) {
|
update(delta: number, ctx: WorldContext) {
|
||||||
|
super.update(delta)
|
||||||
|
|
||||||
|
let waterZones = this.zones.filter(v=>v.type==='fluid')
|
||||||
|
if (waterZones.length) {
|
||||||
|
this.puddleTimer += delta
|
||||||
|
if (this.puddleTimer >= 600) {
|
||||||
|
if (ctx) {
|
||||||
|
ctx.addEntity(new PuddleEntity('effects.water.ripple.small.0'), this.x, this.y)
|
||||||
|
console.log('add ripple')
|
||||||
|
}
|
||||||
|
this.puddleTimer = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let shouldMove = false
|
||||||
if (this.action) {
|
if (this.action) {
|
||||||
// FIXME: Use physics.
|
// FIXME: Use physics.
|
||||||
let shouldMove = false
|
|
||||||
switch(this.action.type) {
|
switch(this.action.type) {
|
||||||
case 'west':
|
case 'west':
|
||||||
if (this.direction !== 0) {
|
if (this.direction !== 0) {
|
||||||
|
@ -69,6 +85,8 @@ export class PlayerEntity extends Entity {
|
||||||
} else if (this.direction < 0) {
|
} else if (this.direction < 0) {
|
||||||
this.direction = 360
|
this.direction = 360
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldMove) {
|
if (shouldMove) {
|
||||||
let r = this.direction * (Math.PI/180)
|
let r = this.direction * (Math.PI/180)
|
||||||
if (Math.abs(this.velocity[0]) < this.maxSpeed) {
|
if (Math.abs(this.velocity[0]) < this.maxSpeed) {
|
||||||
|
@ -78,10 +96,15 @@ export class PlayerEntity extends Entity {
|
||||||
this.velocity[1] -= Math.sin(r) * this.acceleration
|
this.velocity[1] -= Math.sin(r) * this.acceleration
|
||||||
}
|
}
|
||||||
let cardinal = this.getCardinal()
|
let cardinal = this.getCardinal()
|
||||||
if (this.sprite.subsetKey !== cardinal) {
|
this.sprite.setKey = 'run'
|
||||||
|
if (this.sprite.subsetKey !== cardinal || this.sprite.subsetKey !== 'run') {
|
||||||
this.sprite.setCtor(`${this.sprite.spriteKey}.${this.sprite.animationKey}.${this.sprite.setKey}.${cardinal}.${this.sprite.frameIndex}`)
|
this.sprite.setCtor(`${this.sprite.spriteKey}.${this.sprite.animationKey}.${this.sprite.setKey}.${cardinal}.${this.sprite.frameIndex}`)
|
||||||
}
|
}
|
||||||
}
|
this.sprite.animate = true
|
||||||
|
} else {
|
||||||
|
this.sprite.animate = false
|
||||||
|
this.sprite.setKey = 'stand'
|
||||||
|
this.sprite.setCtor(`${this.sprite.spriteKey}.${this.sprite.animationKey}.${this.sprite.setKey}.${this.getCardinal()}.0`)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -92,25 +115,17 @@ export class PlayerEntity extends Entity {
|
||||||
this.body?.setLinearVelocity(planck.Vec2(this.velocity[0], this.velocity[1]))
|
this.body?.setLinearVelocity(planck.Vec2(this.velocity[0], this.velocity[1]))
|
||||||
}
|
}
|
||||||
getCardinal(): string {
|
getCardinal(): string {
|
||||||
const degreesPerDirection = 360 / 8
|
const degreesPerDirection = 360 / 4
|
||||||
const angle = this.direction + degreesPerDirection / 2
|
const angle = this.direction + degreesPerDirection / 2
|
||||||
|
|
||||||
if (angle >= 0 * degreesPerDirection && angle < 1 * degreesPerDirection) {
|
if (angle >= 0 * degreesPerDirection && angle < 1 * degreesPerDirection) {
|
||||||
return 'w'
|
return 'west'
|
||||||
} else if (angle >= 1 * degreesPerDirection && angle < 2 * degreesPerDirection) {
|
} else if (angle >= 1 * degreesPerDirection && angle < 2 * degreesPerDirection) {
|
||||||
return 'nw'
|
return 'north'
|
||||||
} else if (angle >= 2 * degreesPerDirection && angle < 3 * degreesPerDirection) {
|
} else if (angle >= 2 * degreesPerDirection && angle < 3 * degreesPerDirection) {
|
||||||
return 'n'
|
return 'east'
|
||||||
} else if (angle >= 3 * degreesPerDirection && angle < 4 * degreesPerDirection) {
|
|
||||||
return 'ne'
|
|
||||||
} else if (angle >= 4 * degreesPerDirection && angle < 5 * degreesPerDirection) {
|
|
||||||
return 'e'
|
|
||||||
} else if (angle >= 5 * degreesPerDirection && angle < 6 * degreesPerDirection) {
|
|
||||||
return 'se'
|
|
||||||
} else if (angle >= 6 * degreesPerDirection && angle < 7 * degreesPerDirection) {
|
|
||||||
return 's'
|
|
||||||
}
|
}
|
||||||
return 'sw'
|
return 'south'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
Engine/src/live/PuddleEntity.ts
Normal file
20
Engine/src/live/PuddleEntity.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { Entity } from "./Entity"
|
||||||
|
import { WorldContext } from "./World"
|
||||||
|
|
||||||
|
export class PuddleEntity extends Entity {
|
||||||
|
lifetime: number = 400
|
||||||
|
elapsed: number = 0
|
||||||
|
constructor(ctor: string) {
|
||||||
|
super(ctor)
|
||||||
|
console.log(this.sprite)
|
||||||
|
}
|
||||||
|
update(delta: number, ctx?: WorldContext) {
|
||||||
|
super.update(delta)
|
||||||
|
this.elapsed += delta
|
||||||
|
if (this.elapsed >= this.lifetime) {
|
||||||
|
console.log('ah, remove ourself')
|
||||||
|
ctx?.removeEntity(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
Engine/src/live/World.ts
Normal file
6
Engine/src/live/World.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { Entity } from "./Entity"
|
||||||
|
|
||||||
|
export interface WorldContext {
|
||||||
|
addEntity(entity: Entity, x: number, y: number): void
|
||||||
|
removeEntity(entity: Entity): void
|
||||||
|
}
|
|
@ -20,6 +20,9 @@ export class SpriteInstance {
|
||||||
subsetKey: string = ''
|
subsetKey: string = ''
|
||||||
frame?: SpritePart
|
frame?: SpritePart
|
||||||
frameIndex: number = 0
|
frameIndex: number = 0
|
||||||
|
frameCount: number = 0
|
||||||
|
animate: boolean = true
|
||||||
|
elapsed: number = 0
|
||||||
|
|
||||||
constructor(ctor: string) {
|
constructor(ctor: string) {
|
||||||
this.container = new PIXI.Container()
|
this.container = new PIXI.Container()
|
||||||
|
@ -34,6 +37,7 @@ export class SpriteInstance {
|
||||||
this.setKey = setKey
|
this.setKey = setKey
|
||||||
this.subsetKey = subsetKey
|
this.subsetKey = subsetKey
|
||||||
this.frameIndex = Number(frameKey)
|
this.frameIndex = Number(frameKey)
|
||||||
|
this.frameCount = 0
|
||||||
this.sprite = sprites[spriteKey]
|
this.sprite = sprites[spriteKey]
|
||||||
if (!this.sprite) {
|
if (!this.sprite) {
|
||||||
this.container.addChild(new PIXI.Text('missing sprite'))
|
this.container.addChild(new PIXI.Text('missing sprite'))
|
||||||
|
@ -44,6 +48,7 @@ export class SpriteInstance {
|
||||||
this.subset = this.set.children[subsetKey]
|
this.subset = this.set.children[subsetKey]
|
||||||
//
|
//
|
||||||
if (this.subset.frames) {
|
if (this.subset.frames) {
|
||||||
|
this.frameCount = this.subset.frames.length
|
||||||
this.frame = this.subset.frames[this.frameIndex]
|
this.frame = this.subset.frames[this.frameIndex]
|
||||||
let s = new PIXI.Sprite(this.frame.texture)
|
let s = new PIXI.Sprite(this.frame.texture)
|
||||||
s.x -= this.frame.originX
|
s.x -= this.frame.originX
|
||||||
|
@ -52,6 +57,19 @@ export class SpriteInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update(delta: number) {
|
||||||
|
if (!this.animate) return
|
||||||
|
this.elapsed += delta
|
||||||
|
while (this.frameCount > 0 && this.frame && this.elapsed >= this.frame.time && this.frame.time > 0) {
|
||||||
|
this.elapsed -= this.frame.time
|
||||||
|
this.frameIndex++
|
||||||
|
if (this.frameIndex >= this.frameCount) {
|
||||||
|
this.frameIndex = 0
|
||||||
|
}
|
||||||
|
this.setCtor(`${this.spriteKey}.${this.animationKey}.${this.setKey}.${this.subsetKey}.${this.frameIndex}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getBodyShape(): Shape|undefined {
|
getBodyShape(): Shape|undefined {
|
||||||
if (this.frame && this.frame.shapes) {
|
if (this.frame && this.frame.shapes) {
|
||||||
return this.frame.shapes.find(v=>v.key==='body')
|
return this.frame.shapes.find(v=>v.key==='body')
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { Zone } from "../live/Zone"
|
||||||
import { Entity } from "../live/Entity"
|
import { Entity } from "../live/Entity"
|
||||||
import { isPlayerEntity, PlayerEntity } from "../live/PlayerEntity"
|
import { isPlayerEntity, PlayerEntity } from "../live/PlayerEntity"
|
||||||
import { Action } from "../live/Action"
|
import { Action } from "../live/Action"
|
||||||
|
import { WorldContext } from "../live/World"
|
||||||
|
|
||||||
export interface PIXIMissingColorMatrix extends PIXI.Filter {
|
export interface PIXIMissingColorMatrix extends PIXI.Filter {
|
||||||
night(intensity: number, multiply: boolean): void
|
night(intensity: number, multiply: boolean): void
|
||||||
|
@ -34,8 +35,9 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
//disableSound()
|
//disableSound()
|
||||||
let isNight = false
|
let isNight = false
|
||||||
let modeTimer = 0
|
let modeTimer = 0
|
||||||
let nightTime = 10 * 60
|
let nightTime = 10 * 1000
|
||||||
let dayTime = 10 * 60
|
let dayTime = 10 * 1000
|
||||||
|
let lastTime: number = performance.now()
|
||||||
|
|
||||||
let world: planck.World = planck.World({
|
let world: planck.World = planck.World({
|
||||||
gravity: planck.Vec2(0, 0),
|
gravity: planck.Vec2(0, 0),
|
||||||
|
@ -43,6 +45,34 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
let worldBody: planck.Body = world.createBody({
|
let worldBody: planck.Body = world.createBody({
|
||||||
type: 'static',
|
type: 'static',
|
||||||
})
|
})
|
||||||
|
world.on('begin-contact', (contact: planck.Contact) => {
|
||||||
|
let a = contact.getFixtureA().getUserData()
|
||||||
|
let b = contact.getFixtureB().getUserData()
|
||||||
|
if (a instanceof Zone) {
|
||||||
|
if (b instanceof Entity) {
|
||||||
|
b.addZoneContact(a)
|
||||||
|
}
|
||||||
|
} else if (a instanceof Entity) {
|
||||||
|
if (b instanceof Entity) {
|
||||||
|
a.addEntityContact(b)
|
||||||
|
b.addEntityContact(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
world.on('end-contact', (contact: planck.Contact) => {
|
||||||
|
let a = contact.getFixtureA().getUserData()
|
||||||
|
let b = contact.getFixtureB().getUserData()
|
||||||
|
if (a instanceof Zone) {
|
||||||
|
if (b instanceof Entity) {
|
||||||
|
b.removeZoneContact(a)
|
||||||
|
}
|
||||||
|
} else if (a instanceof Entity) {
|
||||||
|
if (b instanceof Entity) {
|
||||||
|
a.removeEntityContact(b)
|
||||||
|
b.removeEntityContact(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
let rootContainer = new PIXI.Container()
|
let rootContainer = new PIXI.Container()
|
||||||
let playLayer: Layer
|
let playLayer: Layer
|
||||||
|
@ -51,6 +81,7 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
let zones: Zone[] = []
|
let zones: Zone[] = []
|
||||||
|
|
||||||
let enter = () => {
|
let enter = () => {
|
||||||
|
lastTime = performance.now()
|
||||||
hookKeyboard()
|
hookKeyboard()
|
||||||
// Load the world segment.
|
// Load the world segment.
|
||||||
let w = segments.world
|
let w = segments.world
|
||||||
|
@ -115,7 +146,7 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add bogus entity
|
// Add bogus entity
|
||||||
addEntity(new PlayerEntity('bogus-arrows.player.normal.w.0'), 0, 0)
|
addEntity(new PlayerEntity('deer.animal.stand.west.0'), 300, 100)
|
||||||
|
|
||||||
ctx.app.stage.addChild(rootContainer)
|
ctx.app.stage.addChild(rootContainer)
|
||||||
}
|
}
|
||||||
|
@ -128,9 +159,12 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
}
|
}
|
||||||
let elapsed: number = 0
|
let elapsed: number = 0
|
||||||
let update = (delta: number) => {
|
let update = (delta: number) => {
|
||||||
|
let time = performance.now()
|
||||||
|
let realDelta = time - lastTime
|
||||||
|
lastTime = time
|
||||||
checkGamepads()
|
checkGamepads()
|
||||||
elapsed += delta
|
elapsed += delta
|
||||||
modeTimer += delta
|
modeTimer += realDelta
|
||||||
if (isNight && modeTimer >= nightTime) {
|
if (isNight && modeTimer >= nightTime) {
|
||||||
modeTimer = 0
|
modeTimer = 0
|
||||||
nightfall(false)
|
nightfall(false)
|
||||||
|
@ -146,7 +180,7 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
// Update/render.
|
// Update/render.
|
||||||
for (let layer of layers) {
|
for (let layer of layers) {
|
||||||
for (let decoration of layer.decorations) {
|
for (let decoration of layer.decorations) {
|
||||||
decoration.update(delta)
|
decoration.update(realDelta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let entity of entities) {
|
for (let entity of entities) {
|
||||||
|
@ -156,7 +190,7 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
rootContainer.position.set(Math.round(ctx.app.renderer.width/2), Math.round(ctx.app.renderer.height/2))
|
rootContainer.position.set(Math.round(ctx.app.renderer.width/2), Math.round(ctx.app.renderer.height/2))
|
||||||
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)))
|
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)))
|
||||||
}
|
}
|
||||||
entity.update(delta)
|
entity.update(realDelta, worldContext)
|
||||||
// I guess...
|
// I guess...
|
||||||
entity.sprite.container.x = entity.x
|
entity.sprite.container.x = entity.x
|
||||||
entity.sprite.container.y = entity.y
|
entity.sprite.container.y = entity.y
|
||||||
|
@ -166,6 +200,7 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
|
|
||||||
let addEntity = (entity: Entity, x: number, y: number) => {
|
let addEntity = (entity: Entity, x: number, y: number) => {
|
||||||
if (entities.find(v=>v===entity)) return
|
if (entities.find(v=>v===entity)) return
|
||||||
|
console.log('add somethin', entity)
|
||||||
entities.push(entity)
|
entities.push(entity)
|
||||||
playLayer.container.addChild(entity.sprite.container)
|
playLayer.container.addChild(entity.sprite.container)
|
||||||
// I guess this is a fair enough place to create physics and add it to the entity.
|
// I guess this is a fair enough place to create physics and add it to the entity.
|
||||||
|
@ -188,6 +223,7 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
friction: 0.9,
|
friction: 0.9,
|
||||||
restitution: 0.05,
|
restitution: 0.05,
|
||||||
})
|
})
|
||||||
|
fixture.setUserData(entity)
|
||||||
entity.body = body
|
entity.body = body
|
||||||
body.setUserData(entity)
|
body.setUserData(entity)
|
||||||
}
|
}
|
||||||
|
@ -214,6 +250,7 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
if (zone.type === 'fluid') {
|
if (zone.type === 'fluid') {
|
||||||
zone.fixture.setSensor(true)
|
zone.fixture.setSensor(true)
|
||||||
}
|
}
|
||||||
|
zone.fixture.setUserData(zone)
|
||||||
}
|
}
|
||||||
let removeZone = (zone: Zone) => {
|
let removeZone = (zone: Zone) => {
|
||||||
zones = zones.filter(v=>v!==zone)
|
zones = zones.filter(v=>v!==zone)
|
||||||
|
@ -222,6 +259,11 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let worldContext: WorldContext = {
|
||||||
|
addEntity,
|
||||||
|
removeEntity,
|
||||||
|
}
|
||||||
|
|
||||||
let desiredActions: Action[] = []
|
let desiredActions: Action[] = []
|
||||||
let adjustAction = (type: string, v: number, inc?: boolean) => {
|
let adjustAction = (type: string, v: number, inc?: boolean) => {
|
||||||
let action = desiredActions.find(v=>v.type===type)
|
let action = desiredActions.find(v=>v.type===type)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user