Add some physics handling
This commit is contained in:
parent
b3ef7a86f0
commit
745c3573a7
|
@ -2,8 +2,10 @@ import { ContextI } from "../ContextI"
|
||||||
import { segments } from "../shared/segments"
|
import { segments } from "../shared/segments"
|
||||||
import { StateI } from "./StateI"
|
import { StateI } from "./StateI"
|
||||||
import * as PIXI from 'pixi.js'
|
import * as PIXI from 'pixi.js'
|
||||||
|
import * as planck from 'planck'
|
||||||
import { DecorationInstance } from "../shared/decors"
|
import { DecorationInstance } from "../shared/decors"
|
||||||
import { SpriteInstance } from "../shared/sprites"
|
import { SpriteInstance, sprites } from "../shared/sprites"
|
||||||
|
import { ShapeCircle, ShapePoints } from "../data/sprite"
|
||||||
|
|
||||||
interface Action {
|
interface Action {
|
||||||
type: string
|
type: string
|
||||||
|
@ -12,6 +14,11 @@ interface Action {
|
||||||
|
|
||||||
class Entity {
|
class Entity {
|
||||||
sprite: SpriteInstance
|
sprite: SpriteInstance
|
||||||
|
body?: planck.Body
|
||||||
|
velocity: [number, number] = [0, 0]
|
||||||
|
acceleration: number = 0.5
|
||||||
|
maxSpeed: number = 4
|
||||||
|
direction: number = 0
|
||||||
|
|
||||||
constructor(ctor: string) {
|
constructor(ctor: string) {
|
||||||
this.sprite = new SpriteInstance(ctor)
|
this.sprite = new SpriteInstance(ctor)
|
||||||
|
@ -21,27 +28,59 @@ class Entity {
|
||||||
// TODO: Update sprite.
|
// TODO: Update sprite.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get position(): [number, number] {
|
||||||
|
if (this.body) {
|
||||||
|
let p = this.body.getPosition()
|
||||||
|
return [p.x, p.y]
|
||||||
|
}
|
||||||
|
return [this.sprite.container.x, this.sprite.container.y]
|
||||||
|
}
|
||||||
get x(): number {
|
get x(): number {
|
||||||
|
if (this.body) {
|
||||||
|
let p = this.body.getPosition()
|
||||||
|
return p.x
|
||||||
|
}
|
||||||
return this.sprite.container.x
|
return this.sprite.container.x
|
||||||
}
|
}
|
||||||
set x(v: number) {
|
set x(v: number) {
|
||||||
this.sprite.container.x = v
|
if (this.body) {
|
||||||
|
let p = this.body.getPosition()
|
||||||
|
this.body.setPosition(
|
||||||
|
planck.Vec2(
|
||||||
|
v,
|
||||||
|
p.y,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.sprite.container.y = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
get y(): number {
|
get y(): number {
|
||||||
|
if (this.body) {
|
||||||
|
let p = this.body.getPosition()
|
||||||
|
return p.y
|
||||||
|
}
|
||||||
return this.sprite.container.y
|
return this.sprite.container.y
|
||||||
}
|
}
|
||||||
set y(v: number) {
|
set y(v: number) {
|
||||||
|
if (this.body) {
|
||||||
|
let p = this.body.getPosition()
|
||||||
|
this.body.setPosition(
|
||||||
|
planck.Vec2(
|
||||||
|
p.x,
|
||||||
|
v,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
this.sprite.container.y = v
|
this.sprite.container.y = v
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlayerEntity extends Entity {
|
class PlayerEntity extends Entity {
|
||||||
action?: Action
|
action?: Action
|
||||||
constructor(ctor: string) {
|
constructor(ctor: string) {
|
||||||
super(ctor)
|
super(ctor)
|
||||||
this.x = 100
|
|
||||||
this.y = 100
|
|
||||||
// TODO: Hooks for key state check input, perhaps?
|
|
||||||
}
|
}
|
||||||
act(actions: Action[]) {
|
act(actions: Action[]) {
|
||||||
this.action = actions.sort((a, b) => {
|
this.action = actions.sort((a, b) => {
|
||||||
|
@ -59,19 +98,33 @@ class PlayerEntity extends Entity {
|
||||||
// FIXME: Use physics.
|
// FIXME: Use physics.
|
||||||
switch(this.action.type) {
|
switch(this.action.type) {
|
||||||
case 'west':
|
case 'west':
|
||||||
this.x--
|
if (this.velocity[0] > -this.maxSpeed) {
|
||||||
|
this.velocity[0] -= this.acceleration
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'east':
|
case 'east':
|
||||||
this.x++
|
if (this.velocity[0] < this.maxSpeed) {
|
||||||
|
this.velocity[0] += this.acceleration
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'north':
|
case 'north':
|
||||||
this.y--
|
if (this.velocity[1] > -this.maxSpeed) {
|
||||||
|
this.velocity[1] -= this.acceleration
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'south':
|
case 'south':
|
||||||
this.y++
|
if (this.velocity[1] < this.maxSpeed) {
|
||||||
|
this.velocity[1] += this.acceleration
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
this.velocity[0] *= 0.5
|
||||||
|
this.velocity[1] *= 0.5
|
||||||
|
|
||||||
|
// Eh... let's manually handle velocity
|
||||||
|
this.body?.setLinearVelocity(planck.Vec2(this.velocity[0], this.velocity[1]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function isPlayerEntity(o: any): o is PlayerEntity {
|
function isPlayerEntity(o: any): o is PlayerEntity {
|
||||||
|
@ -79,6 +132,9 @@ function isPlayerEntity(o: any): o is PlayerEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GameState(ctx: ContextI): StateI {
|
export function GameState(ctx: ContextI): StateI {
|
||||||
|
let world: planck.World = planck.World({
|
||||||
|
gravity: planck.Vec2(0, 0),
|
||||||
|
})
|
||||||
|
|
||||||
let rootContainer = new PIXI.Container()
|
let rootContainer = new PIXI.Container()
|
||||||
let decorations: DecorationInstance[] = []
|
let decorations: DecorationInstance[] = []
|
||||||
|
@ -102,17 +158,26 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
di.elapsed = d.timeOffset
|
di.elapsed = d.timeOffset
|
||||||
di.container.x = d.x
|
di.container.x = d.x
|
||||||
di.container.y = d.y
|
di.container.y = d.y
|
||||||
|
if (d.rotation !== 0) {
|
||||||
|
di.container.angle = d.rotation
|
||||||
|
}
|
||||||
if (d.flip) {
|
if (d.flip) {
|
||||||
di.container.pivot.y = 1
|
di.container.pivot.y = 1
|
||||||
di.container.scale.y *= -1
|
di.container.scale.y *= -1
|
||||||
|
if (d.rotation === 0) {
|
||||||
di.container.position.y--
|
di.container.position.y--
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (d.mirror) {
|
if (d.mirror) {
|
||||||
di.container.pivot.x = 1
|
di.container.pivot.x = 1
|
||||||
di.container.scale.x *= -1
|
di.container.scale.x *= -1
|
||||||
di.container.position.x--
|
di.container.position.x--
|
||||||
|
if (d.rotation !== 0) {
|
||||||
|
di.container.angle = -d.rotation
|
||||||
|
di.container.position.x++
|
||||||
|
di.container.position.y--
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
container.addChild(di.container)
|
container.addChild(di.container)
|
||||||
decorations.push(di)
|
decorations.push(di)
|
||||||
}
|
}
|
||||||
|
@ -121,7 +186,8 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add bogus entity
|
// Add bogus entity
|
||||||
addEntity(new PlayerEntity('animals.deer.animal.west.0'))
|
//addEntity(new PlayerEntity('animals.deer.animal.west.0'), 0, 0)
|
||||||
|
addEntity(new PlayerEntity('bogus-arrows.player.normal.e.0'), 0, 0)
|
||||||
|
|
||||||
ctx.app.stage.addChild(rootContainer)
|
ctx.app.stage.addChild(rootContainer)
|
||||||
}
|
}
|
||||||
|
@ -132,7 +198,15 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
}
|
}
|
||||||
ctx.app.stage.removeChild(rootContainer)
|
ctx.app.stage.removeChild(rootContainer)
|
||||||
}
|
}
|
||||||
|
let elapsed: number = 0
|
||||||
let update = (delta: number) => {
|
let update = (delta: number) => {
|
||||||
|
elapsed += delta
|
||||||
|
// Run world sim.
|
||||||
|
while (elapsed >= 1/60) {
|
||||||
|
world.step(1/60)
|
||||||
|
elapsed -= 1/60
|
||||||
|
}
|
||||||
|
// Update/render.
|
||||||
for (let decoration of decorations) {
|
for (let decoration of decorations) {
|
||||||
decoration.update(delta)
|
decoration.update(delta)
|
||||||
}
|
}
|
||||||
|
@ -144,17 +218,50 @@ export function GameState(ctx: ContextI): StateI {
|
||||||
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(delta)
|
||||||
|
// I guess...
|
||||||
|
entity.sprite.container.x = entity.x
|
||||||
|
entity.sprite.container.y = entity.y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let addEntity = (entity: Entity) => {
|
let addEntity = (entity: Entity, x: number, y: number) => {
|
||||||
if (entities.find(v=>v===entity)) return
|
if (entities.find(v=>v===entity)) return
|
||||||
entities.push(entity)
|
entities.push(entity)
|
||||||
rootContainer.addChild(entity.sprite.container)
|
rootContainer.addChild(entity.sprite.container)
|
||||||
|
// I guess this is a fair enough place to create physics and add it to the entity.
|
||||||
|
let spriteShape = entity.sprite.getBodyShape()
|
||||||
|
if (spriteShape) {
|
||||||
|
let shape: planck.Shape|undefined
|
||||||
|
if (spriteShape instanceof ShapeCircle) {
|
||||||
|
shape = planck.Circle(planck.Vec2(spriteShape.x, spriteShape.y), spriteShape.radius)
|
||||||
|
} else if (spriteShape instanceof ShapePoints) {
|
||||||
|
shape = planck.Polygon(spriteShape.points.map(v=>planck.Vec2(v[0], v[1])))
|
||||||
|
}
|
||||||
|
if (shape !== undefined) {
|
||||||
|
let body = world.createDynamicBody({
|
||||||
|
position: planck.Vec2(entity.x, entity.y),
|
||||||
|
fixedRotation: true,
|
||||||
|
})
|
||||||
|
let fixture = body.createFixture({
|
||||||
|
shape,
|
||||||
|
density: 1,
|
||||||
|
friction: 0.9,
|
||||||
|
restitution: 0.05,
|
||||||
|
})
|
||||||
|
entity.body = body
|
||||||
|
body.setUserData(entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entity.x = x
|
||||||
|
entity.y = y
|
||||||
}
|
}
|
||||||
let removeEntity = (entity: Entity) => {
|
let removeEntity = (entity: Entity) => {
|
||||||
entities = entities.filter(v=>v!==entity)
|
entities = entities.filter(v=>v!==entity)
|
||||||
rootContainer.removeChild(entity.sprite.container)
|
rootContainer.removeChild(entity.sprite.container)
|
||||||
|
if (entity.body) {
|
||||||
|
world.destroyBody(entity.body)
|
||||||
|
entity.body = undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let desiredActions: Action[] = []
|
let desiredActions: Action[] = []
|
||||||
|
|
Loading…
Reference in New Issue
Block a user