Files
Documentation/content/advanced/effects/particles.fr.md
2026-01-20 20:33:59 +01:00

21 KiB

title, type, weight
title type weight
Particules docs 1

Le système de particules de Hytale fournit des effets visuels riches à travers des émetteurs et renderers configurables. Créez des explosions, traînées, auras et effets visuels complexes avec un contrôle précis sur le comportement et l'apparence.

Package : com.hypixel.hytale.server.core.asset.type.particle

{{< cards cols="3" >}} {{< card link="#générer-des-particules" title="Génération" subtitle="Créer des effets de particules" icon="sparkles" >}} {{< card link="#configuration-du-système-de-particules" title="Configuration" subtitle="Config système et spawner" icon="adjustments" >}} {{< card link="#attracteurs-de-particules" title="Attracteurs" subtitle="Forces et mouvement" icon="arrow-circle-right" >}} {{< /cards >}}


Générer des Particules

Méthodes ParticleUtil

{{< tabs items="Basique,Avancé,WorldParticle" >}} {{< tab >}}

import com.hypixel.hytale.server.core.universe.world.ParticleUtil;

// Génération basique à une position (trouve auto les joueurs proches)
ParticleUtil.spawnParticleEffect(
    "explosion_small",           // ID du système de particules
    position,                    // Position Vector3d
    componentAccessor
);

// Générer pour des joueurs spécifiques
ParticleUtil.spawnParticleEffect(
    "magic_trail",
    position,
    playerRefs,                  // List<Ref<EntityStore>>
    componentAccessor
);

Distance de Diffusion : DEFAULT_PARTICLE_DISTANCE = 75 blocs

{{< /tab >}} {{< tab >}}

// Avec référence à l'entité source
ParticleUtil.spawnParticleEffect(
    "attack_swing",
    position,
    sourceEntityRef,             // Entité qui a généré ceci
    playerRefs,
    componentAccessor
);

// Avec contrôle de rotation
ParticleUtil.spawnParticleEffect(
    "directional_beam",
    position,
    yaw, pitch, roll,            // Angles de rotation
    sourceEntityRef,
    playerRefs,
    componentAccessor
);

// Avec échelle et couleur
ParticleUtil.spawnParticleEffect(
    "colored_burst",
    position,
    yaw, pitch, roll,
    2.0f,                        // Multiplicateur d'échelle
    new Color(255, 100, 50, 255), // Couleur RGBA
    playerRefs,
    componentAccessor
);

{{< /tab >}} {{< tab >}}

import com.hypixel.hytale.server.core.asset.type.particle.config.WorldParticle;

// Contrôle complet avec le wrapper WorldParticle
WorldParticle worldParticle = new WorldParticle(
    "my_particle_system",
    new Color(255, 100, 50, 255),  // Override couleur RGBA
    1.5f,                          // Multiplicateur d'échelle
    new Vector3f(0, 1, 0),         // Offset de position
    new Direction(0, 0, 0)         // Offset de rotation
);

ParticleUtil.spawnParticleEffect(
    worldParticle,
    position,
    sourceRef,
    playerRefs,
    componentAccessor
);

{{< /tab >}} {{< /tabs >}}


Configuration du Système de Particules

Classe ParticleSystem

La configuration racine pour un effet de particules :

public class ParticleSystem {
    protected String id;                        // Identifiant unique
    protected ParticleSpawnerGroup[] spawners;  // Configurations de spawners
    protected float lifeSpan;                   // Durée de vie du système (secondes)
    protected float cullDistance;               // Distance avant culling
    protected float boundingRadius;             // Boîte englobante de collision
    protected boolean isImportant;              // Flag de priorité réseau
}
Champ Type Description
id String Identifiant unique du système de particules
spawners ParticleSpawnerGroup[] Tableau de configurations de spawners
lifeSpan float Durée de vie du système (secondes)
cullDistance float Distance à laquelle les particules sont culled
boundingRadius float Sphère englobante pour les calculs de culling
isImportant boolean Si vrai, prioritisé dans la sync réseau

Configuration ParticleSpawner

Contrôle comment les particules individuelles sont émises :

{{< tabs items="Propriétés,Émission,Mouvement,Rendu" >}} {{< tab >}}

