Sunburned Goose Posted May 29, 2014 Share Posted May 29, 2014 I use the the thrust function of P2 to move a character around in space. When the character nears a planet, I would like to give them a projection of their future location to help them see that they might be pulled into the planet. Is there a feature of P2 and Phaser that let me do this? I was thinking that there might be a way to create a sprite and call the update function to move it and rely upon the P2JS system to update the position of the sprite for the change in time, but I don't know white how to do that right now, Ideas? Red => FutureGreen => Past Looking at this second image, you can see how my calculations right now are coming up a bit shallow for very elliptical orbits. Link to comment Share on other sites More sharing options...
Zef Posted May 29, 2014 Share Posted May 29, 2014 Hmm thats an interesting one. So do you have it working in those screen caps? Is that using something other than phaser? The first idea that comes to my head would be to make a copy the p2 world and step that one forward to find out the position of the sprite a number of frames ahead. I don't know how expensive this will be but I am sure it would be possible. In fact, briefly looking at the p2 docs there is a world.clone() function, and word.step(float) function to move the world forward. I haven't tried but I bet you could do it using those two Link to comment Share on other sites More sharing options...
Sunburned Goose Posted May 30, 2014 Author Share Posted May 30, 2014 Thanks. I'll look at those functions. This has been made in Phaser 2.0.3 but it is slow and inaccurate. Link to comment Share on other sites More sharing options...
cub Posted May 30, 2014 Share Posted May 30, 2014 Take a look to this tutorial http://gamemechanicexplorer.com/#bullets-5 Link to comment Share on other sites More sharing options...
lewster32 Posted May 30, 2014 Share Posted May 30, 2014 It's certainly a non-trivial problem, as it requires having to understand the concepts and maths behind the physics calculations themselves, and then if necessary, adapting them to match the actual calculations the engine performs based on any shortcuts or optimisations it takes. I'm pretty sure all three physics systems work procedurally, meaning they don't pre-plan the trajectories of the objects, they just update them every frame based on current forces - so you're left with two options; the 'brute force' option where you run the physics system at high speed to generate a plotted path, or the 'mathematical' option where you actually calculate the trajectories ahead of time. Link to comment Share on other sites More sharing options...
schteppe Posted May 31, 2014 Share Posted May 31, 2014 What if you manually copy the p2.World instance and step it? I believe that you'll only need a single body in that world copy, and stepping such small system should be fast. Make sure you use the same parameters, such as gravity, time step, damping, etc, and it should give you the correct trajectory.If you choose to make the computations manually, you could just mimic the .integrateBody function in p2.World.If you want more P2 specific help, create an issue on our Github page. https://github.com/schteppe/p2.js Link to comment Share on other sites More sharing options...
Sunburned Goose Posted June 2, 2014 Author Share Posted June 2, 2014 I'm using Euler's Integration and that's doing a fine job matching up with P2's Thrust/Force system once I do enough calculations to remove enough error. It works just fine as is, but I had hoped to use a RK4 integration so I could use a time function to do the same thing. Calculates the Forces on the ShipSoi.Entities.Ship.prototype.calculateForce = function (aBody, bBody) { var d, g, mass, f, a; var force; if (!aBody) { aBody = this; } bBody = this.getNearestBody(aBody); if (!bBody) { force = new Phaser.Point(0,0); } else { var bC = bBody.center; d = Soi.Math.distanceBetween(aBody.center, bC); g = bBody.gravity; mass = bBody.mass; f = g * mass / Math.max(d * d, 10); a = Phaser.Math.angleBetween(aBody.x, aBody.y, bC.x, bC.y) + Math.PI / 2; force = new Phaser.Point(f * Math.cos(a), f * Math.sin(a)); } return force;};Creates an array of points to represent the position at intervals.Soi.Entities.Ship.prototype.calculatePositions = function() { var positions = []; var currentPosition = this.center; var currentVelocity = new Phaser.Point(this.body.velocity.x, this.body.velocity.y); this._currentPosition = { 'x': 0, 'y': 0, 'center': { 'x': 0, 'y': 0 }, 'exists': true }; var span = 300; var step = -0.36; var spanSteps = span / 5; var spanMod = spanSteps - 1; for(var i = 0; i < span; i++) { this._currentPosition.x = this._currentPosition.center.x = currentPosition.x; this._currentPosition.y = this._currentPosition.center.y = currentPosition.y; this._currentPosition.exists = this.exists; var currentForce = this.calculateForce(this._currentPosition); var fx = this.body.world.pxmi(currentForce.x * step); var fy = this.body.world.pxmi(currentForce.y * -1 * step); currentVelocity.x = currentVelocity.x + fx; currentVelocity.y = currentVelocity.y + fy; currentPosition.x += currentVelocity.x * step; currentPosition.y += currentVelocity.y * step; if (i % spanSteps === spanMod) { positions.push({ 'x': currentPosition.x, 'y': currentPosition.y}); } } return positions;};Updates sprites to represent the positions. _.each(positions, function(position, index) { var point = that.futurePosition[index]; point.x = position.x; point.y = position.y; }); Link to comment Share on other sites More sharing options...
Recommended Posts