163 lines
4.2 KiB
JavaScript
163 lines
4.2 KiB
JavaScript
import { Witch } from './Witch.js';
|
|
import { WitchProjectile } from './WitchProjectile.js';
|
|
import { Vector2D } from '../engine/Vector2D.js';
|
|
|
|
export class MegaWitch extends Witch {
|
|
constructor(
|
|
x,
|
|
y,
|
|
target,
|
|
{
|
|
container,
|
|
viewport,
|
|
speed = 55,
|
|
size = 52,
|
|
color = [0.8, 0.15, 0.7, 1],
|
|
health = 22,
|
|
knockback = 130,
|
|
scoreValue = 12,
|
|
preferredDistance = 240,
|
|
fireInterval = 2,
|
|
projectileSpeed = 240,
|
|
projectileCount = 3,
|
|
projectileSpread = 0.35,
|
|
projectileColor = [1, 0.3, 0.3, 1],
|
|
novaInterval = 5,
|
|
novaCount = 16,
|
|
novaProjectileSpeed = 250,
|
|
spawnProjectile = (p) => {},
|
|
spawnOnDeath = () => {},
|
|
spawnCount = 3,
|
|
} = {},
|
|
) {
|
|
super(x, y, target, {
|
|
container,
|
|
viewport,
|
|
speed,
|
|
size,
|
|
color,
|
|
health,
|
|
knockback,
|
|
scoreValue,
|
|
preferredDistance,
|
|
fireInterval,
|
|
projectileSpeed,
|
|
projectileCount,
|
|
projectileSpread,
|
|
projectileColor,
|
|
spawnProjectile,
|
|
onDeath: (mega) => {
|
|
for (let i = 0; i < spawnCount; i += 1) {
|
|
const angle = (i / spawnCount) * Math.PI * 2;
|
|
const offset = mega.size + 30;
|
|
spawnOnDeath(
|
|
mega.pos.x + Math.cos(angle) * offset,
|
|
mega.pos.y + Math.sin(angle) * offset,
|
|
target,
|
|
container,
|
|
);
|
|
}
|
|
},
|
|
});
|
|
this.novaInterval = novaInterval;
|
|
this.novaCount = novaCount;
|
|
this.novaProjectileSpeed = novaProjectileSpeed;
|
|
this._novaTimer = novaInterval * 0.5;
|
|
this._novaRotation = Math.random() * Math.PI * 2;
|
|
this._pendingNova = [];
|
|
}
|
|
|
|
update(dt) {
|
|
super.update(dt);
|
|
|
|
if (this.target.health <= 0) return;
|
|
|
|
for (let i = this._pendingNova.length - 1; i >= 0; i -= 1) {
|
|
const entry = this._pendingNova[i];
|
|
entry.remaining -= dt;
|
|
if (entry.remaining <= 0) {
|
|
this._pendingNova.splice(i, 1);
|
|
entry.fire();
|
|
}
|
|
}
|
|
|
|
this._novaTimer -= dt;
|
|
if (this._novaTimer <= 0) {
|
|
this._novaTimer = this.novaInterval * (0.85 + Math.random() * 0.3);
|
|
this.nova();
|
|
}
|
|
}
|
|
|
|
nova() {
|
|
const lost = 1 - Math.max(0, this.health / this.maxHealth);
|
|
const count = Math.max(6, Math.round(this.novaCount * (0.75 + 0.25 * lost)));
|
|
const speed = this.novaProjectileSpeed * (1 + lost * 0.45);
|
|
const size = this.size * 0.3;
|
|
const color = [1, 0.5, 0.3, 1];
|
|
this._novaRotation += 0.36;
|
|
|
|
const fireRing = (offset) => {
|
|
for (let i = 0; i < count; i += 1) {
|
|
const angle = (i / count) * Math.PI * 2 + this._novaRotation + offset;
|
|
const direction = new Vector2D(Math.cos(angle), Math.sin(angle));
|
|
const projectile = new WitchProjectile(this.pos.x, this.pos.y, direction, {
|
|
container: this.container,
|
|
viewport: this.viewport,
|
|
speed,
|
|
size,
|
|
color,
|
|
});
|
|
this.spawnProjectile(projectile);
|
|
}
|
|
};
|
|
|
|
fireRing(0);
|
|
this._pendingNova.push({
|
|
remaining: 0.22,
|
|
fire: () => fireRing(Math.PI / count),
|
|
});
|
|
if (lost > 0.34) {
|
|
this._pendingNova.push({
|
|
remaining: 0.44,
|
|
fire: () => fireRing(0),
|
|
});
|
|
}
|
|
this._cast = 0.32;
|
|
}
|
|
|
|
draw(renderer) {
|
|
const charge = 1 - Math.max(0, this._novaTimer) / this.novaInterval;
|
|
if (charge > 0.72) {
|
|
const hp = Math.max(0, this.health / this.maxHealth);
|
|
const punch = (charge - 0.72) / 0.28;
|
|
const r = this.size * (0.6 + punch * 1.7) * (1.4 - hp * 0.6);
|
|
renderer.setBlendMode('additive');
|
|
renderer.drawTexture(
|
|
renderer.glowTexture,
|
|
this.pos.x - r,
|
|
this.pos.y - r,
|
|
r * 2,
|
|
r * 2,
|
|
[1, 0.3, 0.15, punch * 0.7],
|
|
);
|
|
renderer.drawTexture(
|
|
renderer.ringTexture,
|
|
this.pos.x - r * 1.5,
|
|
this.pos.y - r * 1.5,
|
|
r * 3,
|
|
r * 3,
|
|
[1, 0.45, 0.2, punch * 0.9],
|
|
);
|
|
renderer.drawTexture(
|
|
renderer.ringTexture,
|
|
this.pos.x - r * 2.1,
|
|
this.pos.y - r * 2.1,
|
|
r * 4.2,
|
|
r * 4.2,
|
|
[1, 0.25, 0.1, punch * 0.35],
|
|
);
|
|
renderer.setBlendMode('normal');
|
|
}
|
|
super.draw(renderer);
|
|
}
|
|
} |