rely on stringification instead of state reports
This commit is contained in:
@@ -38,6 +38,9 @@ export default class Ability {
|
||||
effect: function straightShotEffect(caster, cursor) {
|
||||
const ability = this
|
||||
const straightShotCollision = function straightShotCollision(projectile, collidingEntity) {
|
||||
if (collidingEntity == null) { return }
|
||||
if (collidingEntity.team == (projectile.owner?.team ?? 'unknown')) { return }
|
||||
|
||||
collidingEntity.damage(ability.damage)
|
||||
projectile.despawn()
|
||||
}
|
||||
|
||||
+27
-25
@@ -79,21 +79,12 @@ export default class Entity {
|
||||
])
|
||||
}
|
||||
|
||||
adjustWaypoint(waypoint, direction) {
|
||||
return SATX.clamp(
|
||||
waypoint.clone().add(direction.clone().multiplyScalar(this.radius)),
|
||||
this.game?.width,
|
||||
this.game?.height,
|
||||
this.radius,
|
||||
)
|
||||
}
|
||||
|
||||
attackAction(cursor) {
|
||||
this.moveAction(cursor, true)
|
||||
}
|
||||
|
||||
castAction(slot, cursor, halt = false) {
|
||||
const ability = this.abilities[slot]
|
||||
const ability = this.ability(slot)
|
||||
if (ability == null) { return }
|
||||
|
||||
if (this.casting != null) {
|
||||
@@ -143,6 +134,21 @@ export default class Entity {
|
||||
|
||||
// --- Actions above --- //
|
||||
|
||||
ability(slot) {
|
||||
if (this.abilities[slot] != null) {
|
||||
return this.game?.abilities.find((it) => it.id == this.abilities[slot])
|
||||
}
|
||||
}
|
||||
|
||||
adjustWaypoint(waypoint, direction) {
|
||||
return SATX.clamp(
|
||||
waypoint.clone().add(direction.clone().multiplyScalar(this.radius)),
|
||||
this.game?.width,
|
||||
this.game?.height,
|
||||
this.radius,
|
||||
)
|
||||
}
|
||||
|
||||
collidables() {
|
||||
const entityColliders = (this.game?.entities ?? []).filter((e) => e.id != this.id).map((e) => e.collider())
|
||||
const terrainColliders = (this.game?.terrains ?? []).map((t) => t.colliders()).flat()
|
||||
@@ -200,12 +206,6 @@ export default class Entity {
|
||||
this.dead = false
|
||||
}
|
||||
|
||||
state() {
|
||||
return {
|
||||
...this,
|
||||
}
|
||||
}
|
||||
|
||||
teleport(cursor) {
|
||||
this.position = cursor.clone()
|
||||
this.fixPosition()
|
||||
@@ -264,16 +264,18 @@ export default class Entity {
|
||||
|
||||
if (this.#attacking) {
|
||||
const cursor = this.#dest ?? this.position
|
||||
const basicAttack = this.abilities[0]
|
||||
const target = this.closestTargetTo(cursor, basicAttack.range)
|
||||
if (target != null && this.distanceTo(target.position) < basicAttack.range) {
|
||||
const cooldown = this.game?.secToTick(basicAttack.cooldown) ?? 0
|
||||
const lastCast = this.cooldowns[basicAttack.id]
|
||||
const timestamp = this.game?.currentTick ?? 0
|
||||
if (lastCast != null && lastCast + cooldown > timestamp) { return false }
|
||||
const basicAttack = this.ability(0)
|
||||
if (basicAttack != null) {
|
||||
const target = this.closestTargetTo(cursor, basicAttack.range)
|
||||
if (target != null && this.distanceTo(target.position) < basicAttack.range) {
|
||||
const cooldown = this.game?.secToTick(basicAttack.cooldown) ?? 0
|
||||
const lastCast = this.cooldowns[basicAttack.id]
|
||||
const timestamp = this.game?.currentTick ?? 0
|
||||
if (lastCast != null && lastCast + cooldown > timestamp) { return false }
|
||||
|
||||
this.castAction(0, cursor, false)
|
||||
return true
|
||||
this.castAction(0, cursor, false)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-23
@@ -1,31 +1,30 @@
|
||||
import { EventEmitter } from 'node:events'
|
||||
import Ability from './ability.js'
|
||||
import Entity from './entity.js'
|
||||
import Projectile from './projectile.js'
|
||||
import Terrain from './terrain.js'
|
||||
|
||||
export default class Game {
|
||||
abilities = Object.values({...Ability})
|
||||
averageTick = 0
|
||||
currentTick = 0
|
||||
entities = []
|
||||
height = 2000
|
||||
projectiles = []
|
||||
secondToSlowestTick = 0
|
||||
terrains = []
|
||||
tickRate = 30
|
||||
width = 2000
|
||||
|
||||
#currentTiming = 0
|
||||
#entities = []
|
||||
#eventEmitter = new EventEmitter()
|
||||
#logic = null
|
||||
#nextTickAt = 0
|
||||
#projectiles = []
|
||||
#terrains = []
|
||||
#tickBudget = 1000 / this.tickRate
|
||||
#timings = new Float32Array(this.tickRate)
|
||||
|
||||
get logic() { return this.#logic }
|
||||
get entities() { return this.#entities }
|
||||
get eventEmitter() { return this.#eventEmitter }
|
||||
get projectiles() { return this.#projectiles }
|
||||
get terrains() { return this.#terrains }
|
||||
get tickBudget() { return this.#tickBudget }
|
||||
set logic(value) { this.#logic = value }
|
||||
|
||||
@@ -34,7 +33,7 @@ export default class Game {
|
||||
}
|
||||
|
||||
addTerrain(terrain) {
|
||||
this.#terrains.push(terrain)
|
||||
this.terrains.push(terrain)
|
||||
}
|
||||
|
||||
despawn(object) {
|
||||
@@ -45,17 +44,17 @@ export default class Game {
|
||||
}
|
||||
|
||||
despawnEntity(entity) {
|
||||
this.#entities = this.#entities.filter((e) => e.id != entity.id)
|
||||
this.entities = this.entities.filter((e) => e.id != entity.id)
|
||||
entity.game = null
|
||||
}
|
||||
|
||||
despawnProjectile(projectile) {
|
||||
this.#projectiles = this.#projectiles.filter((p) => p.id != projectile.id)
|
||||
this.projectiles = this.projectiles.filter((p) => p.id != projectile.id)
|
||||
projectile.game = null
|
||||
}
|
||||
|
||||
removeTerrain(terrain) {
|
||||
this.#terrains = this.#terrains.filter((t) => t.id != terrain.id)
|
||||
this.terrains = this.terrains.filter((t) => t.id != terrain.id)
|
||||
}
|
||||
|
||||
secToTick(sec) {
|
||||
@@ -70,31 +69,22 @@ export default class Game {
|
||||
}
|
||||
|
||||
spawnEntity(entity) {
|
||||
this.#entities.push(entity)
|
||||
this.entities.push(entity)
|
||||
entity.game = this
|
||||
}
|
||||
|
||||
spawnProjectile(projectile) {
|
||||
this.#projectiles.push(projectile)
|
||||
this.projectiles.push(projectile)
|
||||
projectile.game = this
|
||||
}
|
||||
|
||||
state() {
|
||||
return {
|
||||
...this,
|
||||
entities: this.#entities.map((e) => e.state()),
|
||||
terrains: this.#terrains.map((t) => t.state()),
|
||||
projectiles: this.#projectiles.map((p) => p.state()),
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
setInterval(() => this.#gameLoop(), 1)
|
||||
}
|
||||
|
||||
update() {
|
||||
this.#entities.forEach((e) => e.update())
|
||||
this.#projectiles.forEach((p) => p.update())
|
||||
this.entities.forEach((e) => e.update())
|
||||
this.projectiles.forEach((p) => p.update())
|
||||
if (this.#logic != null) {
|
||||
this.#logic()
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ app.use(express.urlencoded({ extended: true }))
|
||||
app.ws('/ws', async (req, res) => {
|
||||
const websocket = await res.accept()
|
||||
|
||||
const subscription = () => websocket.send(JSON.stringify(game.state()))
|
||||
const subscription = () => websocket.send(JSON.stringify(game))
|
||||
game.eventEmitter.on('tick', subscription)
|
||||
|
||||
websocket.on('close', () => {
|
||||
|
||||
@@ -52,12 +52,6 @@ export default class Projectile {
|
||||
this.game?.despawn(this)
|
||||
}
|
||||
|
||||
state() {
|
||||
return {
|
||||
...this,
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
this.#move()
|
||||
if (this.onCollide != null) { this.checkCollisions(this.collider()) }
|
||||
|
||||
+5
-5
@@ -5,7 +5,7 @@ import Team from './team.js'
|
||||
export default class Template {
|
||||
static minion(team, options = {}) {
|
||||
return {
|
||||
abilities: [options.ranged ? Ability.rangedAttack : Ability.meleeAttack, null, null, null],
|
||||
abilities: [options.ranged ? Ability.rangedAttack.id : Ability.meleeAttack.id, null, null, null],
|
||||
height: options.ranged ? 40 : 38,
|
||||
logic: this.#minionLogic(options.route),
|
||||
maxHealth: options.ranged ? 300 : 450,
|
||||
@@ -20,10 +20,10 @@ export default class Template {
|
||||
static player(overrides) {
|
||||
return {
|
||||
abilities: [
|
||||
Ability.rangedAttack,
|
||||
Ability.straightShot,
|
||||
Ability.shieldThrow,
|
||||
Ability.blink,
|
||||
Ability.rangedAttack.id,
|
||||
Ability.straightShot.id,
|
||||
Ability.shieldThrow.id,
|
||||
Ability.blink.id,
|
||||
],
|
||||
height: 80,
|
||||
logic: this.#playerLogic,
|
||||
|
||||
@@ -45,12 +45,6 @@ export default class Terrain {
|
||||
|
||||
colliders() { return this.#colliders }
|
||||
|
||||
state() {
|
||||
return {
|
||||
...this,
|
||||
}
|
||||
}
|
||||
|
||||
#shape() {
|
||||
const complexShape = new Shape()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user