mirror of
https://github.com/Sheldan/canvas.git
synced 2026-04-15 12:10:20 +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() {
|
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)
|
let projectile = StraightProjectile.createStraightProjectile(this.world, this._position, this.world.player.position, this, stats)
|
||||||
this.projectiles.push(projectile)
|
this.projectiles.push(projectile)
|
||||||
return projectile
|
return projectile
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type {Acting, Drawable, Healthy, Weapon} from "./interfaces.ts";
|
import type {Acting, Drawable, Healthy, Weapon} from "./interfaces.ts";
|
||||||
import {Vector} from "./base.ts";
|
import {Vector} from "./base.ts";
|
||||||
import {drawDot} from "./utils.ts";
|
import {drawDot, getCoordinatesSplit} from "./utils.ts";
|
||||||
|
|
||||||
export class Player implements Drawable, Acting, Healthy {
|
export class Player implements Drawable, Acting, Healthy {
|
||||||
private _position: Vector;
|
private _position: Vector;
|
||||||
@@ -37,17 +37,13 @@ export class Player implements Drawable, Acting, Healthy {
|
|||||||
addWeapon(weapon: Weapon) {
|
addWeapon(weapon: Weapon) {
|
||||||
let weaponCount = this._weapons.length + 1;
|
let weaponCount = this._weapons.length + 1;
|
||||||
let angle = 2 * Math.PI / weaponCount;
|
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 affectedWeapon = this._weapons[i];
|
||||||
let x = Math.cos(angle * i)
|
affectedWeapon.setOffset(value.multiply(affectedWeapon.getSize()))
|
||||||
let y = Math.sin(angle * i)
|
|
||||||
console.log(x + ' ' + y)
|
|
||||||
affectedWeapon.setOffset(new Vector(x, y).multiply(affectedWeapon.getSize()))
|
|
||||||
}
|
}
|
||||||
let newPosition = new Vector(Math.cos(angle * (weaponCount - 1)), Math.sin(angle * (weaponCount - 1)));
|
weapon.setOffset(points[points.length - 1].multiply(weapon.getSize()))
|
||||||
newPosition = newPosition.multiply(weapon.getSize())
|
|
||||||
console.log(newPosition.x + ' ' + newPosition.y)
|
|
||||||
weapon.setOffset(newPosition)
|
|
||||||
this._weapons.push(weapon)
|
this._weapons.push(weapon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ export class World {
|
|||||||
this._enemies = this._enemies.filter(item => item !== enemy)
|
this._enemies = this._enemies.filter(item => item !== enemy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxValue() {
|
||||||
|
return Math.max(this.size.x, this.size.y)
|
||||||
|
}
|
||||||
|
|
||||||
get enemies(): [Enemy] {
|
get enemies(): [Enemy] {
|
||||||
return this._enemies;
|
return this._enemies;
|
||||||
|
|||||||
@@ -2,7 +2,15 @@ import type {Acting, Placeable, Healthy} from "./interfaces.ts";
|
|||||||
import type {Vector} from "./base.ts";
|
import type {Vector} from "./base.ts";
|
||||||
import {World} from "./World.ts";
|
import {World} from "./World.ts";
|
||||||
import {Cooldown, Point, Vector} from "./base.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";
|
import {InstanceOfUtils} from "./instance.ts";
|
||||||
|
|
||||||
export abstract class Projectile implements Acting, Placeable {
|
export abstract class Projectile implements Acting, Placeable {
|
||||||
@@ -27,6 +35,10 @@ export abstract class Projectile implements Acting, Placeable {
|
|||||||
this.status = new ProjectileStatus(stats.piercings)
|
this.status = new ProjectileStatus(stats.piercings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
this.world.removeProjectile(this)
|
||||||
|
}
|
||||||
|
|
||||||
act() {
|
act() {
|
||||||
this.move()
|
this.move()
|
||||||
if(this.parent !== this.world.player) {
|
if(this.parent !== this.world.player) {
|
||||||
@@ -45,11 +57,11 @@ export abstract class Projectile implements Acting, Placeable {
|
|||||||
let healthy = target as Healthy;
|
let healthy = target as Healthy;
|
||||||
healthy.takeDamage(this.stats.damage)
|
healthy.takeDamage(this.stats.damage)
|
||||||
if(!this.status.hasPiercingLeft()) {
|
if(!this.status.hasPiercingLeft()) {
|
||||||
this.world.removeProjectile(this)
|
this.die()
|
||||||
}
|
}
|
||||||
this.status.decreasePiercings()
|
this.status.decreasePiercings()
|
||||||
} else {
|
} else {
|
||||||
this.world.removeProjectile(this)
|
this.die()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.lastColliding = target;
|
this.lastColliding = target;
|
||||||
@@ -66,15 +78,13 @@ export abstract class Projectile implements Acting, Placeable {
|
|||||||
|
|
||||||
checkWorldBorder() {
|
checkWorldBorder() {
|
||||||
if(this.world.outside(this.position)) {
|
if(this.world.outside(this.position)) {
|
||||||
this.world.removeProjectile(this)
|
this.die()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impactPlayer() {
|
impactPlayer() {
|
||||||
this.world.player.takeDamage(this.stats.damage)
|
this.world.player.takeDamage(this.stats.damage)
|
||||||
if(!this.status.hasPiercingLeft()) {
|
this.die()
|
||||||
this.world.removeProjectile(this)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
draw(ctx: CanvasRenderingContext2D) {
|
draw(ctx: CanvasRenderingContext2D) {
|
||||||
@@ -152,7 +162,7 @@ export class HomingProjectile extends Projectile {
|
|||||||
if(pointOnLineWithinLine(this.target.getPosition(), this.lastPosition, this.position)) {
|
if(pointOnLineWithinLine(this.target.getPosition(), this.lastPosition, this.position)) {
|
||||||
justMovedDirection = olderMovedDirection
|
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 {
|
} else {
|
||||||
if(pointOnLineWithinLine(this.target.getPosition(), this.lastPosition, this.position)) {
|
if(pointOnLineWithinLine(this.target.getPosition(), this.lastPosition, this.position)) {
|
||||||
@@ -173,6 +183,22 @@ export class HomingProjectile extends Projectile {
|
|||||||
return 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 {
|
export class ProjectileStatus {
|
||||||
@@ -204,16 +230,46 @@ export class ProjectileStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ProjectileStats {
|
export class ProjectileStats {
|
||||||
|
|
||||||
private _piercings: number;
|
private _piercings: number;
|
||||||
private _size: number;
|
private _size: number;
|
||||||
private _damage: number;
|
private _damage: number;
|
||||||
private _speed: number;
|
private _speed: number;
|
||||||
|
private _deathSplit: number;
|
||||||
|
private _deathSplitChance: number;
|
||||||
|
|
||||||
constructor(piercings: number, size: number, damage: number, _speed: number) {
|
constructor() {
|
||||||
this._piercings = piercings;
|
this._size = 1
|
||||||
this._size = size;
|
}
|
||||||
this._damage = damage
|
|
||||||
this._speed = _speed;
|
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 {
|
get piercings(): number {
|
||||||
@@ -232,4 +288,13 @@ export class ProjectileStats {
|
|||||||
get damage(): number {
|
get damage(): number {
|
||||||
return this._damage;
|
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);
|
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 range = this.calculateRange()
|
||||||
let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position, range);
|
let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position, range);
|
||||||
if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined) {
|
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')
|
let projectile = HomingProjectile.createHomingProjectile(this.world, this.getPosition(), this.player, closestTargetTo[1]!, stats, 'yellow')
|
||||||
this.projectiles.push(projectile)
|
this.projectiles.push(projectile)
|
||||||
return true
|
return true
|
||||||
@@ -90,7 +94,9 @@ export class HomingPistol extends RangeWeapon {
|
|||||||
if(!offset) {
|
if(!offset) {
|
||||||
offset = new Vector(5, 5)
|
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)
|
let pistol = new HomingPistol(world, stats)
|
||||||
pistol.offset = offset;
|
pistol.offset = offset;
|
||||||
pistol.size = 5;
|
pistol.size = 5;
|
||||||
@@ -110,7 +116,11 @@ export class Pistol extends RangeWeapon {
|
|||||||
let range = this.calculateRange()
|
let range = this.calculateRange()
|
||||||
let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position, range);
|
let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position, range);
|
||||||
if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined) {
|
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')
|
let projectile = StraightProjectile.createStraightProjectile(this.world, this.getPosition(), closestTargetTo[1]!.getPosition(), this.player, stats, 'pink')
|
||||||
this.projectiles.push(projectile)
|
this.projectiles.push(projectile)
|
||||||
return true
|
return true
|
||||||
@@ -123,11 +133,9 @@ export class Pistol extends RangeWeapon {
|
|||||||
if(!offset) {
|
if(!offset) {
|
||||||
offset = new Vector(5, 5)
|
offset = new Vector(5, 5)
|
||||||
}
|
}
|
||||||
let stats = new WeaponStats(0,
|
let stats = new WeaponStats()
|
||||||
1,
|
.withProjectileSpeed(5)
|
||||||
5,
|
.withDamage(5)
|
||||||
2,
|
|
||||||
5)
|
|
||||||
let pistol = new Pistol(world, stats)
|
let pistol = new Pistol(world, stats)
|
||||||
pistol.offset = offset;
|
pistol.offset = offset;
|
||||||
pistol.size = 5;
|
pistol.size = 5;
|
||||||
@@ -139,13 +147,43 @@ export class Pistol extends RangeWeapon {
|
|||||||
|
|
||||||
|
|
||||||
export class WeaponStats {
|
export class WeaponStats {
|
||||||
constructor(private _weaponRange: number,
|
|
||||||
private _weaponRangeFactor: number,
|
private _weaponRange: number;
|
||||||
private _projectileSpeed: number,
|
private _weaponRangeFactor: number;
|
||||||
private _projectilePiercings: number,
|
private _projectileSpeed: number;
|
||||||
private _damage: 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 {
|
get weaponRange(): number {
|
||||||
return this._weaponRange;
|
return this._weaponRange;
|
||||||
|
|||||||
Reference in New Issue
Block a user