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,6 +85,8 @@ 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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,10 +96,15 @@ export class PlayerEntity extends Entity {
 | 
			
		|||
        this.velocity[1] -= Math.sin(r) * this.acceleration
 | 
			
		||||
      }
 | 
			
		||||
      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.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