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/ancrepositionrotationuvs: 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);