Add touch movement

Hello, to the mouse movement i want to add movement for phones, is it better the touch movement or vr movement? with keys i have wasd and mouse to rotate and tilt and with a phone?

For your game, I would use touch controls by allowing the player to move where they tap on screen. Rotating/pitching the camera can be handled using finger dragging (like the Model Viewer example).

Thinking of games like Diablo in terms of controls.

Ah right sorry @yaustar this question doesn’t involve the game (not yet) it’s for this project of a virtual showroom https://playcanvas.com/editor/scene/584692 anyway i will keep in mind your suggestion for when i take that step in the game :wink: actually i’m looking for the best way to navigate the showroom from a mobile or a tablet

1 Like

Hmm… Another input method is to use touch/finger dragging to rotate the camera like an FPS and use zoom in/out gesture to move forward/back.

Or you can use the Google Maps method and tap an on screen arrow to move X steps forward?

Yes that’s a good way i think, some demo as reference?

Seems that implement touch commands isn’t as simple as i thought :slight_smile: tried 3 different scripts without success

What do i do wrong with the touch commands?

var FirstPersonMovement = pc.createScript('firstPersonMovement');

// optional, assign a camera entity, otherwise one is created
FirstPersonMovement.attributes.add('camera', {
    type: 'entity'
});

FirstPersonMovement.attributes.add('power', {
    type: 'number'
});

FirstPersonMovement.attributes.add('lookSpeed', {
    type: 'number'
});

// initialize code called once per entity
FirstPersonMovement.prototype.initialize = function() {
    this.force = new pc.Vec3();
    //this.camera = null;
    this.eulers = new pc.Vec3();
    var ang=0;
    var app = this.app;
    
    // Listen for mouse move events
    app.mouse.on("mousemove", this._onMouseMove, this);
    
    this.lastTouchPoint = new pc.Vec2();
    var touch = this.app.touch;
    if (touch) {
        touch.on(pc.EVENT_TOUCHSTART, this.onTouchStart, this);
        touch.on(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
        touch.on(pc.EVENT_TOUCHEND, this.onTouchEnd, this);
        touch.on(pc.EVENT_TOUCHCANCEL, this.onTouchCancel, this);
    }    

    // Check for required components
    if (!this.entity.collision) {
        console.error("First Person Movement script needs to have a 'collision' component");
    }

    if (!this.entity.rigidbody || this.entity.rigidbody.type !== pc.BODYTYPE_DYNAMIC) {
        console.error("First Person Movement script needs to have a DYNAMIC 'rigidbody' component");
    }
};

// update code called every frame
FirstPersonMovement.prototype.update = function(dt) {
    // If a camera isn't assigned from the Editor, create one
    if (!this.camera) {
        this._createCamera();
    }
    
    var force = this.force;
    var app = this.app;

    // Get camera directions to determine movement directions
    var forward = this.camera.forward;
    var right = this.camera.right;
       

    // movement
    var x = 0;
    var z = 0;

    // Use W-A-S-D keys to move player
    // Check for key presses
    if (app.keyboard.isPressed(pc.KEY_A)) {
        x -= right.x;
        z -= right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_D)) {
        x += right.x;
        z += right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_W)) {
        x += forward.x;
        z += forward.z;
    }

    if (app.keyboard.isPressed(pc.KEY_S)) {
        x -= forward.x;
        z -= forward.z;
    }

    // use direction from keypresses to apply a force to the character
    if (x !== 0 && z !== 0) {
        force.set(x, 0, z).normalize().scale(this.power);
        this.entity.rigidbody.applyForce(force);
    }

    // update camera angle from mouse events
    this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0);
};

FirstPersonMovement.prototype._onMouseMove = function (e) {
    // If pointer is disabled
    // If the left mouse button is down update the camera from mouse movement
    if (pc.Mouse.isPointerLocked() || e.buttons[0]) {
        this.eulers.x -= this.lookSpeed * e.dx;
        this.eulers.y -= this.lookSpeed * e.dy;
    }            
};

FirstPersonMovement.prototype.onTouchStart = function (event) {
    var touch = event.touches[0];
    this.lastTouchPoint.set(touch.x, touch.y);
};


FirstPersonMovement.prototype.onTouchMove = function (event) {
    var touch = event.touches[0];
    var dx = touch.x - this.lastTouchPoint.x;
    var dy = touch.y - this.lastTouchPoint.y;
    
    this.eulers.x -= this.lookSpeed * dx;
    this.eulers.y -= this.lookSpeed * dy;
    this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0);
    this.lastTouchPoint.set(touch.x, touch.y);
};

FirstPersonMovement.prototype._createCamera = function () {
    // If user hasn't assigned a camera, create a new one
    this.camera = new pc.Entity();
    this.camera.setName("First Person Camera");
    this.camera.addComponent("camera");
    this.entity.addChild(this.camera);
    this.camera.translateLocal(0, 0.5, 0);
};

FirstPersonMovement.prototype.updateFromScreen = function (screenPos) {
    // Use the camera component's screenToWorld function to convert the 
    // position of the mouse into a position in 3D space
    var depth = 5;
    
    this.cameraEntity.camera.screenToWorld(screenPos.x, screenPos.y, depth, this.pos);

    // Finally update the cube's world-space position
    this.entity.setPosition(this.pos);    
};
1 Like

Looks reasonable from a quick look. What issues are you running into?

That the phone ignore the touch :smiley:

Is it ignoring the touch or is the logic in the script that is the issue?

For example:

  • Have you verified that the touch events handlers are being registered?
  • Are there multiple cameras being created/in the scene?
  • Are the values for this.eulers actually changing?

Found why, in the script priority it launched a script that i thought it shouldn’t coz i didn’t add it to any entity, but with script 2.0 it’s slightly different :smiley: anyway now it seems to work…also if camera can get rotated upside down and i should prevent that :smiley:

Just discovered that on iphone don’t work while in android it does