pixijs-scene-particle-container

Par pixijs · pixijs-skills

Utilisez cette skill pour afficher des milliers de sprites légers dans PixiJS v8. Couvre `ParticleContainer` avec les instances `Particle`, `addParticle`/`removeParticle`, le tableau `particleChildren`, `dynamicProperties` (`vertex`, `position`, `rotation`, `uvs`, `color`), `boundsArea`, `roundPixels`, `update`. Se déclenche sur : `ParticleContainer`, `Particle`, `IParticle`, `addParticle`, `particleChildren`, `dynamicProperties`, `boundsArea`, effets de particules, options de constructeur, `ParticleContainerOptions`, `ParticleOptions`.

npx skills add https://github.com/pixijs/pixijs-skills --skill pixijs-scene-particle-container

ParticleContainer est un conteneur spécialisé pour afficher des centaines à des dizaines de milliers de sprites légers en un seul appel de dessin. Utilisez-le pour les effets de particules, les motifs de projectiles ou tout cas où vous avez besoin d'un grand nombre d'objets similaires avec une surcharge minimale par objet. Les particules partagent une seule texture de base et ont un ensemble de transformation limité ; ce ne sont pas des enfants Container complets.

Suppose une familiarité avec pixijs-scene-core-concepts. ParticleContainer est une feuille spéciale dans un autre sens : elle contient des instances Particle dans son propre tableau particleChildren et rejette les enfants PixiJS normaux. Utilisez addParticle, pas addChild, et enveloppez l'ensemble du ParticleContainer dans un Container si vous devez le grouper avec d'autres objets de la scène.

L'API Particle est nouvelle en v8 mais est stable pour une utilisation en production.

Démarrage rapide

const texture = await Assets.load("particle.png");

const container = new ParticleContainer({
  texture,
  boundsArea: new Rectangle(0, 0, app.screen.width, app.screen.height),
  dynamicProperties: {
    position: true,
    rotation: false,
    color: false,
  },
});

for (let i = 0; i < 10000; i++) {
  container.addParticle(
    new Particle({
      texture,
      x: Math.random() * app.screen.width,
      y: Math.random() * app.screen.height,
    }),
  );
}

app.stage.addChild(container);

Compétences associées : pixijs-scene-core-concepts (bases du graphe de scène), pixijs-scene-sprite (quand vous avez besoin de toutes les fonctionnalités par objet), pixijs-assets (textures partagées, atlases), pixijs-performance (batching, optimisation de texture), pixijs-scene-container (envelopper avec d'autres objets d'affichage).

Options du constructeur

ParticleContainerOptions

Toutes les options Container (position, scale, tint, label, filters, zIndex, etc.) sont également valides ici — voir skills/pixijs-scene-core-concepts/references/constructor-options.md. Notez que children est omis : utilisez particles à la place.

Option Type Défaut Description
texture Texture null Texture de base partagée pour toutes les particules. Si omise, le conteneur revient à la texture de la première particule ajoutée ; chaque particule doit partager la même source de texture de base.
particles T[] [] Tableau initial d'instances Particle (ou IParticle). Équivalent à appeler addParticle pour chacune, mais saute les mises à jour de vue par appel.
dynamicProperties ParticleProperties { vertex: false, position: true, rotation: false, uvs: false, color: false } Drapeaux pour les attributs de particule qui se chargent à nouveau sur le GPU à chaque frame. Seule position est dynamique par défaut ; marquez ce que vous animez, laissez le reste statique pour la vitesse.
roundPixels boolean false Arrondit les positions des particules au pixel le plus proche. Produit un rendu plus net pour les styles pixel art au coût du mouvement fluide sub-pixel.
shader Shader shader de particules par défaut Remplace le shader de particules par défaut. Le shader personnalisé doit déclarer aPosition, aUV, aColor, plus tous les attributs dynamiques uniquement activés via dynamicProperties.

boundsArea est hérité de Container mais est effectivement requis sur ParticleContainer : le conteneur retourne des limites vides (0, 0, 0, 0) par défaut pour la performance, donc sans boundsArea il est éliminé comme invisible quand le culling est actif et containsPoint manque toujours.

ParticleOptions

Particle est une structure légère, pas une sous-classe Container — aucun des champs ContainerOptions ne s'applique. La liste complète des options :

