Jump to content

[SOLVED] - Virtual Joystick Usage


Recommended Posts

I have been looking thru the code for virtual joystick camera (which is really just a free camera and calling inputs.addVirtualJoystick).

I tried using VirtualJoystick manually but i don't see the left and right joystick on screen (using iPad just for testing...slow but just used to test)...

I can see the virtual joystick is created and "disabled context menu"... just no sticks rendered to screen...

All my other ancient is at either 0, 1, or 2 z-Index so the z-Index: 5 the virtual joystick is using should be fine.

I have hand.js and loaded to pollyfill onPointerXXXX

Or is the Virtual Joystick even supported on iPad... Can we make the virtual joysticks appear on regular computer at lest for testing???

Here is code my for initing Virtual Joysticks (looks good but doesn't show sticks):

if (BABYLON.SceneManager.leftJoystick == null) {
    BABYLON.SceneManager.leftJoystick = new VirtualJoystick(true);
if (BABYLON.SceneManager.rightJoystick == null) {
    BABYLON.SceneManager.rightJoystick = new VirtualJoystick(false);
    BABYLON.SceneManager.rightJoystick.reverseUpDown = true;


Let me know if you know what the deal is hear :)


Link to comment
Share on other sites

        private divMove;
        private divRotate;
        private rotPosX0 = 0;
        private rotPosY0 = 0;
        private radY = 0;
        private radX = 0;
        private movePosX0 = 0;
        private movePosY0 = 0;
        private moveX = 0;
        private moveZ = 0;

        private setControls(): void {

            this.rotStart = this.rotStart.bind(this);
            this.rotRun = this.rotRun.bind(this);
            this.rotEnd = this.rotEnd.bind(this);

            this.moveStart = this.moveStart.bind(this);
            this.moveRun = this.moveRun.bind(this);
            this.moveEnd = this.moveEnd.bind(this);

            this.divMove = document.getElementById("c-move");
            this.divRotate = document.getElementById("c-rotate");

            this.divRotate.addEventListener("touchstart", this.rotStart);
            this.divRotate.addEventListener("touchend", this.rotEnd);

            this.divMove.addEventListener("touchstart", this.moveStart);
            this.divMove.addEventListener("touchend", this.moveEnd);


        private rotStart(e): void {
            this.rotPosX0 = e.touches[0].clientX;
            this.rotPosY0 = e.touches[0].clientY;
            this.divRotate.addEventListener("touchmove", this.rotRun);

        private rotRun(e): void {
            if (!this.camera) return;
            var touch = e.touches[0];

            var speedY = (touch.clientX - this.rotPosX0) / 700;
            var speedYAbs = Math.abs(speedY);
            if (speedYAbs > .04 && speedY > 0) {
                speedY = .04;
            } else if (speedYAbs > .04 && speedY < 0) {
                speedY = -.04;
            this.radY = speedY;

            var speedX = (touch.clientY - this.rotPosY0) / 2000;
            var speedXAbs = Math.abs(speedX);
            if (speedYAbs < 0.01) {
                if (speedXAbs > .03 && speedX > 0) {
                    speedX = .03;
                } else if (speedXAbs > .04 && speedX < 0) {
                    speedX = -.04;

                //this.radX = speedX;


        private rotEnd(e): void {
            this.divRotate.removeEventListener("touchmove", this.rotRun);
            this.radX = 0;
            this.radY = 0;

        private moveStart(e): void {
            this.movePosX0 = e.touches[0].clientX;
            this.movePosY0 = e.touches[0].clientY;
            this.divMove.addEventListener("touchmove", this.moveRun);

        private moveRun(e): void {
            if (!this.camera) return;
            var touch = e.touches[0];

            var speedZ = (touch.clientY - this.movePosY0) / 70;
            var speedAbsZ = Math.abs(speedZ);
            this.moveZ = speedZ;

            var speedX = (touch.clientX - this.movePosX0) / 100;
            var speedXAbs = Math.abs(speedX);

            if (speedAbsZ < 0.2) {
                this.moveX = speedX;
                //this.moveZ = 0;


        private moveEnd(e): void {
            this.divMove.removeEventListener("touchmove", this.moveRun);
            this.moveX = 0;
            this.moveZ = 0;

And in the main loop:

            this.camera.rotation.y += this.radY;
            this.camera.rotation.x += this.radX;

            if (this.camera._localDirection) {
                this.camera._localDirection.copyFromFloats(this.moveX, 0, -this.moveZ);
                BABYLON.Vector3.TransformNormalToRef(this.camera._localDirection,         this.camera._cameraTransformMatrix, this.camera._transformedDirection);

            var rx = this.camera.rotation.x;
            if (rx <= -.35) {
                this.camera.rotation.x = -.35;
            } else if (rx >= .25) {
                this.camera.rotation.x = .25;


Link to comment
Share on other sites

haha.  Max123... been there... done that.  :)  Sucks getting blocked-out of the playground editor and its menu buttons (or other gui), eh?

A little secret.  When blocked, open browser f12 dev tools... "inspector" (document inspector).  Scroll to </body> at end of document.  Do you see a <canvas> element just before the </body>?  If so, highlight it (in the inspector html source code)... and hit delete.  Remove that LAST canvas, and you should have access the underlying screen.

Here is a demo where I once did VJ tests.  http://www.babylonjs-playground.com/#2J6AXA#0

Lines 88-94 is a safety net... that should get you un-stuck after 20 seconds.

A newer way to do the VJ graphics... would be with canvas2d.  It needs no extra html-canvas over-layed atop the screen.  It uses a different kind of canvas.  BUT... if you want to have "two-thumb fun" in a playground scene (using VJ's)... then guess what?  Left thumb needs to be atop editor area of playground.  And thus, the left thumb VJ graphics needs to be atop the playground editor, too. 

AND... we have not yet seen proof that a screenSpaceCanvas2D is allowed to extend outside of renderCanvas and onto html parts of the screen.  :o  It won't be uncommon for webGL pages to have adopt the classic 3 column motif (narrow left and right html button columns, with big webGL canvas in the middle).  This issue might actually dictate game design and GUI trends... in the future.  We may see less HTML in the side columns, and more webGL full-screen... with MESH or Canvas2D buttons making-up the left/right button columns.   But even THAT poses a problem for the VJ graphics (z-index and canvas2d layering).  hmm.

The jury is still out... about how canvas2D will be used with future virtual joystick graphics (and for pinch/swipe gfx, too).  Everyone is all hush-hush about it.  :D   Ok, party on.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...