Too many changes
This commit is contained in:
parent
a87d44aa82
commit
581da1473d
|
@ -1,5 +1,7 @@
|
|||
import * as planck from 'planck'
|
||||
import { SpriteInstance } from '../shared/sprites'
|
||||
import { WorldContext } from './World'
|
||||
import { Zone } from './Zone'
|
||||
|
||||
export class Entity {
|
||||
sprite: SpriteInstance
|
||||
|
@ -9,13 +11,15 @@ export class Entity {
|
|||
maxSpeed: number = 4
|
||||
direction: number = 0
|
||||
turnRate: number = 10
|
||||
zones: Zone[] = []
|
||||
contacts: Entity[] = []
|
||||
|
||||
constructor(ctor: string) {
|
||||
this.sprite = new SpriteInstance(ctor)
|
||||
}
|
||||
|
||||
update(delta: number) {
|
||||
// TODO: Update sprite.
|
||||
update(delta: number, ctx?: WorldContext) {
|
||||
this.sprite.update(delta)
|
||||
}
|
||||
|
||||
get position(): [number, number] {
|
||||
|
@ -65,4 +69,18 @@ export class Entity {
|
|||
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 { Action } from "./Action"
|
||||
import { Entity } from "./Entity"
|
||||
import { PuddleEntity } from './PuddleEntity'
|
||||
import { WorldContext } from './World'
|
||||
|
||||
export class PlayerEntity extends Entity {
|
||||
action?: Action
|
||||
puddleTimer: number = 0
|
||||
constructor(ctor: string) {
|
||||
super(ctor)
|
||||
}
|
||||
|
@ -18,10 +21,23 @@ export class PlayerEntity extends Entity {
|
|||
return 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) {
|
||||
// FIXME: Use physics.
|
||||
let shouldMove = false
|
||||
switch(this.action.type) {
|
||||
case 'west':
|
||||
if (this.direction !== 0) {
|
||||
|
@ -69,19 +85,26 @@ export class PlayerEntity extends Entity {
|
|||
} else if (this.direction < 0) {
|
||||
this.direction = 360
|
||||
}
|
||||
if (shouldMove) {
|
||||
let r = this.direction * (Math.PI/180)
|
||||
if (Math.abs(this.velocity[0]) < this.maxSpeed) {
|
||||
this.velocity[0] -= Math.cos(r) * this.acceleration
|
||||
}
|
||||
if (Math.abs(this.velocity[1]) < this.maxSpeed) {
|
||||
this.velocity[1] -= Math.sin(r) * this.acceleration
|
||||
}
|
||||
let cardinal = this.getCardinal()
|
||||
if (this.sprite.subsetKey !== cardinal) {
|
||||
this.sprite.setCtor(`${this.sprite.spriteKey}.${this.sprite.animationKey}.${this.sprite.setKey}.${cardinal}.${this.sprite.frameIndex}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldMove) {
|
||||
let r = this.direction * (Math.PI/180)
|
||||
if (Math.abs(this.velocity[0]) < this.maxSpeed) {
|
||||
this.velocity[0] -= Math.cos(r) * this.acceleration
|
||||
}
|
||||
if (Math.abs(this.velocity[1]) < this.maxSpeed) {
|
||||
this.velocity[1] -= Math.sin(r) * this.acceleration
|
||||
}
|
||||
let cardinal = this.getCardinal()
|
||||
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.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]))
|
||||
}
|
||||
getCardinal(): string {
|
||||
const degreesPerDirection = 360 / 8
|
||||
const degreesPerDirection = 360 / 4
|
||||
const angle = this.direction + degreesPerDirection / 2
|
||||
|
||||
if (angle >= 0 * degreesPerDirection && angle < 1 * degreesPerDirection) {
|
||||
return 'w'
|
||||
return 'west'
|
||||
} else if (angle >= 1 * degreesPerDirection && angle < 2 * degreesPerDirection) {
|
||||
return 'nw'
|
||||
return 'north'
|
||||
} else if (angle >= 2 * degreesPerDirection && angle < 3 * degreesPerDirection) {
|
||||
return 'n'
|
||||
} 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 'east'
|
||||
}
|
||||
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 = ''
|
||||
frame?: SpritePart
|
||||
frameIndex: number = 0
|
||||
frameCount: number = 0
|
||||
animate: boolean = true
|
||||
elapsed: number = 0
|
||||
|
||||
constructor(ctor: string) {
|
||||
this.container = new PIXI.Container()
|
||||
|
@ -34,6 +37,7 @@ export class SpriteInstance {
|
|||
this.setKey = setKey
|
||||
this.subsetKey = subsetKey
|
||||
this.frameIndex = Number(frameKey)
|
||||
this.frameCount = 0
|
||||
this.sprite = sprites[spriteKey]
|
||||
if (!this.sprite) {
|
||||
this.container.addChild(new PIXI.Text('missing sprite'))
|
||||
|
@ -44,6 +48,7 @@ export class SpriteInstance {
|
|||
this.subset = this.set.children[subsetKey]
|
||||
//
|
||||
if (this.subset.frames) {
|
||||
this.frameCount = this.subset.frames.length
|
||||
this.frame = this.subset.frames[this.frameIndex]
|
||||
let s = new PIXI.Sprite(this.frame.texture)
|
||||
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 {
|
||||
if (this.frame && this.frame.shapes) {
|
||||
return this.frame.shapes.find(v=>v.key==='body')
|
||||
|
|
|
@ -12,6 +12,7 @@ import { Zone } from "../live/Zone"
|
|||
import { Entity } from "../live/Entity"
|
||||
import { isPlayerEntity, PlayerEntity } from "../live/PlayerEntity"
|
||||
import { Action } from "../live/Action"
|
||||
import { WorldContext } from "../live/World"
|
||||
|
||||
export interface PIXIMissingColorMatrix extends PIXI.Filter {
|
||||
night(intensity: number, multiply: boolean): void
|
||||
|
@ -34,8 +35,9 @@ export function GameState(ctx: ContextI): StateI {
|
|||
//disableSound()
|
||||
let isNight = false
|
||||
let modeTimer = 0
|
||||
let nightTime = 10 * 60
|
||||
let dayTime = 10 * 60
|
||||
let nightTime = 10 * 1000
|
||||
let dayTime = 10 * 1000
|
||||
let lastTime: number = performance.now()
|
||||
|
||||
let world: planck.World = planck.World({
|
||||
gravity: planck.Vec2(0, 0),
|
||||
|
@ -43,6 +45,34 @@ export function GameState(ctx: ContextI): StateI {
|
|||
let worldBody: planck.Body = world.createBody({
|
||||
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 playLayer: Layer
|
||||
|
@ -51,6 +81,7 @@ export function GameState(ctx: ContextI): StateI {
|
|||
let zones: Zone[] = []
|
||||
|
||||
let enter = () => {
|
||||
lastTime = performance.now()
|
||||
hookKeyboard()
|
||||
// Load the world segment.
|
||||
let w = segments.world
|
||||
|
@ -115,7 +146,7 @@ export function GameState(ctx: ContextI): StateI {
|
|||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
@ -128,9 +159,12 @@ export function GameState(ctx: ContextI): StateI {
|
|||
}
|
||||
let elapsed: number = 0
|
||||
let update = (delta: number) => {
|
||||
let time = performance.now()
|
||||
let realDelta = time - lastTime
|
||||
lastTime = time
|
||||
checkGamepads()
|
||||
elapsed += delta
|
||||
modeTimer += delta
|
||||
modeTimer += realDelta
|
||||
if (isNight && modeTimer >= nightTime) {
|
||||
modeTimer = 0
|
||||
nightfall(false)
|
||||
|
@ -146,7 +180,7 @@ export function GameState(ctx: ContextI): StateI {
|
|||
// Update/render.
|
||||
for (let layer of layers) {
|
||||
for (let decoration of layer.decorations) {
|
||||
decoration.update(delta)
|
||||
decoration.update(realDelta)
|
||||
}
|
||||
}
|
||||
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.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...
|
||||
entity.sprite.container.x = entity.x
|
||||
entity.sprite.container.y = entity.y
|
||||
|
@ -166,6 +200,7 @@ export function GameState(ctx: ContextI): StateI {
|
|||
|
||||
let addEntity = (entity: Entity, x: number, y: number) => {
|
||||
if (entities.find(v=>v===entity)) return
|
||||
console.log('add somethin', entity)
|
||||
entities.push(entity)
|
||||
playLayer.container.addChild(entity.sprite.container)
|
||||
// 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,
|
||||
restitution: 0.05,
|
||||
})
|
||||
fixture.setUserData(entity)
|
||||
entity.body = body
|
||||
body.setUserData(entity)
|
||||
}
|
||||
|
@ -214,6 +250,7 @@ export function GameState(ctx: ContextI): StateI {
|
|||
if (zone.type === 'fluid') {
|
||||
zone.fixture.setSensor(true)
|
||||
}
|
||||
zone.fixture.setUserData(zone)
|
||||
}
|
||||
let removeZone = (zone: 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 adjustAction = (type: string, v: number, inc?: boolean) => {
|
||||
let action = desiredActions.find(v=>v.type===type)
|
||||
|
|
Loading…
Reference in New Issue
Block a user