public class ParticleSpawner {
    protected String id;
    protected EmitShape shape;
    protected RangeVector3f emitOffset;
    protected boolean useEmitDirection;
    protected Range totalParticles;
    protected float lifeSpan;
    protected int maxConcurrentParticles;
    protected Rangef particleLifeSpan;
    protected Rangef spawnRate;
    protected boolean spawnBurst;
    protected InitialVelocity initialVelocity;
    protected ParticleAttractor[] attractors;
    protected FXRenderMode renderMode;
    protected float lightInfluence;
    protected Particle particle;
}

{{< /tab >}} {{< tab >}}

Propriétés d'Émission :

Propriété Type Description
shape EmitShape Forme d'émission Sphere ou Cube
emitOffset RangeVector3f Plage d'offset aléatoire depuis l'origine
useEmitDirection boolean Utiliser la direction de spawn pour la vélocité
totalParticles Range Nombre min/max total de particules à émettre
spawnRate Rangef Particules par seconde
spawnBurst boolean Émettre tout d'un coup vs sur la durée

Exemple de config d'émission :

// Explosion burst - tout d'un coup
spawner.setSpawnBurst(true);
spawner.setTotalParticles(new Range(50, 100));

// Flux continu
spawner.setSpawnBurst(false);
spawner.setSpawnRate(new Rangef(10, 20)); // 10-20 par seconde
spawner.setLifeSpan(5.0f); // Émettre pendant 5 secondes

{{< /tab >}} {{< tab >}}

Propriétés de Mouvement :

Propriété Type Description
initialVelocity InitialVelocity Configuration de vélocité initiale
attractors ParticleAttractor[] Forces appliquées aux particules

Vélocité Initiale :

public class InitialVelocity {
    protected float speed;           // Vitesse de base
    protected float speedVariance;   // Variance aléatoire
    protected Vector3f direction;    // Direction de base
    protected float coneAngle;       // Angle de dispersion (degrés)
}

{{< /tab >}} {{< tab >}}

Propriétés de Rendu :

Propriété Type Description
renderMode FXRenderMode Comment les particules sont blendées
lightInfluence float Influence de l'éclairage sur les particules
particle Particle Config texture et animation

{{< /tab >}} {{< /tabs >}}


Formes d'Émission

Contrôle le volume depuis lequel les particules apparaissent :

public enum EmitShape {
    Sphere,     // Émettre depuis un volume sphérique
    Cube        // Émettre depuis un volume cubique
}

{{< tabs items="Sphere,Cube" >}} {{< tab >}}

Émission Sphérique :

Les particules apparaissent dans un volume sphérique, avec la direction pointant vers l'extérieur du centre :

// Configurer l'émission sphérique
spawner.setShape(EmitShape.Sphere);
spawner.setEmitOffset(new RangeVector3f(
    new Rangef(-1, 1),  // Plage X (rayon)
    new Rangef(-1, 1),  // Plage Y (rayon)
    new Rangef(-1, 1)   // Plage Z (rayon)
));

// Utiliser la direction d'émission pour la vélocité vers l'extérieur
spawner.setUseEmitDirection(true);

Idéal pour : Explosions, bursts, effets radiaux

{{< /tab >}} {{< tab >}}

Émission Cubique :

Les particules apparaissent dans un volume de boîte aligné sur les axes :

// Configurer l'émission cubique
spawner.setShape(EmitShape.Cube);
spawner.setEmitOffset(new RangeVector3f(
    new Rangef(-2, 2),  // Plage X
    new Rangef(0, 3),   // Plage Y (au-dessus du sol)
    new Rangef(-2, 2)   // Plage Z
));

Idéal pour : Effets de zone, pluie, effets au sol

{{< /tab >}} {{< /tabs >}}


Modes de Rendu

Détermine comment les particules se mélangent avec la scène :

public enum FXRenderMode {
    BlendLinear,   // Blending de transparence standard
    BlendAdd,      // Blending additif (brillant/lumineux)
    Erosion,       // Effet d'érosion/dissolution
    Distortion     // Effet de distorsion/réfraction
}

{{< tabs items="BlendLinear,BlendAdd,Erosion,Distortion" >}} {{< tab >}}

BlendLinear

Blending alpha standard. Idéal pour :

  • Fumée
  • Poussière
  • Nuages
  • Particules d'apparence solide
spawner.setRenderMode(FXRenderMode.BlendLinear);

{{< /tab >}} {{< tab >}}

BlendAdd

Blending additif - les particules ajoutent de la lumière à la scène. Idéal pour :

  • Feu
  • Étincelles
  • Effets magiques
  • Particules lumineuses
  • Rayons de lumière
