From e91368d3805498b111d770a13742f0003f14e8a8 Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:53:58 +0200 Subject: [PATCH] survivors: maybe made the behaviour better when projectiles flew through the target and then had to continue moving --- absurd-survivors/src/World.ts | 10 +++++++--- absurd-survivors/src/projectile.ts | 26 ++++++++++++++++++++------ absurd-survivors/src/utils.ts | 10 ++++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/absurd-survivors/src/World.ts b/absurd-survivors/src/World.ts index 1c1196f..49964a0 100644 --- a/absurd-survivors/src/World.ts +++ b/absurd-survivors/src/World.ts @@ -83,14 +83,18 @@ export class World { } getClosestTargetTo(point: Vector): [number, Placeable | undefined] | undefined { - return this.getClosestTargetToButNot(point, undefined) + return this.getClosestTargetToButNot(point) } - getClosestTargetToButNot(point: Vector, placeAble?: Placeable): [number, Placeable | undefined] | undefined { + getClosestTargetToButNot(point: Vector, placeable?: Placeable): [number, Placeable | undefined] | undefined { + return this.getClosestTargetToButNotArray(point, [placeable]) + } + + getClosestTargetToButNotArray(point: Vector, placeAbles?: [Placeable | undefined]): [number, Placeable | undefined] | undefined { let currentTarget; let currentDistance = Number.MAX_SAFE_INTEGER; this._enemies.forEach(enemy => { - if(placeAble && enemy === placeAble) { + if(placeAbles && placeAbles.indexOf(enemy) !== -1) { return; } let distance = point.distanceTo(enemy.getPosition()); diff --git a/absurd-survivors/src/projectile.ts b/absurd-survivors/src/projectile.ts index 8d966e9..bc4bfb2 100644 --- a/absurd-survivors/src/projectile.ts +++ b/absurd-survivors/src/projectile.ts @@ -2,7 +2,7 @@ import type {Acting, Placeable, Healthy} from "./interfaces.ts"; import type {Vector} from "./base.ts"; import {World} from "./World.ts"; import {Cooldown, Point, Vector} from "./base.ts"; -import {circleLineCollision, drawDot, moveInDirectionOf, straightMove, toRad} from "./utils.ts"; +import {circleLineCollision, drawDot, moveInDirectionOf, pointOnLineWithinLine, straightMove, toRad} from "./utils.ts"; import {InstanceOfUtils} from "./instance.ts"; export abstract class Projectile implements Acting, Placeable { @@ -15,6 +15,7 @@ export abstract class Projectile implements Acting, Placeable { protected stats: ProjectileStats; protected status: ProjectileStatus; protected lastPosition: Vector; + protected secondToLastPosition?: Vector protected lastColliding?: Placeable; constructor(position: Vector, speedVec: Vector, stats: ProjectileStats, world: World, parent: any) { @@ -81,6 +82,7 @@ export abstract class Projectile implements Acting, Placeable { } move() { + this.secondToLastPosition = this.lastPosition; this.lastPosition = this.position.clone() } @@ -132,19 +134,31 @@ export class HomingProjectile extends Projectile { if(target.dead()) { let closestTargetTo = this.world.getClosestTargetTo(this.position) - let dir = Vector.createVector(this.target.getPosition(), this.position) - let oldDir = Vector.createVector(this.position, this.lastPosition).normalize() + let newTargetDirection = Vector.createVector(this.target.getPosition(), this.position) + let justMovedDirection = Vector.createVector(this.position, this.lastPosition).normalize() + let olderMovedDirection: Vector; + if(this.secondToLastPosition !== undefined) { + olderMovedDirection = Vector.createVector(this.lastPosition, this.secondToLastPosition).normalize(); + } else { + olderMovedDirection = new Vector(0, 1) + } if (closestTargetTo !== undefined && closestTargetTo[1] !== undefined) { let newTargetPosition = closestTargetTo[1]!.getPosition(); let newDir = Vector.createVector(newTargetPosition, this.position) - let newDirAngle = newDir.angleTo(dir); + let newDirAngle = newDir.angleTo(newTargetDirection); if(Math.abs(newDirAngle) >= toRad(150)) { this.target = closestTargetTo[1]!; } else { - this.target = new Point(this.position.add(oldDir.multiply(Math.max(this.world.size.x, this.world.size.y)))) + if(pointOnLineWithinLine(this.target.getPosition(), this.lastPosition, this.position)) { + justMovedDirection = olderMovedDirection + } + this.target = new Point(this.position.add(justMovedDirection.multiply(Math.max(this.world.size.x, this.world.size.y)))) } } else { - this.target = new Point(this.position.add(oldDir.multiply(Math.max(this.world.size.x, this.world.size.y)))) + if(pointOnLineWithinLine(this.target.getPosition(), this.lastPosition, this.position)) { + justMovedDirection = olderMovedDirection + } + this.target = new Point(this.position.add(justMovedDirection.multiply(Math.max(this.world.size.x, this.world.size.y)))) } } } diff --git a/absurd-survivors/src/utils.ts b/absurd-survivors/src/utils.ts index eab1494..e76620e 100644 --- a/absurd-survivors/src/utils.ts +++ b/absurd-survivors/src/utils.ts @@ -40,6 +40,16 @@ export function linePointCollision(point: Vector, lineStart: Vector, lineEnd: Ve return false; } +export function pointOnLineWithinLine(circleCenter: Vector, lineStart: Vector, lineEnd: Vector) { + let lineVector = Vector.createVector(lineEnd, lineStart) + let vectorCenterLine = Vector.createVector(circleCenter, lineStart) + let dot = vectorCenterLine.dotProduct(lineVector) + let closestX = lineStart.x + (dot * (lineVector.x)) + let closestY = lineStart.y + (dot * (lineVector.y)) + let closestPoint = new Vector(closestX, closestY); + return linePointCollision(closestPoint, lineStart, lineEnd); +} + export function circleLineCollision(circleCenter: Vector, radius: number, lineStart: Vector, lineEnd: Vector) { if(pointInsideCircle(circleCenter, radius, lineStart) || pointInsideCircle(circleCenter, radius, lineEnd)) { return true;