Skip to content
This repository has been archived by the owner on May 19, 2024. It is now read-only.

6. Keyboard and mouse

Lubos Lenco edited this page Sep 11, 2016 · 3 revisions

(Reference)

Let's build a controllable camera so we can move around in our 3D world. We need mouse to look and arrow keys to move.

    // Add mouse and keyboard listeners
    Mouse.get().notify(onMouseDown, onMouseUp, onMouseMove, null);
    Keyboard.get().notify(onKeyDown, onKeyUp);

    // Used to calculate delta time
    lastTime = Scheduler.time();

Mouse and keyboard event handlers. Nothing fancy to see here.

    function onMouseDown(button:Int, x:Int, y:Int) {
      isMouseDown = true;
    }

    function onMouseUp(button:Int, x:Int, y:Int) {
      isMouseDown = false;
    }

    function onMouseMove(x:Int, y:Int, movementX:Int, movementY:Int) {
      mouseDeltaX = x - mouseX;
      mouseDeltaY = y - mouseY;

      mouseX = x;
      mouseY = y;
    }

    function onKeyDown(key:Key, char:String) {
      if (key == Key.UP) moveForward = true;
      else if (key == Key.DOWN) moveBackward = true;
      else if (key == Key.LEFT) strafeLeft = true;
      else if (key == Key.RIGHT) strafeRight = true;
    }

    function onKeyUp(key:Key, char:String) {
      if (key == Key.UP) moveForward = false;
      else if (key == Key.DOWN) moveBackward = false;
      else if (key == Key.LEFT) strafeLeft = false;
      else if (key == Key.RIGHT) strafeRight = false;
    }

For the first time we will use update function to calculate our matrices based on input every frame. Let's add a listener in Main.init().

    Scheduler.addTimeTask(game.update, 0, 1 / 60);

On to implementation.

    public function update() {
      // Compute time difference between current and last frame
      var deltaTime = Scheduler.time() - lastTime;
      lastTime = Scheduler.time();

      // Compute new orientation
      if (isMouseDown) {
        horizontalAngle += mouseSpeed * mouseDeltaX * -1;
        verticalAngle += mouseSpeed * mouseDeltaY * -1;
      }

      // Direction: Spherical coordinates to Cartesian coordinates conversion
      var direction = new FastVector3(
        Math.cos(verticalAngle) * Math.sin(horizontalAngle),
        Math.sin(verticalAngle),
        Math.cos(verticalAngle) * Math.cos(horizontalAngle)
      );

      // Right vector
      var right = new FastVector3(
        Math.sin(horizontalAngle - 3.14 / 2.0), 
        0,
        Math.cos(horizontalAngle - 3.14 / 2.0)
      );

      // Up vector
      var up = right.cross(direction);

      // Movement
      if (moveForward) {
        var v = direction.mult(deltaTime * speed);
        position = position.add(v);
      }
      if (moveBackward) {
        var v = direction.mult(deltaTime * speed * -1);
        position = position.add(v);
      }
      if (strafeRight) {
        var v = right.mult(deltaTime * speed);
        position = position.add(v);
      }
      if (strafeLeft) {
        var v = right.mult(deltaTime * speed * -1);
        position = position.add(v);
      }

      // Look vector
      var look = position.add(direction);

      // Camera matrix
      view = FastMatrix4.lookAt(position, // Camera is here
                  look, // and looks here : at the same position, plus "direction"
                  up // Head is up (set to (0, -1, 0) to look upside-down)
      );

      // Update model-view-projection matrix
      mvp = FastMatrix4.identity();
      mvp = mvp.multmat(projection);
      mvp = mvp.multmat(view);
      mvp = mvp.multmat(model);

      mouseDeltaX = 0;
      mouseDeltaY = 0;
    }

One more thing - to enable culling, we adjust pipeline state.

    // Set culling
    pipeline.cullMode = CullMode.Clockwise;

You can access complete sources here.

And here it is! Enjoy flying around our little cube.

Clone this wiki locally