mirror of
https://github.com/Sheldan/canvas.git
synced 2026-01-01 14:58:51 +00:00
survivors: madding death split mechanic to projectiles
adding generic method for coordinate splitting around points refactored projectile stats and weapon stats
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user