This commit is contained in:
2026-01-20 20:33:59 +01:00
commit b16a40e431
583 changed files with 87339 additions and 0 deletions

View File

@@ -0,0 +1,788 @@
---
title: Particules
type: docs
weight: 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 >}}
```java
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 >}}
```java
// 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 >}}
```java
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 :
```java
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 >}}
```java
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 :**
```java
// 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 :**
```java
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 :
```java
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 :
```java
// 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 :
```java
// 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 :
```java
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
```java
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
```java
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
```java
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
```java
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 :
```java
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 :
```java
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 :
```java
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) :
```java
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 :
```java
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 :
```java
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
```java
public enum ParticleUVOption {
None, // Frame unique statique
Animated, // Jouer les frames en séquence
Random // Frame aléatoire par particule
}
```
### Frames d'Animation
```java
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
```java
// 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 :
```java
TransformComponent transform = store.getComponent(entityRef, TransformComponent.getComponentType());
Vector3d position = transform.getPosition();
```
{{< /callout >}}
{{< tabs items="Destruction Bloc,Combat,Mort" >}}
{{< tab >}}
```java
@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 >}}
```java
@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 >}}
```java
@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 >}}
```java
// 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 >}}
```java
// 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 >}}
```java
// 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 |
```java
// 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