diff --git a/absurd-survivors/src/Enemies.ts b/absurd-survivors/src/Enemies.ts index bb40fd1..e779c4a 100644 --- a/absurd-survivors/src/Enemies.ts +++ b/absurd-survivors/src/Enemies.ts @@ -123,7 +123,11 @@ export class ShootingEnemy extends BasicEnemy implements Shooting { } createProjectile() { - let stats = new ProjectileStats(0, 1, 5, 2) + let stats = new ProjectileStats() + .withPiercings(0) + .withSize(1) + .withDamage(5) + .withSpeed(2) let projectile = StraightProjectile.createStraightProjectile(this.world, this._position, this.world.player.position, this, stats) this.projectiles.push(projectile) return projectile diff --git a/absurd-survivors/src/Player.ts b/absurd-survivors/src/Player.ts index 4abedc3..88a23c8 100644 --- a/absurd-survivors/src/Player.ts +++ b/absurd-survivors/src/Player.ts @@ -1,6 +1,6 @@ import type {Acting, Drawable, Healthy, Weapon} from "./interfaces.ts"; import {Vector} from "./base.ts"; -import {drawDot} from "./utils.ts"; +import {drawDot, getCoordinatesSplit} from "./utils.ts"; export class Player implements Drawable, Acting, Healthy { private _position: Vector; @@ -37,17 +37,13 @@ export class Player implements Drawable, Acting, Healthy { addWeapon(weapon: Weapon) { let weaponCount = this._weapons.length + 1; let angle = 2 * Math.PI / weaponCount; - for (let i = 0; i < this._weapons.length; i++) { + let points = getCoordinatesSplit(weaponCount) + for (let i = 0; i < points.length - 1; i++){ + const value = points[i]; let affectedWeapon = this._weapons[i]; - let x = Math.cos(angle * i) - let y = Math.sin(angle * i) - console.log(x + ' ' + y) - affectedWeapon.setOffset(new Vector(x, y).multiply(affectedWeapon.getSize())) + affectedWeapon.setOffset(value.multiply(affectedWeapon.getSize())) } - let newPosition = new Vector(Math.cos(angle * (weaponCount - 1)), Math.sin(angle * (weaponCount - 1))); - newPosition = newPosition.multiply(weapon.getSize()) - console.log(newPosition.x + ' ' + newPosition.y) - weapon.setOffset(newPosition) + weapon.setOffset(points[points.length - 1].multiply(weapon.getSize())) this._weapons.push(weapon) } diff --git a/absurd-survivors/src/World.ts b/absurd-survivors/src/World.ts index 994de8e..c575325 100644 --- a/absurd-survivors/src/World.ts +++ b/absurd-survivors/src/World.ts @@ -60,6 +60,9 @@ export class World { this._enemies = this._enemies.filter(item => item !== enemy) } + maxValue() { + return Math.max(this.size.x, this.size.y) + } get enemies(): [Enemy] { return this._enemies; diff --git a/absurd-survivors/src/projectile.ts b/absurd-survivors/src/projectile.ts index bc4bfb2..ee1bb3f 100644 --- a/absurd-survivors/src/projectile.ts +++ b/absurd-survivors/src/projectile.ts @@ -2,7 +2,15 @@ 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, pointOnLineWithinLine, straightMove, toRad} from "./utils.ts"; +import { + circleLineCollision, + drawDot, + getCoordinatesSplit, + moveInDirectionOf, + pointOnLineWithinLine, + straightMove, + toRad +} from "./utils.ts"; import {InstanceOfUtils} from "./instance.ts"; export abstract class Projectile implements Acting, Placeable { @@ -27,6 +35,10 @@ export abstract class Projectile implements Acting, Placeable { this.status = new ProjectileStatus(stats.piercings) } + die() { + this.world.removeProjectile(this) + } + act() { this.move() if(this.parent !== this.world.player) { @@ -45,11 +57,11 @@ export abstract class Projectile implements Acting, Placeable { let healthy = target as Healthy; healthy.takeDamage(this.stats.damage) if(!this.status.hasPiercingLeft()) { - this.world.removeProjectile(this) + this.die() } this.status.decreasePiercings() } else { - this.world.removeProjectile(this) + this.die() } } this.lastColliding = target; @@ -66,15 +78,13 @@ export abstract class Projectile implements Acting, Placeable { checkWorldBorder() { if(this.world.outside(this.position)) { - this.world.removeProjectile(this) + this.die() } } impactPlayer() { this.world.player.takeDamage(this.stats.damage) - if(!this.status.hasPiercingLeft()) { - this.world.removeProjectile(this) - } + this.die() }; draw(ctx: CanvasRenderingContext2D) { @@ -152,7 +162,7 @@ export class HomingProjectile extends Projectile { 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)))) + this.target = new Point(this.position.add(justMovedDirection.multiply(this.world.maxValue()))) } } else { if(pointOnLineWithinLine(this.target.getPosition(), this.lastPosition, this.position)) { @@ -173,6 +183,22 @@ export class HomingProjectile extends Projectile { return projectile; } + + die() { + if(this.stats.deathSplit && this.stats.deathSplit > 0 && Math.random() > this.stats.deathSplitChance) { + let splits = this.stats.deathSplit; + let directionalVectors = getCoordinatesSplit(splits); + let stats = new ProjectileStats() + .withSize(this.stats.size / 2) + .withDamage(this.stats.damage / 2) + .withSpeed(this.stats.speed / 2) + directionalVectors.forEach(value => { + let target = this.position.add(value.multiply(this.world.maxValue())) + StraightProjectile.createStraightProjectile(this.world, this.position, target, this.parent, stats, 'white') + }) + } + super.die(); + } } export class ProjectileStatus { @@ -204,16 +230,46 @@ export class ProjectileStatus { } export class ProjectileStats { + private _piercings: number; private _size: number; private _damage: number; private _speed: number; + private _deathSplit: number; + private _deathSplitChance: number; - constructor(piercings: number, size: number, damage: number, _speed: number) { - this._piercings = piercings; - this._size = size; - this._damage = damage - this._speed = _speed; + constructor() { + this._size = 1 + } + + withPiercings(value: number) { + this._piercings = value; + return this; + } + + withSize(value: number) { + this._size = Math.max(value, 1); + return this; + } + + withDamage(value: number) { + this._damage = value; + return this; + } + + withSpeed(value: number) { + this._speed = value; + return this; + } + + withDeathSplit(value: number) { + this._deathSplit = value; + return this; + } + + withDeathSplitChance(value: number) { + this._deathSplitChance = value; + return this; } get piercings(): number { @@ -232,4 +288,13 @@ export class ProjectileStats { get damage(): number { return this._damage; } + + + get deathSplitChance(): number { + return this._deathSplitChance; + } + + get deathSplit(): number { + return this._deathSplit; + } } \ No newline at end of file diff --git a/absurd-survivors/src/utils.ts b/absurd-survivors/src/utils.ts index e76620e..cc19c47 100644 --- a/absurd-survivors/src/utils.ts +++ b/absurd-survivors/src/utils.ts @@ -66,4 +66,15 @@ export function circleLineCollision(circleCenter: Vector, radius: number, lineSt } return pointInsideCircle(circleCenter, radius, closestPoint); +} + +export function getCoordinatesSplit(amount: number) { + let angle = 2 * Math.PI / amount; + let points: Vector[] = []; + for (let i = 0; i < amount; i++) { + let x = Math.cos(angle * i) + let y = Math.sin(angle * i) + points.push(new Vector(x, y)) + } + return points; } \ No newline at end of file diff --git a/absurd-survivors/src/weapons.ts b/absurd-survivors/src/weapons.ts index 60def9a..a539650 100644 --- a/absurd-survivors/src/weapons.ts +++ b/absurd-survivors/src/weapons.ts @@ -77,7 +77,11 @@ export class HomingPistol extends RangeWeapon { let range = this.calculateRange() let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position, range); if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined) { - let stats = new ProjectileStats(this.stats.projectilePiercings, 1, this.stats.damage, this.stats.projectileSpeed) + let stats = new ProjectileStats() + .withPiercings(this.stats.projectilePiercings) + .withSize(1) + .withDamage(this.stats.damage) + .withSpeed(this.stats.projectileSpeed); let projectile = HomingProjectile.createHomingProjectile(this.world, this.getPosition(), this.player, closestTargetTo[1]!, stats, 'yellow') this.projectiles.push(projectile) return true @@ -90,7 +94,9 @@ export class HomingPistol extends RangeWeapon { if(!offset) { offset = new Vector(5, 5) } - let stats = new WeaponStats(0, 1, 3, 5, 5) + let stats = new WeaponStats() + .withProjectileSpeed(3) + .withDamage(5) let pistol = new HomingPistol(world, stats) pistol.offset = offset; pistol.size = 5; @@ -110,7 +116,11 @@ export class Pistol extends RangeWeapon { let range = this.calculateRange() let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position, range); if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined) { - let stats = new ProjectileStats(this.stats.projectilePiercings, 1, this.stats.damage, this.stats.projectileSpeed) + let stats = new ProjectileStats() + .withPiercings(this.stats.projectilePiercings) + .withSize(1) + .withDamage(this.stats.damage) + .withSpeed(this.stats.projectileSpeed); let projectile = StraightProjectile.createStraightProjectile(this.world, this.getPosition(), closestTargetTo[1]!.getPosition(), this.player, stats, 'pink') this.projectiles.push(projectile) return true @@ -123,11 +133,9 @@ export class Pistol extends RangeWeapon { if(!offset) { offset = new Vector(5, 5) } - let stats = new WeaponStats(0, - 1, - 5, - 2, - 5) + let stats = new WeaponStats() + .withProjectileSpeed(5) + .withDamage(5) let pistol = new Pistol(world, stats) pistol.offset = offset; pistol.size = 5; @@ -139,13 +147,43 @@ export class Pistol extends RangeWeapon { export class WeaponStats { - constructor(private _weaponRange: number, - private _weaponRangeFactor: number, - private _projectileSpeed: number, - private _projectilePiercings: number, - private _damage: number) { + + private _weaponRange: number; + private _weaponRangeFactor: number; + private _projectileSpeed: number; + private _projectilePiercings: number; + private _damage: number; + + constructor() { + this._weaponRangeFactor = 1 } + withWeaponRange(value: number) { + this._weaponRange = value; + return this; + } + + withWeaponRangeFactor(value: number) { + this._weaponRangeFactor = value; + return this; + } + + withProjectileSpeed(value: number) { + this._projectileSpeed = value; + return this; + } + + + withProjectilePiercings(value: number) { + this._projectilePiercings = value; + return this; + } + + + withDamage(value: number) { + this._damage = value; + return this; + } get weaponRange(): number { return this._weaponRange;