make projectiles use bounding boxes too
This commit is contained in:
+4
-2
@@ -38,7 +38,8 @@ export default class Ability {
|
||||
const ability = this
|
||||
const straightShotCollision = function straightShotCollision(projectile, collidingEntity) {
|
||||
if (collidingEntity == null) { return }
|
||||
if (collidingEntity.team == (projectile.owner?.team ?? 'unknown')) { return }
|
||||
if (collidingEntity.id == caster.id) { return }
|
||||
if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
|
||||
|
||||
collidingEntity.damage(ability.damage, caster)
|
||||
projectile.despawn()
|
||||
@@ -181,7 +182,8 @@ export default class Ability {
|
||||
const ability = this
|
||||
const exposeCollision = function exposeCollision(projectile, collidingEntity) {
|
||||
if (collidingEntity == null) { return }
|
||||
if (collidingEntity.team == (projectile.owner?.team ?? 'unknown')) { return }
|
||||
if (collidingEntity.team == caster.id) { return }
|
||||
if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
|
||||
|
||||
collidingEntity.applyBuff(Buff.exposed.id, caster.id)
|
||||
projectile.despawn()
|
||||
|
||||
+22
-9
@@ -25,6 +25,7 @@ export default class Entity {
|
||||
visualRadius = null
|
||||
|
||||
#attacking = false
|
||||
#colliders = []
|
||||
#dest = null
|
||||
#game = null
|
||||
#logic = null
|
||||
@@ -123,6 +124,8 @@ export default class Entity {
|
||||
if (this.visualRadius == null) {
|
||||
this.visualRadius = this.radius
|
||||
}
|
||||
|
||||
this.#calculateCollider()
|
||||
}
|
||||
|
||||
get attacking() { return this.#attacking }
|
||||
@@ -256,11 +259,11 @@ export default class Entity {
|
||||
}
|
||||
|
||||
collider() {
|
||||
return Entity.collider(this.position.x, this.position.y, this.radius)
|
||||
return this.#colliders.at(0)
|
||||
}
|
||||
|
||||
colliders() {
|
||||
return [this.collider()]
|
||||
return this.#colliders
|
||||
}
|
||||
|
||||
cooldown(id) {
|
||||
@@ -329,7 +332,10 @@ export default class Entity {
|
||||
}
|
||||
|
||||
fixPosition() {
|
||||
this.position = this.fixFuturePosition(this.position.clone()).clone()
|
||||
const fixedPosition = this.fixFuturePosition(this.position)
|
||||
if (this.position.equals(fixedPosition)) { return }
|
||||
|
||||
this.setPosition(fixedPosition)
|
||||
}
|
||||
|
||||
fixFuturePosition(futurePosition) {
|
||||
@@ -400,14 +406,18 @@ export default class Entity {
|
||||
}
|
||||
|
||||
respawn() {
|
||||
this.position = this.#spawnPosition.clone()
|
||||
this.setPosition(this.#spawnPosition)
|
||||
this.health = this.maxHealth
|
||||
this.dead = false
|
||||
}
|
||||
|
||||
setPosition(vector) {
|
||||
this.position.copy(vector)
|
||||
this.#calculateCollider()
|
||||
}
|
||||
|
||||
teleport(cursor) {
|
||||
this.position = cursor.clone()
|
||||
this.fixPosition()
|
||||
this.setPosition(this.fixFuturePosition(cursor))
|
||||
}
|
||||
|
||||
update() {
|
||||
@@ -425,8 +435,6 @@ export default class Entity {
|
||||
if (this.#logic != null) {
|
||||
this.#logic()
|
||||
}
|
||||
|
||||
this.#calculateBbox()
|
||||
}
|
||||
|
||||
waypoints() {
|
||||
@@ -456,6 +464,11 @@ export default class Entity {
|
||||
this.bbox[3] = this.position.x - this.radius
|
||||
}
|
||||
|
||||
#calculateCollider() {
|
||||
this.#calculateBbox()
|
||||
this.#colliders = [Entity.collider(this.position.x, this.position.y, this.radius)]
|
||||
}
|
||||
|
||||
#cast() {
|
||||
if (this.casting == null) {
|
||||
return false
|
||||
@@ -574,7 +587,7 @@ export default class Entity {
|
||||
this.rotation = rotation
|
||||
|
||||
if (!this.willCollide(position)) {
|
||||
this.position.copy(position)
|
||||
this.setPosition(position)
|
||||
}
|
||||
|
||||
if (this.position.equals(destination)) {
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ export default class Game {
|
||||
}
|
||||
|
||||
if (after - before > tickBudget) {
|
||||
console.warn(`Can't keep up! A tick took ${taken.toFixed(1)} ms (Budget: ${tickBudget.toFixed(1)} ms)`)
|
||||
console.warn(`Can't keep up! A tick took ${taken.toFixed(1)} ms. Entity count: ${this.entities.length}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -125,7 +125,8 @@ function laneScenario() {
|
||||
new Vector2(9136, 8248),
|
||||
].map((p) => p.multiplyScalar(1.6))
|
||||
|
||||
if ([(0 * game.tickRate), (1 * game.tickRate), (2 * game.tickRate)].includes(game.currentTick % (30 * game.tickRate))) {
|
||||
if (game.entities.length < 100) {
|
||||
if ([(0 * game.tickRate), (1 * game.tickRate), (2 * game.tickRate)].includes(game.currentTick % (6 * game.tickRate))) {
|
||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: false, route: topRoute })))
|
||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: false, route: midRoute })))
|
||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: false, route: botRoute })))
|
||||
@@ -135,7 +136,7 @@ function laneScenario() {
|
||||
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: false, route: botRoute.toReversed() })))
|
||||
}
|
||||
|
||||
if ([(3 * game.tickRate), (4 * game.tickRate), (5 * game.tickRate)].includes(game.currentTick % (30 * game.tickRate))) {
|
||||
if ([(3 * game.tickRate), (4 * game.tickRate), (5 * game.tickRate)].includes(game.currentTick % (6 * game.tickRate))) {
|
||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: true, route: topRoute })))
|
||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: true, route: midRoute })))
|
||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: true, route: botRoute })))
|
||||
@@ -145,6 +146,8 @@ function laneScenario() {
|
||||
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: true, route: botRoute.toReversed() })))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
game.logic = gameLogic
|
||||
}
|
||||
|
||||
|
||||
+30
-17
@@ -36,17 +36,6 @@ export default class Projectile {
|
||||
}
|
||||
}
|
||||
|
||||
checkCollisions(collider) {
|
||||
(this.game?.entities ?? []).filter((e) => e.id != this.id).forEach((e) => {
|
||||
if (this.game == null) { return }
|
||||
if (e.id == this.owner?.id) { return }
|
||||
|
||||
if (SATX.collideObject(collider, e.collider())) {
|
||||
if (this.onCollide != null) { this.onCollide(this, e) }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
collider() {
|
||||
return new SAT.Circle(new SAT.Vector(this.position.x, this.position.y), this.radius)
|
||||
}
|
||||
@@ -55,10 +44,14 @@ export default class Projectile {
|
||||
this.game?.despawn(this)
|
||||
}
|
||||
|
||||
setPosition(vector) {
|
||||
this.position.copy(vector)
|
||||
this.#calculateBbox()
|
||||
}
|
||||
|
||||
update() {
|
||||
this.#move()
|
||||
this.#calculateBbox()
|
||||
if (this.onCollide != null) { this.checkCollisions(this.collider()) }
|
||||
this.#checkStationaryCollisions()
|
||||
this.#checkIfArrived()
|
||||
}
|
||||
|
||||
@@ -80,21 +73,41 @@ export default class Projectile {
|
||||
this.despawn()
|
||||
}
|
||||
|
||||
#checkStationaryCollisions() {
|
||||
if (this.onCollide == null) { return }
|
||||
|
||||
const bbox = this.bbox
|
||||
const entitiesAndTerrains = this.game?.entities ?? []
|
||||
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox))
|
||||
if (bboxCheckedObstacles.length > 0) {
|
||||
const colliders = bboxCheckedObstacles.map((it) => it.colliders()).flat()
|
||||
const collider = this.collider()
|
||||
colliders.filter((it) => SATX.collideObject(collider, it)).forEach((it) => this.onCollide(this, it))
|
||||
}
|
||||
}
|
||||
|
||||
#move() {
|
||||
if (this.destination == null) { return }
|
||||
|
||||
const speed = (this.speed / (this.game?.tickBudget ?? 1000))
|
||||
const prevPos = this.position.clone()
|
||||
if (this.position.distanceTo(this.destination) < speed) {
|
||||
this.position.copy(this.destination)
|
||||
this.setPosition(this.destination)
|
||||
}
|
||||
else {
|
||||
const step = this.destination.clone().sub(this.position).normalize().multiplyScalar(speed)
|
||||
this.position.add(step)
|
||||
}
|
||||
|
||||
// TODO: decouple from entity's tunnel collider
|
||||
const tunnel = Entity.tunnelCollider(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius)
|
||||
if (this.onCollide != null) { this.checkCollisions(tunnel) }
|
||||
if (this.onCollide != null) {
|
||||
const bbox = Entity.tunnelBbox(position.x, position.y, destination.x, destination.y, this.radius)
|
||||
const entitiesAndTerrains = this.game?.entities ?? []
|
||||
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox))
|
||||
if (bboxCheckedObstacles.length > 0) {
|
||||
const colliders = bboxCheckedObstacles.map((it) => it.colliders()).flat()
|
||||
const collider = Entity.tunnelCollider(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius)
|
||||
colliders.filter((it) => SATX.collideObject(collider, it)).forEach((it) => this.onCollide(this, it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user