0
  • I look at stackoverflow other people similar problems a they have very similar solution but all examples are done in three.js (Not in my case).

  • Jump is relative good working at the moment, i powered gravity (double it). Stairs also works fine even without jumping it is ok for me. I put one big cube to make blocking volume but i dont now how to make player to simple stops because i use WASD for body set position. My player in big cube just have big jump , i wanna prevent WASD body set position in moment of first touch.

Some solutions [not yet tested]:

1] To make movement only with force [not set position] => [possible not nature movements]

2] Make collide detection then prevent set position => [possible angle problems]

3] Some other solution....

All related code is visible in example. Matrix-engine example for FPS:

import App from '../program/manifest';
import * as CANNON from 'cannon';
import {ENUMERATORS, ORBIT_FROM_ARRAY, OSCILLATOR, randomFloatFromTo} from '../lib/utility';

export var runThis = (world) => {

  // Camera
  canvas.style.cursor = 'none';
  App.camera.FirstPersonController = true;
  matrixEngine.Events.camera.fly = false;
  App.camera.speedAmp = 0.01;
  matrixEngine.Events.camera.yPos = 2;

  // Audio effects
  App.sounds.createAudio('shoot', 'res/music/single-gunshot.mp3', 5);

  // Prevent right click context menu
  window.addEventListener("contextmenu", (e) => {
    e.preventDefault();
  });

  // Override mouse up
  App.events.CALCULATE_TOUCH_UP_OR_MOUSE_UP = () => {
    App.scene.FPSTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
    App.scene.FPSTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
    App.scene.FPSTarget.geometry.setScale(0.1);
    App.scene.xrayTarget.visible = false;
  };

  // Override right mouse down
  matrixEngine.Events.SYS.MOUSE.ON_RIGHT_BTN_PRESSED = (e) => {
    App.scene.FPSTarget.geometry.setScale(0.6);
    App.scene.FPSTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
    App.scene.FPSTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
    App.scene.xrayTarget.visible = true;
  };

  // Override mouse down
  App.events.CALCULATE_TOUCH_DOWN_OR_MOUSE_DOWN = (ev, mouse) => {
    // `checkingProcedure` gets secound optimal argument
    // for custom ray origin target.
    if(mouse.BUTTON_PRESSED == 'RIGHT') {
      // Zoom
    } else {
      // This call represent `SHOOT` Action.
      // And it is center of screen
      matrixEngine.raycaster.checkingProcedure(ev, {
        clientX: ev.target.width / 2,
        clientY: ev.target.height / 2
      });
      App.sounds.play('shoot');
    }
  };

  window.addEventListener('ray.hit.event', (ev) => {
    console.log("You shoot the object! Nice!", ev);
    // Physics force apply also change ambienty light.
    if(ev.detail.hitObject.physics.enabled == true) {
      // Shoot the object - apply force
      ev.detail.hitObject.physics.currentBody.force.set(0, 0, 1000);
      // Apply random diff color
      if(ev.detail.hitObject.LightsData) ev.detail.hitObject.LightsData.ambientLight.set(
        randomFloatFromTo(0, 2), randomFloatFromTo(0, 2), randomFloatFromTo(0, 2));
    }
  });

  // Load obj seq animation
  const createObjSequence = (objName) => {

    function onLoadObj(meshes) {

      for(let key in meshes) {
        matrixEngine.objLoader.initMeshBuffers(world.GL.gl, meshes[key]);
      }

      var textuteImageSamplers2 = {
        source: [
          "res/bvh-skeletal-base/swat-guy/textures/Ch15_1001_Diffuse.png" // ,
          // "res/bvh-skeletal-base/swat-guy/textures/Ch15_1001_Diffuse.png"
        ],
        mix_operation: "multiply", // ENUM : multiply , divide
      };

      var animArg = {
        id: objName,
        meshList: meshes,
        currentAni: 0,
        animations: {
          active: 'walk',
          walk: {
            from: 0,
            to: 20,
            speed: 3
          }
        }
      };

      world.Add("obj", 1, objName, textuteImageSamplers2, meshes[objName], animArg);

      // Fix object orientation - this can be fixed also in blender.
      matrixEngine.Events.camera.yaw = 0;

      // Add collision cube to the local player.
      world.Add("cube", 0.5, "playerCollisonBox");
      var collisionBox = new CANNON.Body({
        mass: 500,
        linearDamping: 0.001,
        position: new CANNON.Vec3(0, 0, 0),
        shape: new CANNON.Box(new CANNON.Vec3(3, 3, 3))// new CANNON.Sphere(2)
      });
      physics.world.addBody(collisionBox);
      App.scene.playerCollisonBox.physics.currentBody = collisionBox;
      App.scene.playerCollisonBox.physics.enabled = true;
      App.scene.playerCollisonBox.physics.currentBody.fixedRotation = true;
      App.scene.playerCollisonBox.geometry.setScale(0.02);

      App.scene.playerCollisonBox.glBlend.blendEnabled = true;
      App.scene.playerCollisonBox.glBlend.blendParamSrc = ENUMERATORS.glBlend.param[5];
      App.scene.playerCollisonBox.glBlend.blendParamDest = ENUMERATORS.glBlend.param[6];

      // test 
      addEventListener('hit.keyDown', (e) => {
        // console.log('Bring to the top level', e.detail.keyCode);
        // dont mess in events
        if(e.detail.keyCode == 32) {
          setTimeout(() => {
            App.scene.playerCollisonBox.physics.currentBody.force.set(0, 0, 111)
          }, 250)
        } else if(e.detail.keyCode == 87) {
          // Good place for blocking volume
          // App.scene.playerCollisonBox.physics.currentBody.force.set(0,10,0)
          setTimeout(() => {
            // App.scene.playerCollisonBox.physics.currentBody.force.set(0,100,0)
          }, 100);
        }
      });

      var playerUpdater = {
        UPDATE: () => {
          App.scene[objName].rotation.rotateY(
            matrixEngine.Events.camera.yaw + 180)

          var detPitch;
          var limit = 2;
          if(matrixEngine.Events.camera.pitch < limit &&
            matrixEngine.Events.camera.pitch > -limit) {
            detPitch = matrixEngine.Events.camera.pitch * 2;
          } else if(matrixEngine.Events.camera.pitch > limit) {
            detPitch = limit * 2;
          } else if(matrixEngine.Events.camera.pitch < -(limit + 2)) {
            detPitch = -(limit + 2) * 2;
          }

          if(matrixEngine.Events.camera.virtualJumpActive == true) {
            // invert logic
            // Scene object set
            App.scene[objName].rotation.rotateX(-detPitch);
            var detPitchPos = matrixEngine.Events.camera.pitch;
            if(detPitchPos > 4) detPitchPos = 4;

            App.scene.playerCollisonBox.physics.currentBody.mass = 10;
            App.scene.playerCollisonBox.physics.currentBody.force.set(0, 0, 700);

            App.scene[objName].position.setPosition(
              App.scene.playerCollisonBox.physics.currentBody.position.x,
              App.scene.playerCollisonBox.physics.currentBody.position.z,
              App.scene.playerCollisonBox.physics.currentBody.position.y
            )
            // Cannonjs object set / Switched  Z - Y
            matrixEngine.Events.camera.xPos = App.scene.playerCollisonBox.physics.currentBody.position.x;
            matrixEngine.Events.camera.zPos = App.scene.playerCollisonBox.physics.currentBody.position.y;
            matrixEngine.Events.camera.yPos = App.scene.playerCollisonBox.physics.currentBody.position.z;

            App.scene.playerCollisonBox.
              physics.currentBody.angularVelocity.set(0, 0, 0);

            setTimeout(() => {
              matrixEngine.Events.camera.virtualJumpActive = false;
              App.scene.playerCollisonBox.physics.currentBody.mass = 550;
            }, 1350);

          } else {

            // Make more stable situation
            App.scene.playerCollisonBox.physics.currentBody.mass = 500;
            App.scene.playerCollisonBox.physics.currentBody.quaternion.setFromEuler(0,0,0)

            // Tamo tu iznad duge nebo zri...
            // Cannonjs object set
            // Switched  Z - Y
            matrixEngine.Events.camera.yPos = App.scene.playerCollisonBox.physics.currentBody.position.z;

            // Scene object set
            App.scene[objName].rotation.rotateX(-detPitch);
            var detPitchPos = matrixEngine.Events.camera.pitch;
            if(detPitchPos > 4) detPitchPos = 4;

            App.scene[objName].position.setPosition(
              matrixEngine.Events.camera.xPos,
              matrixEngine.Events.camera.yPos, // - 0.3 + detPitchPos / 50,
              // App.scene.playerCollisonBox.physics.currentBody.position.y,
              matrixEngine.Events.camera.zPos,
            )

            // Cannonjs object set
            // Switched  Z - Y
            App.scene.playerCollisonBox.
              physics.currentBody.position.set(
                matrixEngine.Events.camera.xPos,
                matrixEngine.Events.camera.zPos,
                matrixEngine.Events.camera.yPos)
            // App.scene.playerCollisonBox.physics.currentBody.position.y)
          }
        }
      };
      App.updateBeforeDraw.push(playerUpdater);

      // Player Energy status
      App.scene.player.energy = {};

      for(let key in App.scene.player.meshList) {
        App.scene.player.meshList[key].setScale(1.85);
      }

      // Target scene object
      var texTarget = {
        source: [
          "res/bvh-skeletal-base/swat-guy/target.png",
          "res/bvh-skeletal-base/swat-guy/target.png"
        ],
        mix_operation: "multiply",
      };
      world.Add("squareTex", 0.25, 'FPSTarget', texTarget);
      App.scene.FPSTarget.position.setPosition(0, 0, -4);
      App.scene.FPSTarget.glBlend.blendEnabled = true;
      App.scene.FPSTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
      App.scene.FPSTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
      App.scene.FPSTarget.isHUD = true;
      App.scene.FPSTarget.geometry.setScale(0.1);

      // Energy active bar
      // Custom generic textures. Micro Drawing.
      // Example for arg shema square for now only.
      var options = {
        squareShema: [8, 8],
        pixels: new Uint8Array(8 * 8 * 4)
      };
      // options.pixels.fill(0);
      App.scene.player.energy.value = 8;
      App.scene.player.updateEnergy = function(v) {
        this.energy.value = v;
        var t = App.scene.energyBar.preparePixelsTex(App.scene.energyBar.specialValue);
        App.scene.energyBar.textures.pop()
        App.scene.energyBar.textures.push(App.scene.energyBar.createPixelsTex(t));
      };

      function preparePixelsTex(options) {
        var I = 0, R = 0, G = 0, B = 0, localCounter = 0;
        for(var funny = 0;funny < 8 * 8 * 4;funny += 4) {
          if(localCounter > 7) {
            localCounter = 0;
          }
          if(localCounter < App.scene.player.energy.value) {
            I = 128;
            if(App.scene.player.energy.value < 3) {
              R = 255;
              G = 0;
              B = 0;
              I = 0;
            } else if(App.scene.player.energy.value > 2 && App.scene.player.energy.value < 5) {
              R = 255;
              G = 255;
              B = 0;
            } else {
              R = 0;
              G = 255;
              B = 0;
            }
          } else {
            I = 0;
            R = 0;
            G = 0;
            B = 0;
          }
          options.pixels[funny] = R;
          options.pixels[funny + 1] = G;
          options.pixels[funny + 2] = B;
          options.pixels[funny + 3] = 0;
          localCounter++;
        }
        return options;
      }

      var tex2 = {
        source: [
          "res/images/hud/energy-bar.png",
          "res/images/hud/energy-bar.png"
        ],
        mix_operation: "multiply",
      };

      world.Add("squareTex", 1, 'energyBar', tex2);
      App.scene.energyBar.glBlend.blendEnabled = true;
      App.scene.energyBar.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
      App.scene.energyBar.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
      App.scene.energyBar.isHUD = true;
      // App.scene.energy.visible = false;
      App.scene.energyBar.position.setPosition(0, 1.1, -3);
      App.scene.energyBar.geometry.setScaleByX(1)
      App.scene.energyBar.geometry.setScaleByY(0.05)
      App.scene.energyBar.preparePixelsTex = preparePixelsTex;
      options = preparePixelsTex(options);
      // App.scene.energyBar.textures[0] = App.scene.energyBar.createPixelsTex(options);
      App.scene.energyBar.textures.push(App.scene.energyBar.createPixelsTex(options));
      App.scene.energyBar.specialValue = options;

    }

    matrixEngine.objLoader.downloadMeshes(
      matrixEngine.objLoader.makeObjSeqArg(
        {
          id: objName,
          // path: "res/bvh-skeletal-base/swat-guy/anims/swat-multi",
          path: "res/bvh-skeletal-base/swat-guy/FPShooter-hands/FPShooter-hands",
          from: 1,
          to: 20
        }),
      onLoadObj
    );

  };

  let promiseAllGenerated = [];

  const objGenerator = (n) => {
    for(var j = 0;j < n;j++) {
      promiseAllGenerated.push(new Promise((resolve) => {
        setTimeout(() => {
          world.Add("cubeLightTex", 1, "CUBE" + j, tex);
          var b2 = new CANNON.Body({
            mass: 1,
            linearDamping: 0.01,
            position: new CANNON.Vec3(1, -14.5, 15),
            shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1))
          });
          physics.world.addBody(b2);
          App.scene['CUBE' + j].physics.currentBody = b2;
          App.scene['CUBE' + j].physics.enabled = true;
          resolve();
        }, 1000 * j);
      }));
    }
  }

  // objGenerator(15);

  createObjSequence('player');

  Promise.all(promiseAllGenerated).then((what) => {
    console.info(`Runtime wait for some generetion of scene objects,
                  then swap scene array index for target -> 
                  must be manual setup for now!`, what);
    // swap(5, 19, matrixEngine.matrixWorld.world.contentList);
  });

  // Add ground for physics bodies.
  var tex = {
    source: ["res/images/complex_texture_1/diffuse.png"],
    mix_operation: "multiply",
  };
  // Load Physics world.
  // let gravityVector = [0, 0, -9.82];
  let gravityVector = [0, 0, -29.82];
  let physics = world.loadPhysics(gravityVector);

  // Add ground
  var groundBody = new CANNON.Body({
    mass: 0, // mass == 0 makes the body static
    position: new CANNON.Vec3(0, -15, -2)
  });
  var groundShape = new CANNON.Plane();
  groundBody.addShape(groundShape);
  physics.world.addBody(groundBody);
  // Matrix engine visual
  world.Add("squareTex", 1, "FLOOR_STATIC", tex);
  App.scene.FLOOR_STATIC.geometry.setScaleByX(20);
  App.scene.FLOOR_STATIC.geometry.setScaleByY(20);
  App.scene.FLOOR_STATIC.position.SetY(-2);
  App.scene.FLOOR_STATIC.position.SetZ(-15);
  App.scene.FLOOR_STATIC.rotation.rotx = 90;

  // Target x-ray 
  // See through the objects.
  // In webGL context it is object how was drawn before others.
  var texTarget = {
    source: [
      "res/bvh-skeletal-base/swat-guy/target-night.png"
    ],
    mix_operation: "multiply",
  };
  world.Add("squareTex", 0.18, 'xrayTarget', texTarget);
  App.scene.xrayTarget.glBlend.blendEnabled = true;
  App.scene.xrayTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
  App.scene.xrayTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
  App.scene.xrayTarget.isHUD = true;
  App.scene.xrayTarget.visible = false;
  App.scene.xrayTarget.position.setPosition(-0.3, 0.27, -4);

  // Energy
  var tex1 = {
    source: [
      "res/images/hud/energy.png"
    ],
    mix_operation: "multiply",
  };
  world.Add("squareTex", 0.5, 'energy', tex1);
  App.scene.energy.glBlend.blendEnabled = true;
  App.scene.energy.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
  App.scene.energy.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
  App.scene.energy.isHUD = true;
  // App.scene.energy.visible = false;
  App.scene.energy.position.setPosition(-1, 1.15, -3);
  App.scene.energy.geometry.setScaleByX(0.35)
  App.scene.energy.geometry.setScaleByY(0.1)

  // good for fix rotation in future
  world.Add("cubeLightTex", 1, "FLOOR2", tex);
  var b2 = new CANNON.Body({
    mass: 0,
    linearDamping: 0.01,
    position: new CANNON.Vec3(1, -14.5, -1),
    shape: new CANNON.Box(new CANNON.Vec3(3, 1, 1))
  });
  physics.world.addBody(b2);
  App.scene['FLOOR2'].position.setPosition(1, -1, -14.5)
  App.scene['FLOOR2'].geometry.setScaleByX(3);

  App.scene['FLOOR2'].physics.currentBody = b2;
  App.scene['FLOOR2'].physics.enabled = true;

  world.Add("cubeLightTex", 2, "FLOOR3", tex);
  var b3 = new CANNON.Body({
    mass: 0,
    linearDamping: 0.01,
    position: new CANNON.Vec3(0, -19, 0),
    shape: new CANNON.Box(new CANNON.Vec3(3, 3, 3))
  });
  physics.world.addBody(b3);
  App.scene['FLOOR3'].position.setPosition(0, 0, -19)
  // App.scene['FLOOR3'].geometry.setScaleByX(3);

  App.scene['FLOOR3'].physics.currentBody = b3;
  App.scene['FLOOR3'].physics.enabled = true;


  world.Add("cubeLightTex", 5, "WALL_BLOCK", tex);
  var b5 = new CANNON.Body({
    mass: 0,
    linearDamping: 0.01,
    position: new CANNON.Vec3(10, -19, 0),
    shape: new CANNON.Box(new CANNON.Vec3(5, 5, 5))
  });
  physics.world.addBody(b5);
  App.scene['WALL_BLOCK'].position.setPosition(10, 0, -19)
  // App.scene['WALL_BLOCK'].geometry.setScaleByX(3);
  App.scene['WALL_BLOCK'].physics.currentBody = b5;
  App.scene['WALL_BLOCK'].physics.enabled = true;


};

Any suggestion ?

Nikola Lukic
  • 4,001
  • 6
  • 44
  • 75

0 Answers0