spawner.setRenderMode(FXRenderMode.BlendAdd);

{{< callout type="info" >}} Utilisez BlendAdd pour tout effet lumineux ou brillant. Plusieurs particules superposées créeront des zones plus lumineuses. {{< /callout >}}

{{< /tab >}} {{< tab >}}

Erosion

Crée un effet visuel de dissolution/érosion. Idéal pour :

  • Désintégration
  • Transitions de dissolution
  • Dissipation d'énergie
spawner.setRenderMode(FXRenderMode.Erosion);

{{< /tab >}} {{< tab >}}

Distortion

Réfracte l'arrière-plan, créant des effets de miroitement de chaleur. Idéal pour :

  • Vagues de chaleur
  • Portails
  • Champs d'énergie
  • Effets sous-marins
spawner.setRenderMode(FXRenderMode.Distortion);

{{< callout type="warning" >}} Les effets de distorsion sont plus intensifs en GPU. Utilisez avec parcimonie. {{< /callout >}}

{{< /tab >}} {{< /tabs >}}


Attracteurs de Particules

Applique des forces aux particules pour un mouvement dynamique :

public class ParticleAttractor {
    protected Vector3f position;                // Position locale de l'attracteur
    protected Vector3f radialAxis;              // Direction de la force radiale
    protected float radius;                     // Rayon d'influence

    // Accélérations (forces continues)
    protected float radialAcceleration;         // Accélération vers l'extérieur/intérieur
    protected float radialTangentAcceleration;  // Accélération tangentielle (orbite)
    protected Vector3f linearAcceleration;      // Accélération linéaire directe

    // Impulsions (forces ponctuelles)
    protected float radialImpulse;              // Impulsion vers l'extérieur/intérieur
    protected float radialTangentImpulse;       // Impulsion tangentielle
    protected Vector3f linearImpulse;           // Impulsion linéaire directe

    // Amortissement
    protected Vector3f dampingMultiplier;       // Réduction de vélocité par frame
}

Types de Forces

{{< tabs items="Radiale,Tangentielle,Linéaire,Amortissement" >}} {{< tab >}}

Forces Radiales :

Pousse les particules vers ou loin de la position de l'attracteur :

ParticleAttractor attractor = new ParticleAttractor();
attractor.setPosition(new Vector3f(0, 0, 0)); // Centre du système

// Explosion vers l'extérieur
attractor.setRadialAcceleration(10.0f);  // Positif = vers l'extérieur

// Attraction vers l'intérieur (effet trou noir)
attractor.setRadialAcceleration(-5.0f);  // Négatif = vers l'intérieur

// Burst instantané vers l'extérieur
attractor.setRadialImpulse(20.0f);

{{< /tab >}} {{< tab >}}

Forces Tangentielles :

Crée un mouvement tourbillonnant/orbital autour de l'attracteur :

ParticleAttractor attractor = new ParticleAttractor();
attractor.setPosition(new Vector3f(0, 0, 0));
attractor.setRadialAxis(new Vector3f(0, 1, 0)); // Orbite autour de l'axe Y

// Tourbillon horaire
attractor.setRadialTangentAcceleration(5.0f);

// Anti-horaire
attractor.setRadialTangentAcceleration(-5.0f);

{{< /tab >}} {{< tab >}}

Forces Linéaires :

Applique une force directionnelle constante (comme la gravité ou le vent) :

ParticleAttractor attractor = new ParticleAttractor();

// Gravité (vers le bas)
attractor.setLinearAcceleration(new Vector3f(0, -9.8f, 0));

// Vent (horizontal)
attractor.setLinearAcceleration(new Vector3f(2.0f, 0, 0));

// Flottabilité vers le haut
attractor.setLinearAcceleration(new Vector3f(0, 3.0f, 0));

{{< /tab >}} {{< tab >}}

Amortissement :

Ralentit les particules au fil du temps :

ParticleAttractor attractor = new ParticleAttractor();

// Amortissement uniforme (résistance de l'air)
attractor.setDampingMultiplier(new Vector3f(0.98f, 0.98f, 0.98f));

// Fort amortissement horizontal, faible vertical
attractor.setDampingMultiplier(new Vector3f(0.9f, 0.99f, 0.9f));

// Pas d'amortissement (particules maintiennent leur vélocité)
attractor.setDampingMultiplier(new Vector3f(1.0f, 1.0f, 1.0f));

{{< callout type="info" >}} Les valeurs d'amortissement < 1.0 ralentissent les particules. Des valeurs de 0.98-0.99 donnent une résistance de l'air réaliste. {{< /callout >}}

{{< /tab >}} {{< /tabs >}}


Configuration Visuelle des Particules

Configure l'apparence et l'animation des particules :

public class Particle {
    protected String texture;                   // Chemin de l'atlas de texture
    protected Size frameSize;                   // Dimensions du frame

    protected ParticleUVOption uvOption;        // None, Animated, Random
    protected SoftParticle softParticle;        // Blending soft particle
    protected float softParticlesFadeFactor;    // 0.1 à 2.0

    // Animation
    protected ParticleAnimationFrame initialAnimationFrame;
    protected Map<Integer, ParticleAnimationFrame> animation;
}

Options d'Animation

public enum ParticleUVOption {
    None,       // Frame unique statique
    Animated,   // Jouer les frames en séquence
    Random      // Frame aléatoire par particule
}

Frames d'Animation

public class ParticleAnimationFrame {
    protected int frame;           // Numéro de frame dans l'atlas
    protected Rangef scale;        // Plage de taille
    protected Rangef alpha;        // Plage de transparence (0-1)
    protected Color color;         // Teinte de couleur
    protected Rangef rotation;     // Plage de rotation (degrés)
}

Accéder aux Assets de Particules

// Obtenir un système de particules par ID
ParticleSystem system = ParticleSystem.getAssetMap().getAsset("explosion_large");

// Obtenir la configuration d'un spawner
ParticleSpawner spawner = ParticleSpawner.getAssetMap().getAsset("fire_spawner");

// Utiliser dans les arguments de commande
// ArgTypes.PARTICLE_SYSTEM pour les paramètres de commande

Patterns Courants

Particules Basées sur les Événements

{{< callout type="warning" >}} Note : Les exemples ci-dessous sont simplifiés. Entity n'a pas de méthode getPosition() directe. Dans le code réel, obtenez la position via TransformComponent depuis le store de l'entité. Exemple :

TransformComponent transform = store.getComponent(entityRef, TransformComponent.getComponentType());
Vector3d position = transform.getPosition();

{{< /callout >}}

{{< tabs items="Destruction Bloc,Combat,Mort" >}} {{< tab >}}

@Subscribe
public void onBlockBreak(BreakBlockEvent event) {
    // Utiliser getTargetBlock() - pas getPosition()
    Vector3i blockPos = event.getTargetBlock();
    Vector3d pos = new Vector3d(
        blockPos.x + 0.5,
        blockPos.y + 0.5,
        blockPos.z + 0.5
    );

    // Générer des particules de destruction au centre du bloc
    ParticleUtil.spawnParticleEffect(
        "block_break_particles",
        pos,
        componentAccessor
    );
}

{{< /tab >}} {{< tab >}}

@Subscribe
public void onEntityDamage(EntityDamageEvent event) {
    Entity target = event.getTarget();
    Vector3d hitPos = target.getPosition().add(0, 1, 0);

    // Effet de sang/dégâts
    ParticleUtil.spawnParticleEffect(
        "damage_hit",
        hitPos,
        componentAccessor
    );

    // Effet spécial coup critique
    if (event.isCritical()) {
        ParticleUtil.spawnParticleEffect(
            "critical_hit_sparks",
            hitPos,
            0, 0, 0,    // rotation
            1.5f,       // échelle plus grande
            new Color(255, 215, 0, 255), // couleur or
            getNearbyPlayers(hitPos, 50),
            componentAccessor
        );
    }
}

{{< /tab >}} {{< tab >}}

@Subscribe
public void onEntityDeath(EntityDeathEvent event) {
    Entity entity = event.getEntity();
    Vector3d deathPos = entity.getPosition();

    // Particules de mort
    ParticleUtil.spawnParticleEffect(
        "entity_death_poof",
        deathPos,
        componentAccessor
    );

    // Effet d'âme qui monte pour les joueurs
    if (entity instanceof Player) {
        ParticleUtil.spawnParticleEffect(
            "soul_ascend",
            deathPos.add(0, 0.5, 0),
            componentAccessor
        );
    }
}

{{< /tab >}} {{< /tabs >}}

Effets Continus

{{< tabs items="Traînée Joueur,Aura,Effet de Zone" >}} {{< tab >}}

