Jump to content

sprite follow lasso


skaplun
 Share

Recommended Posts

Hey,

I'm trying to get sprite to follow path user created after mouse up event. i think I need to add timer here or use the update loop, but not sure how. help will be appreciated :)

 

strategy: enable history, add event to sprite, iterate over history and travel along the XY coords

 

code:

 

     newSprite: function (parent, x, y, sideStr){
        var sprite= parent.create(x, y, sideStr);
        sprite.rotation = 1.61;
        sprite.inputEnabled = true;
        sprite.events.onInputDown.add(this.onD, this);
        sprite.events.onInputUp.add(this.onU, this);
 
        return sprite;
    },
 
        onU : function(sprite, pointer){
        var speed = 200;
        if(sprite.key === "enemy" || !pointer._history.length) return;
        pointer._history.forEach(function(v){
            if(speed + 1 < 500) speed++;
            this.game.time.events.loop(Phaser.Timer.SECOND);
            this.game.physics.arcade.accelerateToXY(sprite, v.x, v.y, speed, 900)
            
        })
Link to comment
Share on other sites

Can the user interrupt the sprite's progress once they've started on a path?

 

If not, you should probably chain a bunch of tweens together. Your loop won't work; the sprite will just accelerate towards the last point registered.

Link to comment
Share on other sites

thanks for the input, no the user can't interrupt progress.

Can you please explain why this can't be made to work?

my assumption is that we should be able to chain animations in canvas like one would do with jquery animate for the DOM.

or am I completely off in my thinking here?

 

Thanks again! :)

Link to comment
Share on other sites

This won't work because your call to accelerateToXY immediately sets the acceleration on the physics body. It ignores any previous acceleration and overrides it. Like this:

var angle = this.angleToXY(displayObject, x, y);displayObject.body.acceleration.setTo(Math.cos(angle) * speed, Math.sin(angle) * speed);

If you want to chain a series of changes over time together so that the next one only starts when the first one is over then you want a tween.

Link to comment
Share on other sites

thanks for the input, no the user can't interrupt progress.

Can you please explain why this can't be made to work?

my assumption is that we should be able to chain animations in canvas like one would do with jquery animate for the DOM.

or am I completely off in my thinking here?

 

Thanks again! :)

 

You can't run a tween while another tween is in progress - the object will be moving in one direction and then forced to move in another at the same time. The result? Disaster! Instead, the correct approach is to run the tween and when the tween completes, run the next tween.

 

You can do this by storing all your coordinates in an array (let's call it "path" and set it as a property on the sprite that that path is associated with), then create an onComplete event on the tween:

 

sprite.path = [10, 100, 300, 400, 500, 440]; // im guessing you are creating these coordinates with a pathfinding systemfunction moveToNext(sprite) {    if (sprite.path[0] == undefined) {        game.tweens.removeFrom(sprite);        sprite.path = [];        return; // if there are no coordinates left, stop trying to run this function    }    var time = 1000; // adjust this to set how fast the object moves. use distance/time/speed formula    var move = game.add.tween(sprite).to({        x: [sprite.path[0]],        y: [sprite.path[1]],    }, time);    move.onComplete.add(function() {        sprite.path.shift();        sprite.path.shift();        moveToNext(sprite);    });}

 

Link to comment
Share on other sites

Thanks alot guys, 

you're really helping me get there :)

 

I wanted to draw the path according to input.recordPointerHistory and the resulting pointer._history obj.

Is there any reason why that is a bad idea?

Link to comment
Share on other sites

If input.recordPointerHistory works the way I think it does (reading the doc), I think it would be a bad idea to use it at the default recordRate. If your sprite is moving to coordinates set by the pointer every 100 milliseconds, its going to be creating an awful lot of tweens awfully fast. You'll definitely want to change the recordRate to a higher value, perhaps 1000 milli. 

 

also, If you're planning on using my function, you'll need to check somewhere outside the function to determine if the path is no longer undefined and restart the tween. otherwise once the tween stops, it will stop forever. but i you only want the tween to start on mouse up? in that case, i would run it then. 

Link to comment
Share on other sites

tween with history working pretty well. made adjustments to record rates as suggested and I'm starting to like what I see.

 

I'm trying to get an object that starts in a 90 degree angle with velocity.x = 10 to rotate in the direction of the pointer coords, my updated tween looks like the below but the object is not rotating in the correct direction. I've tried various variations of the below based on all the info I could find but nothing worked. What should I be doing here?
 

Also I feel like I need a math lesson :) any tips on where to find the relevant resources?

 

    moveToNext: function (sprite, history) {
        var first = history[0];
        
        if (first == undefined) {
            return // sprite.kill();
        }
        var time = 2400; 
        
        var move = this.add.tween(sprite)
            .to({
                angle  : this.getAngle(sprite, first.x,first.y)
            }, 250, 'Power0' , false, 30, 0)
            .to({
                x: first.x,
                y: first.y,
            }, time, 'Power0' , false, 30, 0)
          
            .start();
        
        move.onComplete.add(function() {
            history.shift();
            return self.moveToNext(sprite, history);
        });
    }
