feat: migrate JavaScript files to TypeScript, enhancing type safety and maintainability across the codebase
This commit is contained in:
parent
3db2bb9160
commit
c582f2004e
107 changed files with 5876 additions and 3588 deletions
139
src/systems/VFXSystem.ts
Normal file
139
src/systems/VFXSystem.ts
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
import { System } from '../core/System.ts';
|
||||
import { Palette } from '../core/Palette.ts';
|
||||
import { SystemName, ComponentType, VFXType } from '../core/Constants.ts';
|
||||
import type { Entity } from '../core/Entity.ts';
|
||||
import type { Position } from '../components/Position.ts';
|
||||
import type { PlayerControllerSystem } from './PlayerControllerSystem.ts';
|
||||
|
||||
interface Particle {
|
||||
x: number;
|
||||
y: number;
|
||||
vx: number;
|
||||
vy: number;
|
||||
lifetime: number;
|
||||
size: number;
|
||||
color: string;
|
||||
type: VFXType;
|
||||
}
|
||||
|
||||
/**
|
||||
* System responsible for creating and updating visual effects particles.
|
||||
*/
|
||||
export class VFXSystem extends System {
|
||||
particles: Particle[];
|
||||
|
||||
constructor() {
|
||||
super(SystemName.VFX);
|
||||
this.requiredComponents = [];
|
||||
this.priority = 40;
|
||||
this.particles = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all active particles, applying movement, attraction, and drag.
|
||||
* @param deltaTime - Time elapsed since last frame in seconds
|
||||
* @param _entities - Filtered entities
|
||||
*/
|
||||
process(deltaTime: number, _entities: Entity[]): void {
|
||||
const playerController = this.engine.systems.find(
|
||||
(s) => s.name === SystemName.PLAYER_CONTROLLER
|
||||
) as PlayerControllerSystem | undefined;
|
||||
const player = playerController ? playerController.getPlayerEntity() : null;
|
||||
const playerPos = player ? player.getComponent<Position>(ComponentType.POSITION) : null;
|
||||
|
||||
for (let i = this.particles.length - 1; i >= 0; i--) {
|
||||
const p = this.particles[i];
|
||||
|
||||
p.lifetime -= deltaTime;
|
||||
if (p.lifetime <= 0) {
|
||||
this.particles.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p.type === VFXType.ABSORPTION && playerPos) {
|
||||
const dx = playerPos.x - p.x;
|
||||
const dy = playerPos.y - p.y;
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (dist > 5) {
|
||||
p.vx += (dx / dist) * 800 * deltaTime;
|
||||
p.vy += (dy / dist) * 800 * deltaTime;
|
||||
p.vx *= 0.95;
|
||||
p.vy *= 0.95;
|
||||
} else {
|
||||
this.particles.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
p.vx *= 0.9;
|
||||
p.vy *= 0.9;
|
||||
}
|
||||
|
||||
p.x += p.vx * deltaTime;
|
||||
p.y += p.vy * deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an impact particle explosion at a specific location.
|
||||
* @param x - Horizontal coordinate
|
||||
* @param y - Vertical coordinate
|
||||
* @param color - The color of particles
|
||||
* @param angle - The direction of the impact splash
|
||||
*/
|
||||
createImpact(x: number, y: number, color = Palette.WHITE, angle: number | null = null): void {
|
||||
const count = 8;
|
||||
for (let i = 0; i < count; i++) {
|
||||
let vx: number, vy: number;
|
||||
if (angle !== null) {
|
||||
const spread = (Math.random() - 0.5) * 2;
|
||||
const speed = 50 + Math.random() * 150;
|
||||
vx = Math.cos(angle + spread) * speed;
|
||||
vy = Math.sin(angle + spread) * speed;
|
||||
} else {
|
||||
vx = (Math.random() - 0.5) * 150;
|
||||
vy = (Math.random() - 0.5) * 150;
|
||||
}
|
||||
|
||||
this.particles.push({
|
||||
x,
|
||||
y,
|
||||
vx,
|
||||
vy,
|
||||
lifetime: 0.2 + Math.random() * 0.3,
|
||||
size: 1 + Math.random() * 2,
|
||||
color: color,
|
||||
type: VFXType.IMPACT,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create absorption particles that fly towards the player.
|
||||
* @param x - Starting horizontal coordinate
|
||||
* @param y - Starting vertical coordinate
|
||||
* @param color - The color of particles
|
||||
*/
|
||||
createAbsorption(x: number, y: number, color = Palette.CYAN): void {
|
||||
for (let i = 0; i < 12; i++) {
|
||||
this.particles.push({
|
||||
x,
|
||||
y,
|
||||
vx: (Math.random() - 0.5) * 100,
|
||||
vy: (Math.random() - 0.5) * 100,
|
||||
lifetime: 1.5,
|
||||
size: 2,
|
||||
color: color,
|
||||
type: VFXType.ABSORPTION,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all currently active particles.
|
||||
* @returns Array of particle data objects
|
||||
*/
|
||||
getParticles(): Particle[] {
|
||||
return this.particles;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue