DevLog #11 - Virtual Javascript Joystick and UI Enhancements

Hi, welcome to VR Me Up Developer Log number 11. This release has seen some improvements to the desktop and particularly the mobile user interface.

The buttons at the bottom of the screen have been replaced with an easier to use, and much more functional “Virtual Joystick” in the lower left corner of the screen. The other menu options have been condensed and moved into a more compact menu bar at the bottom. This will leave a lot more room for some exciting new features I’m going to be adding in upcoming releases.

For usability reasons, the joystick is only visible on touch devices like phones and tablets.

The new “virtual Joystick” was implemented using some HTML, CSS and Java Script and sits over the Three.js 3D canvas. The code I used to do this is available as a JSFiddle “HTML Virtual Joystick” if you want to use something like it in your own projects. I’ll put a link in the description. The joystick allows you to move forward, backwards, left and right at varying speeds.

To change the direction you are looking, you can still just touch and drag anywhere else on the screen to move your head. Of course, you can use this and the joystick at the same time to give you a lot more control over your avatars movement, and hopefully provides a lot more fun experience than the old buttons.

One of the useful things I learnt while coding these changes was to always track the “touch identifier” when handling the touch events. I had naively been ignoring this in the past as I assumed people would only be using one finger. When needing to use multiple fingers to control both the movement and the head, this approach of course did not work.

onTouchStart(e) {
    if(e.changedTouches) {
        this._touchIdentified = e.changedTouches.item(0).identifier ;
        this.handled(e);
    } else {
        this._touchIdentified = -2 ; // mouse
    }
}

onTouchMove(e) {
    const touch = this.findTouch(e.changedTouches, this._touchIdentified, e) ;
    if(touch) {
        this.moveThumbTo(touch.pageX, touch.pageY);
        this.handled(e);
    }
}

onTouchEnd(e) {
    const touch = this.findTouch(e.changedTouches, this._touchIdentified, e) ;
    if(touch) {
        this._touchIdentified = -1 ;
        this.onTouchCancel(e);
    }
}

onTouchCancel(e) {
    this._touchIdentified = -1 ;
    this.x = 0.0 ;
    this.y = 0.0 ;
    this.resetThumb();
}

findTouch(touchList, identifier, e) {
        if(identifier === -2) {
            return { pageX : e.pageX, pageY : e.pageY } ;
    }
    if (touchList && identifier !== undefined) {
        for(let touch of touchList) {
            if(touch.identifier === identifier) {
                return touch;
            }
        }    
    }
    return undefined;
} 

This required some additional changes to my input system in other areas, which took a while to implement and debug, but it was worth it. I now have a much more robust input system. Lesson learnt!

I also added a configurable “padding zone” to the joystick. This is a small area in the centre of the joystick that will always return a 0 value. This allows you to leave your finger on the joystick in the centre position and not have the avatar slowly move.

Avatar view menu
Avatar view menu

Switching between First Person, Third Person and Gyroscope modes has been moved to a popup button to the left of the VR button. The avatars character selection dialog has been made even more accessible, by using the “coat hanger” button to the right of the VR button. Additionally, you can still get to the avatar dialog from the main virtual menu at the top of the screen while in VR mode.

I hope you find the new User Interface changes an improvement. See you in the Metaverse!

VR Me Up!

Let's Get In Touch!


Join us on the journey creating an Open Metaverse