// Générer une traînée de particules à la position du joueur
public void spawnTrailEffect(Player player, Store<EntityStore> store,
                              ComponentAccessor<EntityStore> componentAccessor) {
    if (hasTrailEffect(player)) {
        // Obtenir la position via TransformComponent
        Ref<EntityStore> entityRef = player.getReference();
        TransformComponent transform = store.getComponent(entityRef, TransformComponent.getComponentType());
        if (transform != null) {
            Vector3d position = transform.getPosition();
            ParticleUtil.spawnParticleEffect(
                "magic_trail",
                position,
                componentAccessor
            );
        }
    }
}

{{< callout type="warning" >}} Note : Player n'a pas de méthode getPosition(). Obtenez la position via TransformComponent depuis le store d'entités. {{< /callout >}}

{{< /tab >}} {{< tab >}}

// Aura persistante autour du joueur
public class AuraManager {
    private final Map<UUID, Boolean> activeAuras = new HashMap<>();
    private Store<EntityStore> store;
    private ComponentAccessor<EntityStore> componentAccessor;

    public void enableAura(Player player) {
        // Utiliser player.getPlayerRef().getUuid() - pas player.getUuid()
        activeAuras.put(player.getPlayerRef().getUuid(), true);
    }

    @Subscribe
    public void onTick(ServerTickEvent event) {
        for (Map.Entry<UUID, Boolean> entry : activeAuras.entrySet()) {
            if (entry.getValue()) {
                Player player = getPlayer(entry.getKey());
                if (player != null) {
                    // Obtenir la position via TransformComponent
                    Ref<EntityStore> entityRef = player.getReference();
                    TransformComponent transform = store.getComponent(
                        entityRef, TransformComponent.getComponentType());
                    if (transform != null) {
                        Vector3d pos = transform.getPosition();
                        ParticleUtil.spawnParticleEffect(
                            "magic_aura",
                            new Vector3d(pos.getX(), pos.getY() + 1, pos.getZ()),
                            componentAccessor
                        );
                    }
                }
            }
        }
    }
}

{{< /tab >}} {{< tab >}}

// Effet de zone de soin
public void createHealingZone(Vector3d center, double radius, int durationTicks) {
    // Générer des particules en anneau
    for (int i = 0; i < 16; i++) {
        double angle = (2 * Math.PI * i) / 16;
        Vector3d pos = center.add(
            Math.cos(angle) * radius,
            0.1,
            Math.sin(angle) * radius
        );

        ParticleUtil.spawnParticleEffect(
            "healing_sparkle",
            pos,
            componentAccessor
        );
    }

    // Effet pilier central
    ParticleUtil.spawnParticleEffect(
        "healing_pillar",
        center,
        componentAccessor
    );
}

{{< /tab >}} {{< /tabs >}}


Directives de Performance

{{< callout type="warning" >}} Notes de Performance :

  • Distance de diffusion par défaut : 75 blocs (DEFAULT_PARTICLE_DISTANCE)
  • Les particules utilisent le paquet SpawnParticleSystem (ID : 152)
  • Définissez isImportant = true pour les feedbacks visuels critiques
  • Limitez le nombre de particules pour les performances client
  • Utilisez maxConcurrentParticles pour limiter les particules actives {{< /callout >}}

Conseils d'Optimisation

Conseil Description
Limiter le total de particules Gardez sous 100-200 pour les effets burst
Utiliser une cullDistance appropriée Ne pas rendre les particules trop éloignées
Grouper les spawns Générer plusieurs particules dans le même tick
Utiliser spawnBurst judicieusement Les bursts sont moins coûteux que le continu
Considérer le nombre de joueurs Plus de joueurs = plus de trafic réseau
// Bon : Génération de particules efficace
public void spawnEfficiently(Vector3d position) {
    // Générer seulement pour les joueurs proches
    List<PlayerRef> nearbyPlayers = getNearbyPlayers(position, 50);

    if (!nearbyPlayers.isEmpty()) {
        ParticleUtil.spawnParticleEffect(
            "my_effect",
            position,
            nearbyPlayers,  // Audience limitée
            componentAccessor
        );
    }
}

Sujets Connexes

  • [Effets d'Entité]({{< relref "entity-effects" >}}) - Effets de statut avec composants visuels
  • [Réseau]({{< relref "/advanced/networking" >}}) - Comment les particules sont diffusées
  • [Événements]({{< relref "/core-concepts/events" >}}) - Déclencher des particules depuis les événements