GGJ22/Engine/src/live/AnimalEntity.ts

217 lines
6.2 KiB
TypeScript
Raw Normal View History

2022-01-29 18:25:51 -08:00
import * as planck from 'planck'
2022-01-29 23:48:13 -08:00
import { AnimalDefinition, CreatureDefinition } from '../data/animals'
2022-01-29 18:25:51 -08:00
import { Action } from "./Action"
2022-01-29 23:48:13 -08:00
import { Entity, Sensor } from "./Entity"
2022-01-29 21:43:20 -08:00
import { PuddleEntity } from './PuddleEntity'
import { WorldContext } from './World'
2022-01-29 18:25:51 -08:00
2022-01-29 22:39:11 -08:00
export class AnimalEntity extends Entity {
2022-01-29 18:25:51 -08:00
action?: Action
2022-01-29 21:43:20 -08:00
puddleTimer: number = 0
2022-01-29 22:39:11 -08:00
isPlayer: boolean = false
2022-01-29 23:48:13 -08:00
isMonster: boolean = false
thinkTimer: number = 0 // Time since last thought, used by AI.
target?: Entity
def: AnimalDefinition
mode: CreatureDefinition
2022-01-29 22:39:11 -08:00
2022-01-29 23:48:13 -08:00
constructor(def: AnimalDefinition) {
super(`${def.name}.animal.stand.west.0`)
this.def = def
this.mode = def.animal
this.maxSpeed = def.animal.maxSpeed
this.acceleration = def.animal.acceleration
this.turnRate = def.animal.turnRate
2022-01-29 18:25:51 -08:00
}
act(actions: Action[]) {
this.action = actions.sort((a, b) => {
if (a.priority < b.priority) {
2022-01-29 20:30:56 -08:00
return 1
2022-01-29 18:25:51 -08:00
}
if (a.priority > b.priority) {
2022-01-29 20:30:56 -08:00
return -1
2022-01-29 18:25:51 -08:00
}
return 0
})[0]
}
2022-01-29 21:43:20 -08:00
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) {
let p = this.position
p[0] += (this.sprite.frame?.originX??0) + ((this.sprite.frame?.width??0)/2??0)
p[1] += (this.sprite.frame?.originY??0) + ((this.sprite.frame?.height??0)/2??0)
ctx.addEntity(new PuddleEntity('effects.water.ripple.small.0'), 'ground', p[0], p[1])
2022-01-29 21:43:20 -08:00
}
this.puddleTimer = 0
}
}
let shouldMove = false
2022-01-29 18:25:51 -08:00
if (this.action) {
// FIXME: Use physics.
switch(this.action.type) {
case 'west':
if (this.direction !== 0) {
if (this.direction < 180) {
2022-01-29 23:48:13 -08:00
this.direction -= this.mode.turnRate
2022-01-29 18:25:51 -08:00
} else {
2022-01-29 23:48:13 -08:00
this.direction += this.mode.turnRate
2022-01-29 18:25:51 -08:00
}
}
shouldMove = true
break
case 'east':
if (this.direction !== 180) {
if (this.direction < 180) {
2022-01-29 23:48:13 -08:00
this.direction += this.mode.turnRate
2022-01-29 18:25:51 -08:00
} else {
2022-01-29 23:48:13 -08:00
this.direction -= this.mode.turnRate
2022-01-29 18:25:51 -08:00
}
}
shouldMove = true
break
case 'north':
if (this.direction !== 90) {
if (this.direction < 90 || this.direction > 270) {
2022-01-29 23:48:13 -08:00
this.direction += this.mode.turnRate
2022-01-29 18:25:51 -08:00
} else {
2022-01-29 23:48:13 -08:00
this.direction -= this.mode.turnRate
2022-01-29 18:25:51 -08:00
}
}
shouldMove = true
break
case 'south':
if (this.direction !== 270) {
if (this.direction > 90 && this.direction < 270) {
2022-01-29 23:48:13 -08:00
this.direction += this.mode.turnRate
2022-01-29 18:25:51 -08:00
} else {
2022-01-29 23:48:13 -08:00
this.direction -= this.mode.turnRate
2022-01-29 18:25:51 -08:00
}
}
shouldMove = true
break
}
if (this.direction > 360) {
this.direction = 0
} else if (this.direction < 0) {
this.direction = 360
}
2022-01-29 21:43:20 -08:00
}
if (shouldMove) {
let r = this.direction * (Math.PI/180)
2022-01-29 23:48:13 -08:00
if (Math.abs(this.velocity[0]) < this.mode.maxSpeed) {
this.velocity[0] -= Math.cos(r) * this.mode.acceleration
2022-01-29 21:43:20 -08:00
}
2022-01-29 23:48:13 -08:00
if (Math.abs(this.velocity[1]) < this.mode.maxSpeed) {
this.velocity[1] -= Math.sin(r) * this.mode.acceleration
2022-01-29 21:43:20 -08:00
}
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}`)
2022-01-29 18:25:51 -08:00
}
2022-01-29 21:43:20 -08:00
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`)
2022-01-29 18:25:51 -08:00
}
//
2022-01-29 22:24:41 -08:00
this.velocity[0] *= 0.65
this.velocity[1] *= 0.65
2022-01-29 18:25:51 -08:00
// Eh... let's manually handle velocity
this.body?.setLinearVelocity(planck.Vec2(this.velocity[0], this.velocity[1]))
}
getCardinal(): string {
2022-01-29 21:43:20 -08:00
const degreesPerDirection = 360 / 4
2022-01-29 18:25:51 -08:00
const angle = this.direction + degreesPerDirection / 2
if (angle >= 0 * degreesPerDirection && angle < 1 * degreesPerDirection) {
2022-01-29 21:43:20 -08:00
return 'west'
2022-01-29 18:25:51 -08:00
} else if (angle >= 1 * degreesPerDirection && angle < 2 * degreesPerDirection) {
2022-01-29 21:43:20 -08:00
return 'north'
2022-01-29 18:25:51 -08:00
} else if (angle >= 2 * degreesPerDirection && angle < 3 * degreesPerDirection) {
2022-01-29 21:43:20 -08:00
return 'east'
2022-01-29 18:25:51 -08:00
}
2022-01-29 21:43:20 -08:00
return 'south'
2022-01-29 18:25:51 -08:00
}
2022-01-29 23:48:13 -08:00
think(delta: number) {
this.thinkTimer += delta
while (this.thinkTimer >= 500) {
if (!this.isMonster) {
if (this.target) {
// Flee from target
} else {
// Wander.
}
}
this.thinkTimer -= 500
}
}
setTarget(entity: Entity) {
}
sense(sensor: Sensor, entity: AnimalEntity) {
if (this.isPlayer) return
if (sensor.type === 'long') {
this.smell(entity)
} else {
this.see(entity)
}
}
lost(sensor: Sensor, entity: AnimalEntity) {
if (this.isPlayer) return
if (sensor.type === 'long') {
this.unsmell(entity)
} else {
this.unsee(entity)
}
}
smell(entity: AnimalEntity) {
if (entity.isPlayer) {
if (!this.isMonster) {
console.log('alert, we can smell player')
} else {
console.log('we smell the player, wander towards them')
}
}
}
unsmell(entity: AnimalEntity) {
if (entity.isPlayer) {
if (!this.isMonster) {
console.log('no longer smell player, wander around')
} else {
console.log('no longer smell player, wander around')
}
}
}
see(entity: AnimalEntity) {
if (entity.isPlayer) {
if (!this.isMonster) {
console.log('oh no, run from player')
} else {
console.log('oh ho, chase player')
}
}
}
unsee(entity: AnimalEntity) {
if (entity.isPlayer) {
if (!this.isMonster) {
console.log('oh ye, we safe')
} else {
console.log('hunt last seen location')
}
}
}
2022-01-29 18:25:51 -08:00
}
2022-01-29 22:39:11 -08:00
export function isAnimalEntity(o: any): o is AnimalEntity {
2022-01-29 18:25:51 -08:00
return o.act
}