BdR Posted May 25, 2017 Share Posted May 25, 2017 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? 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]; } } Quote Link to comment Share on other sites More sharing options...
samid737 Posted May 27, 2017 Share Posted May 27, 2017 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). Quote Link to comment Share on other sites More sharing options...
stay Posted May 29, 2017 Share Posted May 29, 2017 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. BdR and samid737 2 Quote Link to comment Share on other sites More sharing options...
BdR Posted May 29, 2017 Author Share Posted May 29, 2017 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. Quote Link to comment Share on other sites More sharing options...
samid737 Posted May 30, 2017 Share Posted May 30, 2017 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... stay 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.