En esta página

Qt Quick Física 3D - Ejemplo de Impulsor

Demuestra el uso de cuerpos de disparo e información de colisión.

Captura de pantalla de un renderizado 3D que muestra una esfera azul sobre una superficie verde, un bloque rectangular rosa sobre ella y una esfera roja flotando encima.

Este ejemplo demuestra cómo utilizar cuerpos de disparo e información de colisión. La escena consiste en un plano estático verde, una esfera dinámica roja, un cuerpo de disparo rosa y una esfera estática azul. Cuando la esfera roja se superponga al cuerpo de disparo se volverá amarilla y cuando colisione con la esfera azul será repelida.

Configurar

Como de costumbre tenemos que añadir nuestro PhysicsWorld:

PhysicsWorld {
    gravity: Qt.vector3d(0, -490, 0)
    scene: viewport.scene
}

También añadimos un View3D donde ponemos nuestros objetos de escena. En este tenemos algunos ajustes para el entorno visual:

environment: SceneEnvironment {
    clearColor: "#d6dbdf"
    backgroundMode: SceneEnvironment.Color
}

PerspectiveCamera {
    position: Qt.vector3d(0, 200, 1000)
    clipFar: 2000
    clipNear: 1
}

DirectionalLight {
    eulerRotation.x: -45
    eulerRotation.y: 45
    castsShadow: true
    brightness: 1
    shadowFactor: 50
}

Objetos físicos

Tenemos nuestro plano estático regular:

StaticRigidBody {
    position: Qt.vector3d(0, -100, 0)
    eulerRotation: Qt.vector3d(-90, 0, 0)
    collisionShapes: PlaneShape {}
    Model {
        source: "#Rectangle"
        scale: Qt.vector3d(500, 500, 1)
        materials: PrincipledMaterial {
            baseColor: "green"
        }
        castsShadows: false
        receivesShadows: true
    }
}

Así se define nuestra esfera dinámica:

DynamicRigidBody {
    id: sphere
    massMode: DynamicRigidBody.CustomDensity
    density: 0.00001
    position: Qt.vector3d(0, 600, 0)
    property bool inArea: false
    sendContactReports: true
    receiveTriggerReports: true

    onEnteredTriggerBody: {
        inArea = true
    }
    onExitedTriggerBody: {
        inArea = false
    }

    collisionShapes: SphereShape {}
    Model {
        source: "#Sphere"
        materials: PrincipledMaterial {
            baseColor: sphere.inArea ? "yellow" : "red"
        }
    }
}

La propiedad inArea es una propiedad personalizada que utilizamos para mantener un registro de cuando la esfera se superpone al cuerpo de disparo de la caja. Esto se utiliza para la propiedad baseColor para hacer que la esfera amarilla cuando se superpone a la caja y rojo en caso contrario. Dado que queremos que la esfera participe en el informe de contacto, la propiedad sendContactReports debe establecerse en true. Dado que también queremos que la esfera reciba llamadas de retorno al entrar y salir de TriggerBody, la propiedad receiveContactReports también se establece en true. Implementamos los métodos de señal enteredTriggerBody y exitedTriggerBody en la esfera donde establecemos la propiedad inArea en true o false al entrar o salir del cuerpo de disparo.

Ahora veamos el cuerpo del disparador:

TriggerBody {
    position: Qt.vector3d(0, 350, 0)
    scale: Qt.vector3d(1, 2, 1)

    collisionShapes: BoxShape {
        id: boxShape
    }
    Model {
        source: "#Cube"
        materials: PrincipledMaterial {
            baseColor: Qt.rgba(1, 0, 1, 0.2)
            alphaMode: PrincipledMaterial.Blend
        }
    }
}

El tipo qml es un TriggerBody que actúa como un cuerpo estático excepto que sus colisiones están inactivas. En su lugar, activará las llamadas a los métodos enteredTriggerBody y exitedTriggerBody en la esfera.

Por último, veamos el impulsor:

StaticRigidBody {
    position: Qt.vector3d(0, 0, 0)
    scale: Qt.vector3d(2, 2, 2)
    receiveContactReports: true

    collisionShapes: SphereShape {}

    Model {
        source: "#Sphere"
        materials: PrincipledMaterial {
            baseColor: "blue"
        }
    }

    onBodyContact: (body, positions, impulses, normals) => {
        for (var normal of normals) {
            let velocity = normal.times(-700)
            body.setLinearVelocity(velocity)
        }
    }
}

Este es un cuerpo estático y configuramos receiveContactReports a true para activar las llamadas de colisión. El callback bodyContact es llamado cada vez que se reporta una colisión. En el método llamamos a setLinearVelocity para establecer la velocidad lineal en la dirección opuesta al vector normal de colisión para simular un impulsor.

Ficheros:

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.