diff --git a/absurd-survivors/src/Player.ts b/absurd-survivors/src/Player.ts index 6bea9f2..ebc3f24 100644 --- a/absurd-survivors/src/Player.ts +++ b/absurd-survivors/src/Player.ts @@ -6,7 +6,7 @@ export class Player implements Drawable, Acting, Healthy { private _position: Vector; private _stats: Stats; private _color: string; - private _status: Status; + private _status: PlayerStatus; private _weapons: [Weapon] = [] // temp @@ -27,7 +27,7 @@ export class Player implements Drawable, Acting, Healthy { player._color = 'blue'; player._stats = Stats.defaultPlayerStats(); player._speed = new Vector(0, 0) - player._status = new Status(10, 0); + player._status = new PlayerStatus(10, 0); return player; } @@ -64,7 +64,7 @@ export class Player implements Drawable, Acting, Healthy { return this._stats; } - get status(): Status { + get status(): PlayerStatus { return this._status; } @@ -92,7 +92,7 @@ export class Player implements Drawable, Acting, Healthy { } } -export class Status { +export class PlayerStatus { constructor(private _health: number, private _wealth: number) { } diff --git a/absurd-survivors/src/World.ts b/absurd-survivors/src/World.ts index a941fcc..1c1196f 100644 --- a/absurd-survivors/src/World.ts +++ b/absurd-survivors/src/World.ts @@ -1,5 +1,4 @@ import {Enemy} from "./Enemies.ts"; -import type {Player} from "./Player.ts"; import {Player} from "./Player.ts"; import {Projectile} from "./projectile.ts"; import {Vector} from "./base.ts"; @@ -40,6 +39,15 @@ export class World { this._drops.push(drop) } + movePlayer(vector: Vector) { + this._player.position.x += vector.x; + this._player.position.y += vector.y; + this._player.position.x = Math.min(this.size.x - this._player.getSize(), this._player.position.x) + this._player.position.x = Math.max(this._player.getSize(), this._player.position.x) + this._player.position.y = Math.min(this.size.y -this._player.getSize(), this._player.position.y) + this._player.position.y = Math.max(this._player.getSize(), this._player.position.y) + } + removeDrop(drop: Drop) { this._drops = this._drops.filter(item => item !== drop) } @@ -75,9 +83,16 @@ export class World { } getClosestTargetTo(point: Vector): [number, Placeable | undefined] | undefined { + return this.getClosestTargetToButNot(point, undefined) + } + + getClosestTargetToButNot(point: Vector, placeAble?: Placeable): [number, Placeable | undefined] | undefined { let currentTarget; let currentDistance = Number.MAX_SAFE_INTEGER; this._enemies.forEach(enemy => { + if(placeAble && enemy === placeAble) { + return; + } let distance = point.distanceTo(enemy.getPosition()); if(distance < currentDistance) { currentDistance = distance; diff --git a/absurd-survivors/src/drop.ts b/absurd-survivors/src/drop.ts index 17ae403..0e83ea4 100644 --- a/absurd-survivors/src/drop.ts +++ b/absurd-survivors/src/drop.ts @@ -63,7 +63,7 @@ export class MoneyDrop extends BasicDrop { let drop = new MoneyDrop(world, position) drop.worth = 1; drop._size = 1; - drop._color = 'yellow'; + drop._color = 'orange'; world.addDrop(drop) return drop; } diff --git a/absurd-survivors/src/main.ts b/absurd-survivors/src/main.ts index 16d61a5..14854f5 100644 --- a/absurd-survivors/src/main.ts +++ b/absurd-survivors/src/main.ts @@ -65,16 +65,16 @@ function makeKey(char, fun) { let keys = {}; makeKey('w', function () { - world.player.position.y += -world.player.stats.speed + world.movePlayer(new Vector(0, -world.player.stats.speed)) }) makeKey('s', function () { - world.player.position.y += world.player.stats.speed + world.movePlayer(new Vector(0, world.player.stats.speed)) }) makeKey('a', function () { - world.player.position.x += -world.player.stats.speed + world.movePlayer(new Vector(-world.player.stats.speed, 0)) }) makeKey('d', function () { - world.player.position.x += world.player.stats.speed + world.movePlayer(new Vector(world.player.stats.speed, 0)) }) diff --git a/absurd-survivors/src/projectile.ts b/absurd-survivors/src/projectile.ts index 4432a9f..429f58a 100644 --- a/absurd-survivors/src/projectile.ts +++ b/absurd-survivors/src/projectile.ts @@ -12,8 +12,10 @@ export abstract class Projectile implements Acting, Placeable { protected world: World; protected parent: any; protected color: string - private stats: ProjectileStats; - private status: ProjectileStatus; + protected stats: ProjectileStats; + protected status: ProjectileStatus; + protected lastPosition: Vector; + protected lastColliding?: Placeable; constructor(position: Vector, speedVec: Vector, stats: ProjectileStats, world: World, parent: any) { this.position = position.clone(); @@ -26,20 +28,20 @@ export abstract class Projectile implements Acting, Placeable { act() { this.move() - if(this.status.collisionCooldown.cooledDown()) { - if(this.parent !== this.world.player) { - if(this.position.distanceTo(this.world.player.position) < (this.stats.size + this.world.player.stats.size)) { - this.impactPlayer() - this.status.collisionCooldown.resetCooldown() - } - } else if(this.parent === this.world.player) { - let closestTargetTo = this.world.getClosestTargetTo(this.position); - if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined && closestTargetTo[1]?.getPosition().distanceTo(this.position) < (this.stats.size + closestTargetTo[1]?.getSize())) { - let target: Placeable = closestTargetTo[1]!; + if(this.parent !== this.world.player) { + if(this.position.distanceTo(this.world.player.position) < (this.stats.size + this.world.player.stats.size) && this.status.collisionCooldown.cooledDown()) { + this.impactPlayer() + this.status.collisionCooldown.resetCooldown() + } + } else if(this.parent === this.world.player) { + let closestTargetTo = this.world.getClosestTargetToButNot(this.position, this.lastColliding); + if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined && closestTargetTo[1]?.getPosition().distanceTo(this.position) < (this.stats.size + closestTargetTo[1]?.getSize())) { + let target: Placeable = closestTargetTo[1]!; + if(target !== this.lastColliding) { if(InstanceOfUtils.instanceOfHealthy(target)) { let healthy = target as Healthy; healthy.takeDamage(this.stats.damage) - if(this.status.piercingsLeft <= 0) { + if(!this.status.hasPiercingLeft()) { this.world.removeProjectile(this) } this.status.decreasePiercings() @@ -47,9 +49,12 @@ export abstract class Projectile implements Acting, Placeable { this.world.removeProjectile(this) } } + this.lastColliding = target; + } else { + this.lastColliding = undefined; } } - this.status.collisionCooldown.decreaseCooldown(); + this.status.collisionCooldown.decreaseCooldown() this.checkWorldBorder() } @@ -61,7 +66,9 @@ export abstract class Projectile implements Acting, Placeable { impactPlayer() { this.world.player.takeDamage(this.stats.damage) - this.world.removeProjectile(this) + if(!this.status.hasPiercingLeft()) { + this.world.removeProjectile(this) + } }; draw(ctx: CanvasRenderingContext2D) { @@ -69,6 +76,7 @@ export abstract class Projectile implements Acting, Placeable { } move() { + this.lastPosition = this.position.clone() } getPosition(): Vector { @@ -89,6 +97,7 @@ export class StraightProjectile extends Projectile { } move() { + super.move() this.position = straightMove(this.position, this.speedVec) } @@ -111,35 +120,35 @@ export class HomingProjectile extends Projectile { } move() { + super.move() + this.position = moveInDirectionOf(this.position, this.target.getPosition(), this.speedVec.vecLength()) if(InstanceOfUtils.instanceOfHealthy(this.target)) { let target = this.target as Healthy if(target.dead()) { - if(this.position.distanceTo(this.target.getPosition()) < (this.target.getSize() + this.getSize())) { - this.world.removeProjectile(this) - return; - } - let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position) + let closestTargetTo = this.world.getClosestTargetTo(this.position) + let dir = Vector.createVector(this.target.getPosition(), this.position).normalize() + let oldDir = Vector.createVector(this.position, this.lastPosition).normalize() if (closestTargetTo !== undefined && closestTargetTo[1] !== undefined) { - let dir = Vector.createVector(this.target.getPosition(), this.position).normalize() let newTargetPosition = closestTargetTo[1]!.getPosition(); let newDir = Vector.createVector(newTargetPosition, this.position).normalize() let newDirAngle = newDir.angleTo(dir); - if(Math.abs(newDirAngle) < toRad(60)) { + if(Math.abs(newDirAngle) >= toRad(150)) { this.target = closestTargetTo[1]!; } else { - this.target = new Point(this.target.getPosition().add(dir.normalize().multiply(Math.max(this.world.size.x, this.world.size.y)))) + this.target = new Point(this.position.add(oldDir.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)))) } } } - this.position = moveInDirectionOf(this.position, this.target.getPosition(), this.speedVec.vecLength()) this.checkWorldBorder() } static createHomingProjectile(world: World, start: Vector, parent: any, target: Placeable, stats: ProjectileStats, color?: string) { - let projectile = new HomingProjectile(start, new Vector(5, 1), stats, world, parent, target) + let projectile = new HomingProjectile(start, new Vector(0, stats.speed), stats, world, parent, target) projectile.color = color === undefined ? 'red' : color!; world.addProjectile(projectile) return projectile; @@ -160,6 +169,10 @@ export class ProjectileStatus { return this._piercingsLeft; } + hasPiercingLeft(): boolean { + return this.piercingsLeft >= 0; + } + get collisionCooldown(): Cooldown { return this._collisionCooldown; @@ -175,11 +188,13 @@ export class ProjectileStats { private _piercings: number; private _size: number; private _damage: number; + private _speed: number; - constructor(piercings: number, size: number, damage: number) { + constructor(piercings: number, size: number, damage: number, _speed: number) { this._piercings = piercings; this._size = size; this._damage = damage + this._speed = _speed; } get piercings(): number { @@ -191,6 +206,10 @@ export class ProjectileStats { } + get speed(): number { + return this._speed; + } + get damage(): number { return this._damage; } diff --git a/absurd-survivors/src/weapons.ts b/absurd-survivors/src/weapons.ts index 5cae681..4183eb2 100644 --- a/absurd-survivors/src/weapons.ts +++ b/absurd-survivors/src/weapons.ts @@ -7,10 +7,10 @@ import {Vector} from "./base.ts"; export class Pistol implements Weapon { - private player: Player + private readonly player: Player private shootInterval: number; private shootCooldown: number = 0; - private world: World; + private readonly world: World; private offset: Vector; private projectiles: [Projectile] = [] private color: string; @@ -37,7 +37,7 @@ export class Pistol implements Weapon { private createProjectile(): boolean { let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position); if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined) { - let stats = new ProjectileStats(0, 1, 5) + let stats = new ProjectileStats(2, 1, 5, 1) let projectile = HomingProjectile.createHomingProjectile(this.world, this.getPosition(), this.player, closestTargetTo[1]!, stats, 'yellow') this.projectiles.push(projectile) return true