BdR

String of sprites following the player, best way to do it?

Recommended Posts

I'm working on a JavaScript game using Phaser, where the player picks up blobs and the blobs then follow the player. So there will be a string of sprites snaking behind the player. It should be similar to the "options" in Nemesis/Gradius that follow your space ship. Except there's more of them, so like a couple of dozens, so the effect is more like the line of balls in the game Zuma.

My question is, what is the best way to get this effect?
At the moment my method is like this:

* Keep a large array of x/y positions
* For each frame, put the player x/y position in the array
* For each blob, keep an array index and copy the x/y position from that array index.

It works, but I suspect there will problems with performence on mobile, as even on laptop it sometimes lags. Also when the line of blobs gets longer, the array needs to be resized. Although that could be solved by just making the array maximum size.

Any best-practices ideas for this?

phaser_blobs.png

Here's the code I've got so far:

function create() {
    // create the guy
    _grpblobs = game.add.group();
    _thedude = game.add.sprite(0, 0, 'phaserdude');
    _idxoff = 0;
    
    // add blobs
    for (var i=0; i<40; i++) {
        var blob = game.add.sprite(0, 0, 'orbs', (i%6));
        _grpblobs.add(blob);
    };

    // array to keep track of positions
    for (var i=0; i<1000; i++) {
        _blobpos[i] = 0;
    };

    // resize
    window.addEventListener("mousemove", onGameMouseMove);
}

function onGameMouseMove(evt) {
    _thedude.x = evt.x;
    _thedude.y = evt.y;
}

function update() {
    // the main guy current position
    _blobpos[_idxoff]   = _thedude.x;
    _blobpos[_idxoff+1] = _thedude.y;
    
    // -2 because it's 2 values; x value and y value
    _idxoff = _idxoff - 2;
    if (_idxoff < 0) _idxoff = _idxoff + 1000;
    
    // update blob positions
    for (var i=0; i < _grpblobs.length; i++) {
        var idx = _idxoff + ( (i+1) * 20);
        idx = idx % 1000;
        
        _grpblobs.children[i].x = _blobpos[idx];
        _grpblobs.children[i].y = _blobpos[idx+1];
    }
}

 

Share this post


Link to post
Share on other sites

Goedemorgen!

The effect you have made looks pretty much the same as using rendertextures to draw a trail. Maybe this example will give you more ideas/insight:

I think you will also have a benefit in performance by doing this (not sure though, you will have to compare).

Share this post


Link to post
Share on other sites

I've run into this scenario before, and I find it surprisingly difficult, especially if your frame rate varies at all.  It gets worse the more dynamic and responsive the effect needs to be - e.g. if these trailing things are real game objects, not just effects, and they join and leave on the fly, and they need to stop when you stop, and if one leaves and another is expected to move up to take its place, etc.

I think the approach you've started with (a recorded position array) is reasonable, and should work.  I've done exactly that, and it worked out fine in my case.  I admit I didn't care a lot about performance at the time, but I also didn't notice problems and didn't do any optimization.  I can't think of any obvious reason the code you've presented would have performance problems.

The one thing I was going to suggest right away was using a circular buffer, but you're already doing that. :)

If the player can stop and you want the followers to stop, you can suppress adding new positions to the list until the hero has moved a minimum amount from their last position.

For the sake of offering alternatives, a more complicated approach is to treat the trail like a spline (or something similar - even just some simple interpolation code from point to point).  Track positions like you have, but each point in your list is a node in a spline.  Then you just need to know a distance along the splice (maybe an interpolation value from 0 to 1) for each trailing object, and you can determine per frame exactly where each object needs to be.

The downside is this is a lot of work, and fairly technical.  And it may not do you any favors in terms of performance.  The upside is that it's extremely flexible and dynamic.  You change spacing between objects, remove one in the middle, etc.  And everything can be ultra smooth, since you're using interpolated points on a spline.  Another upside is you can make the array as long or short as you want, and collect points more infrequently.

This is all probably not very useful if you really just want a visual effect and not gameplay objects.

And if you find a better approach, I'd love to hear about it, since I keep running into this. :)

Share this post


Link to post
Share on other sites

Okay, thanks for the tips and advice :) I do want the blobs to interact and check collisions/overlaps with other game objects etc. so I'll try some more stuff. They don't need any animations and I might use a SpriteBatch for better performance maybe.

btw I've created a "pen" of the example code, here it is. Click on "Edit on CodePen" to view it.

 

 

Share this post


Link to post
Share on other sites

To elaborate @stay his suggestion for spline interpolation, here is an example of how to do so (based upon this source):

 

You have the option to choose which interpolation method to use (within the plot function). It looks like linear interpolation will do fine in your case. There are also two parameters (deltaT and dataPointLimit) that determine the way your trail will behave, so you can tweak those numbers. As you can see, the spacing between sprites is not fixed, this is because the motion path itself is not linear. If you want equidistance, you might have to do some calculus/numeric integration to compute the distances of each segment (arc length computation) or you maybe you can figure something out in the code.. By the way I tested your codepen on an Iphone 5C, it looks smooth, maybe an indication that your on the right track with your own code?..... The interpolation method also works fine on the same device...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.