@gwenjs/physics2d
pnpm add @gwenjs/physics2d
Plugin de moteur de physique 2D alimenté par Rapier2D. Fournit la dynamique des corps rigides, les colliders et les capteurs pour les jeux 2D.
Configuration du plugin
Physics2DPlugin()
Signature:
function Physics2DPlugin(options?: Physics2DPluginOptions): PluginDefDescription. Crée le plugin de physique 2D. Enregistrez dans votre config d'app pour activer la simulation physique.
Retourne: PluginDef — définition du plugin de physique.
Exemple:
export default defineConfig({
plugins: [Physics2DPlugin()],
// ...
});Composables
Utilisez ceux-ci à l'intérieur de defineActor pour ajouter des composants de physique aux entités.
useShape(options)
Signature:
function useShape(options: ShapeOptions): voidDescription. Ajoute une forme (collider) à l'entité courante.
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| options | ShapeOptions | Configuration de la forme |
Retourne: void
useDynamicBody(options?)
Signature:
function useDynamicBody(options?: DynamicBodyOptions): voidDescription. Ajoute un corps rigide dynamique (affecté par la gravité et les forces). À utiliser pour les objets de jeu en mouvement.
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| options | DynamicBodyOptions | Configuration du corps (optionnel) |
Retourne: void
Exemple:
const BallPrefab = definePrefab([{ def: Position, defaults: { x: 0, y: 0 } }])
export const BallActor = defineActor(BallPrefab, () => {
useDynamicBody({ mass: 2, restitution: 0.8 })
useBoxCollider({ w: 1, h: 1 })
})useKinematicBody(options?)
Signature:
function useKinematicBody(options?: KinematicBodyOptions): voidDescription. Ajoute un corps cinématique (non affecté par la gravité, contrôlé par la vélocité). À utiliser pour les plates-formes, les obstacles mobiles.
Retourne: void
useStaticBody()
Signature:
function useStaticBody(): voidDescription. Ajoute un corps statique (immobile). À utiliser pour le terrain, les murs, le sol.
Retourne: void
Exemple:
const GroundPrefab = definePrefab([{ def: Position, defaults: { x: 0, y: 0 } }])
export const GroundActor = defineActor(GroundPrefab, () => {
useStaticBody()
useBoxCollider({ w: 100, h: 1 })
})Colliders
useBoxCollider(options)
Signature:
function useBoxCollider(options: BoxColliderOptions): voidDescription. Ajoute un collider de boîte/rectangle à l'entité courante.
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| options.w | number | Largeur de la boîte en unités monde |
| options.h | number | Hauteur de la boîte en unités monde |
| options.isSensor | boolean | Si vrai, génère des événements de chevauchement sans réponse physique |
| options.layer | number | Bitmask de couche d'appartenance aux collisions |
| options.mask | number | Bitmask de filtre de collision |
| options.offsetX | number | Décalage X local par rapport à l'origine de l'acteur |
| options.offsetY | number | Décalage Y local par rapport à l'origine de l'acteur |
Retourne: BoxColliderHandle
Exemple:
useBoxCollider({ w: 2, h: 2, isSensor: false });useSphereCollider(options)
Signature:
function useSphereCollider(options: SphereColliderOptions): voidDescription. Ajoute un collider circulaire à l'entité courante.
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| options.radius | number | Rayon du cercle en unités monde |
| options.isSensor | boolean | Si vrai, génère des événements de chevauchement sans réponse physique |
| options.layer | number | Bitmask de couche d'appartenance aux collisions |
| options.mask | number | Bitmask de filtre de collision |
Retourne: void
useCapsuleCollider(options)
Signature:
function useCapsuleCollider(options: CapsuleColliderOptions): voidDescription. Ajoute un collider de capsule (rectangle arrondi).
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| options.radius | number | Rayon de la capsule en unités monde |
| options.height | number | Hauteur totale de la capsule en unités monde |
| options.isSensor | boolean | Si vrai, génère des événements de chevauchement sans réponse physique |
| options.layer | number | Bitmask de couche d'appartenance aux collisions |
| options.mask | number | Bitmask de filtre de collision |
Retourne: void
Événements
onContact(handler)
Signature:
function onContact(handler: (event: ContactEvent) => void): voidDescription. Enregistre un gestionnaire pour les événements de collision (quand deux colliders entrent en collision).
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| handler | function | Appelé avec les informations de collision |
Retourne: void
Exemple:
const PlayerPrefab = definePrefab([{ def: Position, defaults: { x: 0, y: 0 } }])
export const PlayerActor = defineActor(PlayerPrefab, () => {
onContact((event) => {
if (event.relativeVelocity > 10) {
// Impact violent — prendre des dégâts
}
})
})ContactEvent
Signature:
interface ContactEvent {
entityA: bigint;
entityB: bigint;
contactX: number;
contactY: number;
normalX: number;
normalY: number;
relativeVelocity: number;
}onSensorEnter(sensorId, callback)
Signature:
function onSensorEnter(sensorId: number, callback: (entityId: bigint) => void): voidDescription. Appelé quand une autre entité entre dans un collider capteur. Utiliser le colliderId du handle de collider comme sensorId.
Exemple:
export const CoinActor = defineActor(CoinPrefab, () => {
const zone = useSphereCollider({ radius: 0.5, isSensor: true })
onSensorEnter(zone.colliderId, (entityId) => {
// Une entité est entrée dans la zone
console.log('Collecté par l\'entité :', entityId)
})
})onSensorExit(sensorId, callback)
Signature:
function onSensorExit(sensorId: number, callback: (entityId: bigint) => void): voidDescription. Appelé quand une autre entité quitte un collider capteur.
Couches
defineLayers(definition)
Signature:
function defineLayers<T extends Record<string, number>>(definition: T): Record<string, number>Description. Déclare des couches de collision nommées avec leurs valeurs de bitmask. Le plugin Vite intègre les valeurs de couche au moment du build et avertit si des couches partagent des bits.
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| definition | Record<string, number> | Objet associant des noms de couches à des valeurs de bitmask |
Retourne: Record<string, number> — le même objet, avec les noms de couches comme clés.
Exemple:
const Layers = defineLayers({
player: 1 << 0,
enemy: 1 << 1,
wall: 1 << 2,
})
// Utilisez Layers.player, Layers.enemy, Layers.wallService de physique
usePhysics2D()
Signature:
function usePhysics2D(): Physics2DAPIDescription. Retourne le service de physique pour interroger et manipuler les corps.
Retourne: Physics2DAPI — API d'exécution de physique.
Exemple:
const physics = usePhysics2D();
physics.applyImpulse(entityId, 10, 0);Physics2DAPI
Méthodes:
| Méthode | Signature | Description |
|---|---|---|
applyImpulse | (entityId: EntityId, x: number, y: number) => void | Applique une impulsion linéaire instantanée |
setLinearVelocity | (entityId: EntityId, vx: number, vy: number) => void | Remplace la vélocité linéaire (m/s) |
getLinearVelocity | (entityId: EntityId) => { x: number; y: number } | null | Lit la vélocité linéaire actuelle |
getPosition | (entityId: EntityId) => { x: number; y: number; rotation: number } | null | Lit la position et l'angle du corps |
getCollisionEventsBatch | (opts?) => CollisionEventsBatch | Récupère tous les événements de collision de cette frame |
getCollisionContacts | (opts?) => ReadonlyArray<ResolvedCollisionContact> | Lit les paires de contact actives |
getSensorState | (entityId: EntityId, sensorId: number) => SensorState | Lit l'état de chevauchement d'un sensor |
TIP
La plupart des manipulations de corps (forces, vélocités, impulsions) se font via le handle retourné par useDynamicBody() — pas directement via usePhysics2D(). L'API service est principalement utilisée pour le polling des événements de collision et les requêtes spatiales.
Exemple:
const physics = usePhysics2D();
// Appliquer une impulsion via l'API service
physics.applyImpulse(entityId, 0, 500)
// Polling des événements de collision chaque frame
onUpdate(() => {
const batch = physics.getCollisionEventsBatch()
// traitement du batch...
})Systèmes
createPhysicsKinematicSyncSystem(opts)
Signature:
function createPhysicsKinematicSyncSystem(opts?: {
syncPosition?: boolean;
syncRotation?: boolean;
}): SystemDefDescription. Crée un système qui synchronise les positions/rotations des corps cinématiques basées sur les composants Transform.
Retourne: SystemDef
Exemple:
const scene = defineScene({
systems: [
createPhysicsKinematicSyncSystem({ syncPosition: true, syncRotation: true })
]
});createPlatformerGroundedSystem(opts)
Signature:
function createPlatformerGroundedSystem(opts?: {
groundLayer?: LayerMask;
raycastDistance?: number;
}): SystemDefDescription. Crée un système qui suivre lesquelles entités sont sur le sol (debout sur un sol solide). Utile pour les platformers.
Retourne: SystemDef
Exemple:
export const MyScene = defineScene({
name: 'game',
systems: [
createPlatformerGroundedSystem({ raycastDistance: 0.1 }),
],
})Support Tilemap
buildTilemapPhysicsChunks(opts)
Signature:
function buildTilemapPhysicsChunks(opts: {
tilemap: TilemapData;
tileSize: number;
solidTiles: number[];
chunkSize?: number;
}): voidDescription. Construit les colliders de physique pour une tilemap utilisant le chunking pour la performance.
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| opts.tilemap | TilemapData | Données de tilemap |
| opts.tileSize | number | Taille des tuiles en unités |
| opts.solidTiles | number[] | IDs des tuiles qui sont solides |
| opts.chunkSize | number | Taille de la grille de chunks (optionnel) |
Retourne: void
patchTilemapPhysicsChunk(opts)
Signature:
function patchTilemapPhysicsChunk(opts: {
tilemap: TilemapData;
chunkX: number;
chunkY: number;
}): voidDescription. Reconstruit la physique pour un seul chunk de tilemap (pour les éditions de tilemap dynamiques).
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| opts.chunkX | number | Chunk grille X |
| opts.chunkY | number | Chunk grille Y |
Retourne: void
Intégration Vite
physics2dVitePlugin(options?)
Signature:
function physics2dVitePlugin(options?: Physics2DVitePluginOptions): VitePlugin
// interface Physics2DVitePluginOptions { debug?: boolean }Description. Plugin Vite pour bundler Rapier2D WASM. Enregistré automatiquement quand le plugin physics2d est utilisé. Émet un avertissement au moment du build si une couche est définie avec defineLayers() mais jamais référencée dans le même fichier — permet de détecter les définitions de couches inutilisées tôt.
Paramètres:
| Paramètre | Type | Description |
|---|---|---|
| options | Physics2DVitePluginOptions | Options optionnelles du plugin au moment du build |
| options.debug | boolean | Activer les logs de débogage pour l'intégration des couches (défaut: false) |
Retourne: VitePlugin
Note: Lors de l'utilisation de la config du module, passez les options du plugin Vite via la sous-clé
vite:tsmodules: [['@gwenjs/physics2d', { gravity: -9.81, vite: { debug: true } // Options du plugin Vite (build uniquement) }]]
Définitions de type
BoxColliderOptions
interface BoxColliderOptions {
width: number;
height: number;
sensor?: boolean;
density?: number;
}SphereColliderOptions
interface SphereColliderOptions {
radius: number;
sensor?: boolean;
density?: number;
}CapsuleColliderOptions
interface CapsuleColliderOptions {
halfHeight: number;
radius: number;
sensor?: boolean;
density?: number;
}DynamicBodyOptions
interface DynamicBodyOptions {
mass?: number;
linearDamping?: number;
angularDamping?: number;
gravityScale?: number;
restitution?: number;
friction?: number;
ccdEnabled?: boolean;
}KinematicBodyOptions
interface KinematicBodyOptions {
friction?: number;
restitution?: number;
}StaticBodyOptions
interface StaticBodyOptions {
friction?: number;
}