Option Type Défaut Description
texture Texture Obligatoire. Texture utilisée pour afficher cette particule. Toutes les particules dans le même ParticleContainer doivent partager la même source de texture de base.
x number 0 Position X dans l'espace local du conteneur.
y number 0 Position Y dans l'espace local du conteneur.
scaleX number 1 Facteur d'échelle horizontal.
scaleY number 1 Facteur d'échelle vertical.
anchorX number 0 Ancre horizontale dans la plage 0–1 ; 0 est gauche, 0,5 est centre, 1 est droite.
anchorY number 0 Ancre verticale dans la plage 0–1 ; 0 est haut, 0,5 est centre, 1 est bas.
rotation number 0 Rotation en radians.
tint ColorSource 0xffffff Couleur de teinte comme nombre hexadécimal ou chaîne de couleur CSS. Combinée avec alpha dans le champ color interne.
alpha number 1 Transparence (0–1). Les valeurs en dehors de la plage sont limitées. Combinée avec tint dans le champ color interne.

Le constructeur accepte également une Texture brute comme seul argument (new Particle(texture)), qui est un raccourci pour new Particle({ texture }) en utilisant les valeurs par défaut ci-dessus.

Particle.defaultOptions est un objet statique que vous pouvez réassigner pour modifier les valeurs par défaut globalement ; voir la section « Création de particules » ci-dessous.

Motifs principaux

Création de particules

const particle = new Particle({
  texture,
  x: 100,
  y: 200,
  scaleX: 0.5,
  scaleY: 0.5,
  anchorX: 0.5,
  anchorY: 0.5,
  rotation: Math.PI / 4,
  tint: 0xff0000,
  alpha: 0.8,
});

container.addParticle(particle);

Particle est une structure légère avec des champs numériques plats : x, y, scaleX, scaleY, anchorX, anchorY, rotation, color, texture. Elle expose également tint (couleur hex/CSS) et alpha (0-1) comme setters qui se combinent dans le champ color interne. Pas de hiérarchie de transformation, pas d'événements, pas de filtres.

Vous pouvez passer une Texture directement comme seul argument : new Particle(texture).

Remplacez Particle.defaultOptions pour modifier les valeurs par défaut globalement :

Particle.defaultOptions = {
  ...Particle.defaultOptions,
  anchorX: 0.5,
  anchorY: 0.5,
};

Pré-remplissage avec l'option particles

const particles = Array.from(
  { length: 10000 },
  () =>
    new Particle({
      texture,
      x: Math.random() * 800,
      y: Math.random() * 600,
    }),
);

const container = new ParticleContainer({
  texture,
  boundsArea: new Rectangle(0, 0, 800, 600),
  particles,
});

Passer particles dans le constructeur est équivalent à créer le conteneur vide et appeler addParticle pour chacun, mais évite les mises à jour de vue par appel.

Propriétés dynamiques vs statiques et update()

const container = new ParticleContainer({
  dynamicProperties: {
    rotation: true,
  },
});

dynamicProperties contrôle quels attributs de particule se chargent à nouveau sur le GPU à chaque frame. Les valeurs par défaut sur ParticleContainer.defaultOptions.dynamicProperties sont :

{ vertex: false, position: true, rotation: false, uvs: false, color: false }

Vous devez uniquement remplacer les propriétés que vous animez ; le reste hérite des valeurs par défaut (position dynamique, tout le reste statique). Cinq propriétés au total :

  • vertex : sommets d'échelle/ancre
  • position
  • rotation
  • uvs : coordonnées de texture (pour les particules échangées de frames)
  • color : teinte et alpha

Marquez uniquement ce que vous animez ; les propriétés statiques sont moins chères. Si vous changez une propriété statique au runtime, appelez container.update() pour re-charger :

container.particleChildren.forEach((p) => {
  p.tint = 0x00ff00;
});
container.update();

Opérations par lots sur particleChildren

// Ajout en masse
const batch = [];
for (let i = 0; i < 5000; i++) {
  batch.push(
    new Particle({ texture, x: Math.random() * 800, y: Math.random() * 600 }),
  );
}
container.particleChildren.push(...batch);
container.update();

// Suppression en masse
container.particleChildren.length = 0;
container.update();