Link to comment
Share on other sites

 

tween with history working pretty well. made adjustments to record rates as suggested and I'm starting to like what I see.

 

I'm trying to get an object that starts in a 90 degree angle with velocity.x = 10 to rotate in the direction of the pointer coords, my updated tween looks like the below but the object is not rotating in the correct direction. I've tried various variations of the below based on all the info I could find but nothing worked. What should I be doing here?

 

Also I feel like I need a math lesson :) any tips on where to find the relevant resources?

 

    moveToNext: function (sprite, history) {
        var first = history[0];
        
        if (first == undefined) {
            return // sprite.kill();
        }
        var time = 2400; 
        
        var move = this.add.tween(sprite)
            .to({
                angle  : this.getAngle(sprite, first.x,first.y)
            }, 250, 'Power0' , false, 30, 0)
            .to({
                x: first.x,
                y: first.y,
            }, time, 'Power0' , false, 30, 0)
          
            .start();
        
        move.onComplete.add(function() {
            history.shift();
            return self.moveToNext(sprite, history);
        });
    }

 

 

What you need to do is set the rotation of the object to be the same as the angle between the object and the vector the object is moving too. You've got the right idea, but there's some problems with your code. getAngle is not a method for sprites, unless you've created that method. If you've defined it elsewhere, make sure that it is returning degrees and not radians as angle is degrees by default (and that's the property you are tweening). Anyway, there really isn't a need to define your own method since Phaser has its own built in that will work for your scenario. You need to get the angle between an object and a vector. Use angleToXY. If your sprites are not physics-enabled, use Phaser.Math.angleBetween with the raw x/y of the sprite and the vector its moving to as the parameters. 

 

And you probably want to get and set the angle in radians, not degrees - it's not anymore difficult and has marginal performance benefits. So use the rotation property instead of angle (which is degrees by default). Setting the rotation of the sprite is a less roundabout way of changing the angle. 

 

moveToNext: function (sprite, history) {        var first = history[0];                if (first == undefined) {            return // sprite.kill();        }        var time = 2400;                 var move = this.add.tween(sprite)            .to({                rotation  : game.physics.arcade.angleToXY(sprite, first.x,first.y)            }, 250, 'Power0' , false, 30, 0)            .to({                x: first.x,                y: first.y,            }, time, 'Power0' , false, 30, 0)                      .start();                move.onComplete.add(function() {            history.shift();            return self.moveToNext(sprite, history);        });    }

A few other notes: you're rotation time should probably be a lot more than 250 milli. That's a super fast tween and (I suspect) you're rotating a small object. If it's 250, why bother tweening at all and just set the rotation without tweening?

 

Also, because you've set an arbitrary time, your sprite will move really fast if the distance is far and really slow if the distance is close. You do want speed to be arbitrary, so you can control how fast the sprite is going but you don't want time to be arbitrary. That is, the time it takes to get to the destination. Remember that time is a product of speed in relation to distance. You have the distance and you can set the speed (because it's arbitrary). So all you need to do is figure out the time with a basic formula:

 

function milliToDistance(distance, speed) {    var time = (1000 * distance / speed);    return time;}var speed = 60 //this is arbitrary. set it to determine how fast the sprite should tweenvar distance = game.physics.arcade.distanceToXY(sprite, xCoord, yCoord);var time = milliToDistance(distance, speed);

That's how you should calculate your time.   :D  

Link to comment
Share on other sites

Time solution brilliant, thanks.

I actually had to build on angleToXY because there was a -90 degree offset.

 

After some notepad calculations my getXY looks like:

 

    getAngleFromXYDiff : function(sprite, obj){
        var rad = this.physics.arcade.angleToXY(sprite, obj.x, obj.y),
            corrected = rad + (90 * (180 / Math.PI ));
        
        return corrected
        
     },

 

I'm putting this here in case this helps someone struggling with rotations. 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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