slop game oder so
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Wiederverwendbare Projektile (Object Pooling).
|
||||
*
|
||||
* Bei Dauerfeuer entstehen Hunderte Projektile pro Minute. Statt sie jedes Mal neu
|
||||
* zu erzeugen und zu zerstören (Garbage-Collector-Ruckler), werden deaktivierte
|
||||
* Projektile wiederverwendet.
|
||||
* @module entities/ProjectilePool
|
||||
*/
|
||||
|
||||
export class ProjectilePool {
|
||||
/**
|
||||
* @param {Phaser.Scene} scene
|
||||
* @param {string} textureKey
|
||||
* @param {number} maxSize Obergrenze gleichzeitig fliegender Projektile.
|
||||
* @param {number} depth
|
||||
*/
|
||||
constructor(scene, textureKey, maxSize, depth) {
|
||||
this.scene = scene;
|
||||
this.textureKey = textureKey;
|
||||
this.depth = depth;
|
||||
this.group = scene.physics.add.group({
|
||||
classType: Phaser.Physics.Arcade.Image,
|
||||
maxSize,
|
||||
allowGravity: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Feuert ein Projektil ab.
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @param {number} angle Bogenmaß.
|
||||
* @param {number} speed px/s
|
||||
* @param {number} damage
|
||||
* @param {number} range Maximale Flugstrecke in px.
|
||||
* @param {string} [textureKey] Abweichende Textur (z. B. Geschütz).
|
||||
* @returns {Phaser.Physics.Arcade.Image|null} null, wenn der Pool erschöpft ist.
|
||||
*/
|
||||
fire(x, y, angle, speed, damage, range, textureKey) {
|
||||
const projectile = this.group.get(x, y, textureKey ?? this.textureKey);
|
||||
if (!projectile) return null;
|
||||
projectile.enableBody(true, x, y, true, true);
|
||||
projectile.setTexture(textureKey ?? this.textureKey);
|
||||
projectile.setDepth(this.depth);
|
||||
projectile.setRotation(angle);
|
||||
this.scene.physics.velocityFromRotation(angle, speed, projectile.body.velocity);
|
||||
projectile.damage = damage;
|
||||
projectile.spawnX = x;
|
||||
projectile.spawnY = y;
|
||||
projectile.maxTravelSq = range * range;
|
||||
return projectile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deaktiviert Projektile, die ihre Reichweite überschritten oder die Welt verlassen haben.
|
||||
* @param {Phaser.Geom.Rectangle} bounds
|
||||
*/
|
||||
update(bounds) {
|
||||
for (const projectile of this.group.getChildren()) {
|
||||
if (!projectile.active) continue;
|
||||
const dx = projectile.x - projectile.spawnX;
|
||||
const dy = projectile.y - projectile.spawnY;
|
||||
if (dx * dx + dy * dy > projectile.maxTravelSq || !bounds.contains(projectile.x, projectile.y)) {
|
||||
this.kill(projectile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {Phaser.Physics.Arcade.Image} projectile */
|
||||
kill(projectile) {
|
||||
projectile.disableBody(true, true);
|
||||
}
|
||||
|
||||
/** @returns {number} Aktive Projektile. */
|
||||
get activeCount() {
|
||||
return this.group.countActive(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user