addParticle, addParticleAt, removeParticle, removeParticleAt, et removeParticles déclenchent tous les mises à jour de vue par appel. Pour les opérations par lots volumineuses, la manipulation directe du tableau plus un unique update() est plus rapide.

Options de texture et de shader

texture dans ParticleContainerOptions est facultative. Si omise, le conteneur revient à la texture de la première particule ajoutée ; chaque particule suivante doit partager la même source de texture de base. Définissez-la explicitement quand vous voulez déclarer l'atlas à l'avance, ou quand la première particule pourrait changer pendant l'exécution :

const container = new ParticleContainer({ texture });

shader vous permet de remplacer le shader de particules par défaut par n'importe quelle instance Shader. Le shader personnalisé doit déclarer les attributs que le pipe de particules charge (aPosition, aUV, aColor, plus tous les attributs dynamiques uniquement activés via dynamicProperties). Utilisez ceci pour des mathématiques de mélange personnalisées, des sprites en distance-field, ou des effets non-standard :

const container = new ParticleContainer({ texture, shader: myCustomShader });

Limitations

ParticleContainer sacrifie intentionnellement des fonctionnalités pour la vitesse :

  • Pas de filtres, de masques ou de modes de mélange sur les particules individuelles.
  • Pas d'enfants imbriqués sur les particules.
  • Pas de calcul automatique des limites.
  • Toutes les particules doivent partager la même source de texture de base (les atlases fonctionnent ; les textures multiples non liées ne fonctionnent pas).
  • Les shaders personnalisés sont pris en charge via l'option shader.

Migration des méthodes Container

ParticleContainer utilise une API de gestion des enfants séparée optimisée pour les mises à jour du buffer GPU. Les méthodes standard des enfants de Container lèvent une exception quand elles sont appelées sur un ParticleContainer.

Méthode Container standard Équivalent ParticleContainer
addChild(child) addParticle(particle)
removeChild(child) removeParticle(particle)
addChildAt(child, index) addParticleAt(particle, index)
removeChildAt(index) removeParticleAt(index)
removeChildren(begin, end) removeParticles(begin, end)
getChildAt(index) Accédez à container.particleChildren[index] directement
swapChildren() Non disponible
reparentChild() Non disponible

Erreurs courantes

[CRITIQUE] Ajouter des Sprites à ParticleContainer

Incorrect :

const container = new ParticleContainer();
const sprite = new Sprite(texture);
container.addChild(sprite);

Correct :

const container = new ParticleContainer();
const particle = new Particle(texture);
container.addParticle(particle);

ParticleContainer n'accepte pas les enfants Sprite. addChild lève une erreur. Les particules doivent être des instances Particle (ou tout objet implémentant IParticle), ajoutées via addParticle. C'est une refonte complète par rapport à v7, où ParticleContainer acceptait les enfants Sprite.

[HAUTE] Ne pas définir boundsArea sur ParticleContainer

Incorrect :

const container = new ParticleContainer();
// bounds est toujours (0, 0, 0, 0) — culling et hit testing échouent

Correct :

const container = new ParticleContainer({
  boundsArea: new Rectangle(0, 0, 800, 600),
});

ParticleContainer retourne des limites vides (0, 0, 0, 0) par défaut pour la performance. Sans boundsArea, le conteneur est éliminé comme invisible quand le culling est actif, et containsPoint manque toujours. Définissez boundsArea à la région où se trouvent vos particules.

[HAUTE] Utiliser children au lieu de particleChildren

Incorrect :

container.addParticle(new Particle(texture));
console.log(container.children.length); // 0

Correct :

container.addParticle(new Particle(texture));
console.log(container.particleChildren.length); // 1

Les particules sont stockées dans le tableau particleChildren, pas children. Le tableau standard Container.children est vide sur un ParticleContainer. Toute énumération, comptage et manipulation de particules doit utiliser particleChildren plus les méthodes *Particle.

[MOYEN] N'utilisez pas ParticleContainer comme conteneur normal

ParticleContainer contient des particules, pas des objets d'affichage. Si vous devez grouper un système de particules avec un sprite de fond ou une superposition d'interface utilisateur, enveloppez le ParticleContainer lui-même dans un Container ordinaire :

const world = new Container();
world.addChild(backgroundSprite, particleContainer, uiLayer);

Référence API

Skills similaires