Help with drag and movement in orthogonal directions

The attached is a puzzle game I’m trying to build using Phaser 3. I’ve been able to get the drag and motion going as I desire it. On drag, I simply set the velocity of the x and y coordinates depending on the drag direction. When it collides with a block, I set the velocity to 0 to stop the motion. That is how I was able to achieve the drag and motion for the puzzle game.

The challenge I have is that I need to only support movements in up, down, left and right directions. At present, the user could drag the object diagonally which is what I need to prevent. Any assistance with this would be appreciated.

As a follow up, I also need to ensure that movement of the UFO object stays within the grid elements of my squares. I haven’t quite figured out the best way of doing this as the user could drag it ‘outside’ the squares in my background image. I’m still very new to Phaser 3, so will appreciate support in achieving both objectives.

The below is my source code:

var app = {
    // Application Constructor
    initialize: function () {
    document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
},

// deviceready Event Handler
//
// Bind any cordova events here. Common events are:
// 'pause', 'resume', etc.
onDeviceReady: function () {
    var config = {
        type: Phaser.AUTO,
        parent: 'game',
        physics: {
            default: 'arcade',
            arcade: { /*gravity:  { y: -300 },*/ debug: false}
        },
        scene: {
            preload: preload,
            create: create,
            render: render,
            update: update
        },
        width: 550,
        height: 680
    };

    var game = new Phaser.Game(config);
    var currentX, currentY = 0;
    var cow1, cow2, cow3, cow4, cow5, player, blocks1, blocks2, blocks3, blocks4, blocks5, blocks, draggedObject,
        starGold, starBronze, collider1 = null;
    var isMovingRight, isMovingLeft, isMovingUp, isMovingDown = false;
    var dragGravity = 600;

    function preload() {
        this.load.image('canvas', 'img/canvas-8x10.png');

        this.load.image('starGold', 'img/starGold.png');
        this.load.image('starBronze', 'img/starBronze.png');

        this.load.image('block', 'img/block.png');
        this.load.image('clown', 'img/clown.png');
        this.load.image('ufo', 'img/ufo-4.jpg');
        this.load.image('cow', 'img/cow-1.jpg');
    }

    function create() {
        let canvas = this.add.image(0, 0, "canvas");
        canvas.setOrigin(0);
        canvas.setScale(0.46);

        cow1 = this.physics.add.staticImage(175, 110, 'starGold');
        cow2 = this.physics.add.staticImage(175, 250, 'starGold');
        cow3 = this.physics.add.staticImage(175, 380, 'starGold');
        cow4 = this.physics.add.staticImage(450, 590, 'starGold');
        cow5 = this.physics.add.staticImage(107, 590, 'starGold');

        blocks1 = this.physics.add.staticGroup({
            key: 'block',
            repeat: 8,
            setXY: {x: 35, y: this.sys.game.config.height - 30, stepX: 60}
        });

        blocks2 = this.physics.add.staticGroup({
            key: 'block',
            repeat: 8,
            setXY: {x: 35, y: 100, stepY: 60}
        });

        blocks3 = this.physics.add.staticGroup({
            key: 'block',
            repeat: 4,
            setXY: {x: 95, y: 313, stepX: 60}
        });

        blocks4 = this.physics.add.staticGroup({
            key: 'block',
            repeat: 8,
            setXY: {x: 35, y: 35, stepX: 60}
        });

        blocks5 = this.physics.add.staticGroup({
            key: 'block',
            repeat: 8,
            setXY: {x: this.sys.game.config.width - 35, y: 100, stepY: 60}
        });

        player = this.physics.add.sprite(100, 450, 'ufo').setInteractive();
        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        this.physics.add.collider(player, [blocks1, blocks2, blocks3, blocks4, blocks5], detectCollision, null, this);
        this.physics.add.overlap(player, [cow1, cow2, cow3, cow4, cow5], detectCowCollision, null, this);

        var self = this;

        player.on('pointerover', function () {
            this.setTint(0x00ff00);
        });

        player.on('pointerout', function () {
            this.clearTint();
        });

        this.input.setDraggable([player]);

        this.input.dragTimeThreshold = 100;

        this.input.on('dragstart', function (pointer, gameObject) {
            gameObject.setTint(0xff0000);

            currentX = gameObject.x;
            currentY = gameObject.y;

            draggedObject = gameObject;
        });

        this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
            gameObject.x = currentX;
            gameObject.y = currentY;

            isMovingDown = false;
            isMovingUp = false;
            isMovingLeft = false;
            isMovingRight = false;

            if (dragY > currentY) {
                isMovingDown = true;
                gameObject.body.setVelocityY(dragGravity);
            } else if (dragY < currentY) {
                isMovingUp = true;
                gameObject.body.setVelocityY(-dragGravity);
            } else if (dragX > currentX) {
                isMovingRight = true;
                gameObject.body.setVelocityX(dragGravity);

            } else if (dragX < currentX) {
                isMovingLeft = true;
                gameObject.body.setVelocityX(-dragGravity);
            }
        });

        this.input.on('dragend', function (pointer, gameObject) {
            gameObject.clearTint();
        });
    }

    function moveDown(gameObject) {
        config.physics.accelerateTo(gameObject, gameObject.x, gameObject.y + 200, 200);
    }

    function detectCollision(star, block) {
        draggedObject.body.setVelocityX(0);
        draggedObject.body.setVelocityY(0);
    }

    function detectCowCollision(star, block) {
        block.disableBody(true, true);
	}

    function update(time, delta) {
        return;

        // if(isMovingDown && draggedObject.y < (this.sys.game.config.height - 30)){
        //     draggedObject.y += 6;
        //     // console.log('isMovingDown: ' + draggedObject.y);
        // }
        //
        // if(isMovingUp && draggedObject.y > 30){
        //     draggedObject.y -= 6;
        //     // console.log('isMovingUp: ' + draggedObject.y);
        // }
        //
        // if(isMovingRight && draggedObject.x < (this.sys.game.config.width - 30)){
        //     draggedObject.x += 6;
        //     // console.log('isMovingRight: ' + draggedObject.x);
        // }
        //
        // if(isMovingLeft && draggedObject.x > 30){
        //     draggedObject.x -= 6;
        // 	   // console.log('isMovingLeft: ' + draggedObject.x);
        // }
    }


    function render() {
        // game.debug.text(result, 10, 20);
        this.debug.text(result, 10, 20);
    }
 },
};

app.initialize();

Hi @memcache, here is a solution that might help. Try adding some threshold to your direction conditions, so that it will only move in that direction if they drag more in that direction. And also make the velocity of the direction its not moving in to 0.

    if (dragY > currentY + threshold) {
        isMovingDown = true;
        gameObject.body.setVelocityY(dragGravity);
        gameObject.body.setVelocityX(0);
    } else if (dragY < currentY - threshold) {
        isMovingUp = true;
        gameObject.body.setVelocityY(-dragGravity);
        gameObject.body.setVelocityX(0);
    } else if (dragX > currentX + threshold) {
        isMovingRight = true;
        gameObject.body.setVelocityX(dragGravity);
        gameObject.body.setVelocityY(0);

    } else if (dragX < currentX - threshold) {
        isMovingLeft = true;
        gameObject.body.setVelocityX(-dragGravity);
        gameObject.body.setVelocityY(0);
    }
2 Likes

Thanks @123survesh. Setting the velocity of the alternative X or Y coordinates did the trick! Much appreciated. The player now only goes in an orthogonal direction. I made my dragThreshold=30 which appears to be a good value.

1 Like