Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

CarChallenge 3D Demo

 import QtQuick 2.0
 import Felgo 3.0

 // for the shadow component with a PlaneMesh
 import Qt3D.Core 2.0
 import Qt3D.Render 2.0

 EntityBase {
   id: entity
   entityType: "rocket"

   Component.onCompleted: {
       console.debug("Rocket.onCompleted, width:", width);

   BoxCollider {
     id: boxCollider

     // the image and the physics will use this size; this is important as it specifies the mass of the body! it is in respect to the world size
     width: 50
     height: 20

     anchors.centerIn: parent

     density: 0.003
     friction: 0.4
     restitution: 0.5
     body.bullet: true
     // we prevent the physics engine from applying rotation to the rocket, because we will do it ourselves
     body.fixedRotation: true

     property var lastWall: null

     fixture.onBeginContact: {
       var fixture = other;
       var body = other.getBody();
       var otherEntity = body.target

       // get the entityType of the colliding entity
       var collidingType = otherEntity.entityType

       if(collidingType === "car" ||
               collidingType === "rocket") {

       //can't hit the same wall twice, but onBeginContact called again after rotation has changed
       if(otherEntity === lastWall) {
       lastWall = otherEntity

       //apply law of reflection, all calculations in degrees
       var normalAngle = 180 / Math.PI * Math.atan2(contactNormal.y, contactNormal.x)
       var angleDiff = normalAngle - entity.rotation
       var newAngle = entity.rotation + 2 * angleDiff + 180

       // manually set the entity rotation, because it is the target and its rotation will be used for the physics body
       entity.rotation = newAngle

       // it's important to clear the old velocity before applying the impulse, otherwise the rocket would get faster every time it collides with a wall!
       boxCollider.body.linearVelocity = Qt.point(0,0)


   Image {
     id: image
     source: "../../assets/img/rocket_green.png"
     anchors.centerIn: parent
     width: boxCollider.width
     height: boxCollider.height

   Render3D {
     id: render
     source: "../../assets/3d/rocket.obj" // texture is incorrectly mapped
     texture: "../../assets/3d/rocket_col.jpg"

     // an offset is needed to make them point in the right direction; 0 degree is to the right
     rotation: parent.rotation + 90
     rotationAxis: Qt.vector3d(0,0,1)
     // make it match the car & phyiscs dimensions and translate it so 0/0 is the rotation center
     //xOffset: -2*scaleOffset // when rotated, it would not look good if xOffset is set - to fire it in the center of the car, the initial position of the rocket needs to be ajdusted instead in Car.qml
     yOffset: -10*scaleOffset
     scaleOffset: 2
     zOffset: -10 // move it up so the full rocket is above the ground

   Render3D {
     // the shadow texture is a cheap way of adding shadows to the game, until shadow mapping is implemented in one of the coming updates
     zOffset: -0.2 // move it a little bit above the ground so it is visible

     rotation: parent.rotation + 270
     rotationAxis: Qt.vector3d(0,0,1)

     rotationOffset: 270
     rotationAxisOffset: Qt.vector3d(1,0,0)

     texture: "../../assets/3d/rocket_shadow.jpg"
     components: [renderTransform, material, planeMesh]
   PlaneMesh {
     id: planeMesh
     // the boxCollider width is 50 (its height 20), the texture was rotated initially so this is flipped too
     // also, the physics collider does not has the ratio of the image thus make it a bit wider here to match visually
     width: boxCollider.height * 2
     height: boxCollider.width

   function applyForwardImpulse() {
     var power = 1500
     var rad = entity.rotation / 180 * Math.PI

     //can't use body.toWorldVector() because the rotation is not instantly
     var localForward = Qt.point(power * Math.cos(rad), power * Math.sin(rad))
Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded