How to determine the direction an object is moving to?

I have an object (a character) wich moves randomly around the screen. Also I have four animations (left, right, up and down) and I should select the respective animation accordingly to the direction the object is going to.

Thus I need a way of detecting what direction my object is moving to. Of course if it’s moving in diagonal (say to top-right) and it’s going “more” to the top than to the right I would select the top animation. And so on.

Any idea on how can I detect in which direction it’s moving?

1 Like

Check body.velocity.x and y.

Hey Samme!

I tried this:

update() {
        console.log (aEnemies[0].body.velocity.x);
}

But it’s returning me Uncaught TypeError: Cannot read property ‘velocity’ of null

I made a couple tests and figured that aEnemies[0].body returns null.

Here is the code I am using to instantiate enemies dinamically (it works fine, the animations, path, sprite, all runs well):

     AddEnemy = (enemy,aPaths,path,pathduration) => {
        // __MOVES contains the 4 animations references (left,right,up,down)
        // aPaths is an array with different paths which object can follow randomly
        // path is the index of aPaths array of the default path to be used
        // pathduration is the value in ms to run the path

        // create the 4 animations (left,right,up,down)
        for (var m=0;m<=__MOVES.length-1;m++) {
            this.anims.create({
                key: enemy+__MOVES[m],
                frames: this.anims.generateFrameNumbers(enemy+__MOVES[m]),
                frameRate: __ENEMYFRAMERATE,
                repeat: -1
            });
        }

        // add enemy
        this[enemy] = this.add.sprite(0, 0);

        // set path
        this[enemy].pathFollower = this.plugins.get('rexpathfollowerplugin').add(this[enemy], {
            path: aPaths[path],
            t: 0,
            rotateToPath: false
        });

        // add tween
        this.tweens.add({
            targets: this[enemy].pathFollower,
            t: 1,
            ease: 'Linear',
            duration: parseInt(pathduration),
            repeat: 0,
            yoyo: false
        });

        this[enemy].play(enemy+"Right");
        aEnemies.push(this[enemy]);
    }

this.AddEnemy(__CIRCLE,aPaths,3,10000); // __CIRCLE just holds the string "Circle"

Any idea?

I assumed you were using Arcade Physics. :frowning:

Check the rexpathfollowerplugin docs.

You could check the x/y of this[enemy].pathFollower in the tween onUpdate callback.
Compare if with the previous x/y, and you know the direction.
You’ll be one step behind though :slight_smile:
To fix that you would need to set pathFollower.t yourself. (or use Path.Getpoint).
Or even simpler, just use Path.getTangent.

I think you can get a tangent point on the path at t.

Samme, I used the plugin because at the time when I was starting learning Phaser I didn’t find a native path follower example.

Now that you mentioned it I just found this example and this one. Are these Arcade Physics codes?

Have a look at this page… Collision Detection and Physics - JavaScript Tutorial | Spicy Yoghurt

There’s info there to get the direction an object is moving in. It’s a pretty good read overall.

1 Like

No, those aren’t Arcade Physics examples.

See path.getTangent() etc. in

1 Like

Cool!

I wrote a code that is working but that demands manual adjusts for each case and I don’t like it. I will check this example!

:smiley:

The OP didn’t specify exactly that they were using arcade physics but it shouldn’t matter at all because you just need to get the objects velocity which should be possible when using arcade physics.

1 Like

Samme, I think that your approach will be very useful to me! I played with the code and adapted it to my own code and it works to change left-right and it does that by comparing if the tan.x is negative (left) or positive (right). I would like to transform tan.x in angles.

There is formula or Phase method to do this?

tan.angle(), radians

1 Like

Samme, your post with the running example plus the tan.angle() gave me enough to solve my issue.

Given that the tan.angle() will return a value between 0 and 6.4 I just had to divide it by 4 and get the ranges. This is the simplified code for whose may have the same difficulty:

preload() {
	this.load.spritesheet('Right','assets/animations/Right.png', { frameWidth: 60, frameHeight: 56 });
	// add the other spritesheets here (Left, Up and Down)...
}

create() {
        var path = new Phaser.Curves.Path(50,150).lineTo(150,50).lineTo(250,50).lineTo(350,150).lineTo(350,250).lineTo(250,350).lineTo(150,350).lineTo(50,250).lineTo(50,150);
        path.draw(graphics);

	// create animations
	this.anims.create({
		key: 'Right',
		frames: this.anims.generateFrameNumbers('Right'),
		frameRate: 15,
		repeat: -1
	});

	// create the other animations here (Left, Up and Down)...

        // add the character
        this.mycharacter = this.add.follower(path, -20, 200, 'Right').startFollow({
            duration: 10000,
            loop: 0,
        });
}

update() {
	var anim = "";
	var tan = this.path.getTangent(this.mycharacter.pathTween.getValue());
	
	if ((tan.angle() >= 2.4) && (tan.angle() <= 4))
		anim = "Left";
	
	if (((tan.angle() >= 0) && (tan.angle() <= 0.8)) || ((tan.angle() >= 5.6) && (tan.angle() <= 6.4)))
		anim = "Right";
	
	if ((tan.angle() > 4) && (tan.angle() < 5.6))
		anim = "Up";
	
	if ((tan.angle() > 0.8) && (tan.angle() < 2.4))
		anim = "Down";
	
	if ((this.mycharacter.anim != anim) && (anim != "")) {
		this.mycharacter.anim = anim;
		this.mycharacter.play(anim);
	}
}

:slightly_smiling_face:

Its worth noting I solved a similar problem with help from this video from @supertommy:

Works great if you have your object’s XY and your target’s. I use this for navigating through a tilemap in an isometric environment. Here’s my code:

updateGameObject () {

		var tileX = this.tileX;
	var tileY = this.tileY;
	
	var motion = this.motion;
	
	var currentX = this.x;
	var currentY = this.y;
	var newTargetX = this.targetX;
	var newTargetY = this.targetY;
	
	var targetRad = Phaser.Math.Angle.Between(
			currentX, currentY,
			newTargetX, newTargetY
		);
	
	var targetDegrees = Phaser.Math.RadToDeg(targetRad);
	
	
	//DETERMINE SOUTHEAST IN DEGREES
	if (targetDegrees > 22.5 && targetDegrees < 67.5 ) {
			this.direction = 'southEast';
		}

}
1 Like