Last active
November 16, 2019 20:58
-
-
Save ederst/bb75db4beb74620a7c8569635a0a8889 to your computer and use it in GitHub Desktop.
simple planetary gravity with phaser3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on this example: | |
// * http://jsfiddle.net/gJ4kA/ | |
// further reads: | |
// * https://gamedev.stackexchange.com/questions/71233/planet-gravity | |
// * https://gamedev.stackexchange.com/questions/21063/2d-planet-gravity | |
// * http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ | |
// calc: https://www.ajdesigner.com/phpgravity/gravity_acceleration_equation.php#ajscroll | |
// todo: how to scale -> m/s² conversion to px/s² etc... | |
/* | |
// Constrain reticle to a cirlcle around player | |
function constrainReticle(reticle) | |
{ | |
var distX = reticle.x - player.x; // X distance between player & reticle | |
var distY = reticle.y - player.y; // Y distance between player & reticle | |
var maxDist = 300; | |
var maxDistVec = new Phaser.Math.Vector2(distX, distY).normalize().multiply( | |
new Phaser.Math.Vector2(maxDist, maxDist) | |
); | |
// Ensures reticle cannot be moved offscreen (player follow) | |
text.setText([ | |
"distXY: " + distX + " : " + distY, | |
"maxDistVec: " + maxDistVec.x + " : " + maxDistVec.y | |
]); | |
//reticle.x = player.x + maxDistVec.x; | |
//reticle.y = player.y + maxDistVec.y; | |
if ((maxDistVec.x > 0 && distX > maxDistVec.x) || (maxDistVec.x < 0 && distX < maxDistVec.x)) | |
reticle.x = player.x + maxDistVec.x; | |
if ((maxDistVec.y > 0 && distY > maxDistVec.y) || (maxDistVec.y < 0 && distY < maxDistVec.y)) | |
reticle.y = player.y + maxDistVec.y; | |
} | |
*/ | |
var config = { | |
type: Phaser.AUTO, | |
parent: 'planet-gravity-example', | |
width: 1024, | |
height: 768, | |
physics: { | |
default: 'arcade', | |
arcade: { | |
gravity: { y: 0, x: 0 }, | |
debug: true | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var game = new Phaser.Game(config); | |
function preload() { | |
this.load.atlas('space', 'assets/tests/space/space.png', 'assets/tests/space/space.json'); | |
this.load.image('target', 'assets/demoscene/ball.png'); | |
} | |
var planet; | |
var moon; | |
var ship; | |
var keyBackThrust; | |
var keyFwdThrust; | |
var keyLeft; | |
var keyRight; | |
var keyShipCam; | |
var keyPlanetCam; | |
var keyMoonCam; | |
var reticle; | |
var mainCam; | |
//var rt; | |
//var trail; | |
var G = 0.5;//6.67e-11; | |
var planetMass = 500000000; | |
var moonMass = planetMass/20; | |
var planetRadius = 2500; | |
var moonRadius = 250; | |
var shipRadius = 10; | |
var graphics; | |
//var initialSpeed = 0; | |
//var initialVector; | |
function create() { | |
graphics = this.add.graphics(); | |
planet = this.physics.add.sprite(400, 300, 'space', 'blue-planet').setOrigin(0.5, 0.5).setDisplaySize(planetRadius*2,planetRadius*2); | |
moon = this.physics.add.sprite(400, 15600, 'space', 'moon1').setOrigin(0.5, 0.5).setDisplaySize(moonRadius*2,moonRadius*2); | |
ship = this.physics.add.sprite(400, -2500, 'space', 'ship').setDepth(2).setOrigin(0.5, 0.5).setDisplaySize(20,20); | |
//rt = this.add.renderTexture(-20000, -20000, 40000, 40000); | |
//trail = this.add.image(0, 0, 'space', 'ship').setOrigin(0.5,0.5).setDisplaySize(10,10).setVisible(false); | |
ship.body.allowGravity = true; | |
moon.body.allowGravity = true; | |
var shipBodyPos = new Phaser.Math.Vector2(ship.x, ship.y); | |
var planetBodyPos = new Phaser.Math.Vector2(planet.x, planet.y); | |
var moonBodyPos = new Phaser.Math.Vector2(moon.x, moon.y); | |
// setup ship initial velocity | |
var shipPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
// perpendicular 2d vector to gravitational vector (https://gamedev.stackexchange.com/a/146492) | |
var initialShipVector = new Phaser.Math.Vector2(-(planetBodyPos.y - shipBodyPos.y), planetBodyPos.x - shipBodyPos.x).normalize(); | |
var initialShipSpeed = Math.sqrt(G*planetMass/shipPlanetDistance); | |
ship.body.velocity.x = initialShipVector.x * initialShipSpeed; | |
ship.body.velocity.y = initialShipVector.y * initialShipSpeed; | |
// setup moon initial velocity | |
var moonPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, moonBodyPos.x, moonBodyPos.y); | |
// perpendicular 2d vector to gravitational vector (https://gamedev.stackexchange.com/a/146492) | |
var initialMoonVector = new Phaser.Math.Vector2(-(planetBodyPos.y - moonBodyPos.y), planetBodyPos.x - moonBodyPos.x).normalize(); | |
var initialMoonSpeed = Math.sqrt(G*planetMass/moonPlanetDistance); | |
moon.body.velocity.x = initialMoonVector.x * initialMoonSpeed; | |
moon.body.velocity.y = initialMoonVector.y * initialMoonSpeed; | |
text = this.add.text(32, 32).setScrollFactor(0).setFontSize(16).setColor('#ffffff'); | |
// ship cam | |
mainCam = this.cameras.main; | |
mainCam.startFollow(ship); | |
keyBackThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); | |
keyFwdThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W); | |
keyLeft = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A); | |
keyRight = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); | |
keyPlanetCam = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.P); | |
keyPlanetCam.on('down', function (key, event) { | |
// planet cam | |
mainCam.startFollow(planet); | |
mainCam.zoom = 0.13; | |
}); | |
keyMoonCam = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.O); | |
keyMoonCam.on('down', function (key, event) { | |
// moon cam | |
mainCam.startFollow(moon); | |
mainCam.zoom = 0.5; | |
}); | |
keyShipCam = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.I); | |
keyShipCam.on('down', function (key, event) { | |
// ship cam | |
mainCam.startFollow(ship); | |
mainCam.zoom = 1; | |
}); | |
reticle = this.physics.add.sprite(ship.x, ship.y + 50, 'target'); | |
reticle.setOrigin(0.5, 0.5).setDisplaySize(5, 5); | |
// Pointer lock will only work after mousedown | |
game.canvas.addEventListener('mousedown', function () { | |
game.input.mouse.requestPointerLock(); | |
}); | |
this.input.on('pointermove', function (pointer) { | |
if (this.input.mouse.locked) | |
{ | |
reticle.x += pointer.movementX; | |
reticle.y += pointer.movementY; | |
} | |
}, this); | |
} | |
function update() { | |
var shipBodyPos = new Phaser.Math.Vector2(ship.body.x + shipRadius, ship.body.y + shipRadius); | |
ship.rotation = Phaser.Math.Angle.Between(ship.x, ship.y, reticle.x, reticle.y); | |
//restrainReticle() | |
reticle.body.velocity.x = ship.body.velocity.x; | |
reticle.body.velocity.y = ship.body.velocity.y; | |
/*var reticleBodyPos = new Phaser.Math.Vector2(reticle.body.x + reticle.body.width/2, reticle.body.y + reticle.body.height/2); | |
shipReticleNormalized = new Phaser.Math.Vector2(reticleBodyPos.x - shipBodyPos.x, reticleBodyPos.y - shipBodyPos.y).normalize(); | |
if (shipBodyPos.x + shipReticleNormalized.x * 100 > reticleBodyPos.x) { | |
reticle.body.x = shipBodyPos.x + shipReticleNormalized.x * 100; | |
} else if (shipBodyPos.x + shipReticleNormalized.x * 100 < reticleBodyPos.x) { | |
reticle.body.x = shipBodyPos.x + shipReticleNormalized.x * 100; | |
} | |
if (shipBodyPos.y + shipReticleNormalized.y * 100 > reticleBodyPos.y) { | |
reticle.body.y = shipBodyPos.y + shipReticleNormalized.y * 100; | |
} else if (shipBodyPos.y + shipReticleNormalized.y * 100 < reticleBodyPos.y) { | |
reticle.body.y = shipBodyPos.y + shipReticleNormalized.y * 100; | |
}*/ | |
var noCursorDown = true; | |
var downVec = Phaser.Math.Vector2.ZERO; | |
var upVec = Phaser.Math.Vector2.ZERO; | |
var leftVec = Phaser.Math.Vector2.ZERO; | |
var rightVec = Phaser.Math.Vector2.ZERO; | |
if (keyLeft.isDown) { | |
noCursorDown = false; | |
leftVec = this.physics.velocityFromAngle(ship.angle - 90, 10); | |
} | |
if (keyRight.isDown) { | |
noCursorDown = false; | |
rightVec = this.physics.velocityFromAngle(ship.angle + 90, 10); | |
} | |
if (keyBackThrust.isDown) { | |
noCursorDown = false; | |
downVec = this.physics.velocityFromAngle(ship.angle - 180, 10); | |
} | |
if (keyFwdThrust.isDown) { | |
noCursorDown = false; | |
upVec = this.physics.velocityFromAngle(ship.angle, 200); | |
} | |
var addVec = new Phaser.Math.Vector2() | |
.add(downVec) | |
.add(upVec) | |
.add(leftVec) | |
.add(rightVec); | |
if (noCursorDown) { | |
ship.setAcceleration(0); | |
} else { | |
ship.body.acceleration = addVec; | |
} | |
var planetBodyPos = new Phaser.Math.Vector2(planet.body.x + planetRadius, planet.body.y + planetRadius); | |
var moonBodyPos = new Phaser.Math.Vector2(moon.body.x + moonRadius, moon.body.y + moonRadius); | |
var shipAcc = new Phaser.Math.Vector2(); | |
var shipPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
var shipPlanetDistanceSquared = Math.pow(shipPlanetDistance, 2); | |
shipPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/shipPlanetDistanceSquared, (G*planetMass)/shipPlanetDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
shipPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - shipBodyPos.x, planetBodyPos.y - shipBodyPos.y).normalize(); | |
shipAcc.add(shipPlanetNormalized.clone().multiply(shipPlanetGravity)); | |
// add atmospheric drag, but not with this drag since it decelerates just to 0, instead of just slowing down things | |
var shipMoonDistance = Phaser.Math.Distance.Between(moonBodyPos.x, moonBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
var shipMoonDistanceSquared = Math.pow(shipMoonDistance, 2); | |
shipMoonGravity = new Phaser.Math.Vector2((G*moonMass)/shipMoonDistanceSquared, (G*moonMass)/shipMoonDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
shipMoonNormalized = new Phaser.Math.Vector2(moonBodyPos.x - shipBodyPos.x, moonBodyPos.y - shipBodyPos.y).normalize(); | |
shipAcc.add(shipMoonNormalized.clone().multiply(shipMoonGravity)); | |
ship.body.gravity = shipAcc; | |
var moonPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, moonBodyPos.x, moonBodyPos.y); | |
var moonPlanetDistanceSquared = Math.pow(moonPlanetDistance, 2); | |
moonPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/moonPlanetDistanceSquared, (G*planetMass)/moonPlanetDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
moonPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - moonBodyPos.x, planetBodyPos.y - moonBodyPos.y).normalize(); | |
moonAcc = moonPlanetNormalized.clone().multiply(moonPlanetGravity); | |
moon.body.gravity = moonAcc; | |
graphics.clear(); | |
graphics.lineStyle(2, 0x0000ff, 1); | |
graphics.lineBetween(shipBodyPos.x, shipBodyPos.y, shipBodyPos.x + shipPlanetNormalized.x * 50, shipBodyPos.y + shipPlanetNormalized.y * 50); | |
graphics.lineStyle(2, 0xff0000, 1); | |
graphics.lineBetween(shipBodyPos.x, shipBodyPos.y, shipBodyPos.x + shipMoonNormalized.x * 50, shipBodyPos.y + shipMoonNormalized.y * 50); | |
var shipTrajectory = estimateTrajectory(shipBodyPos.clone(), ship.body.velocity.clone(), planetBodyPos.clone(), moonBodyPos.clone(), moon.body.velocity.clone()); | |
var currentPos = shipBodyPos; | |
for (var i = 0; i < shipTrajectory.length; i++) { | |
var nextPos = shipTrajectory[i]; | |
graphics.lineStyle(2, 0xffff00, 1); | |
graphics.lineBetween(currentPos.x, currentPos.y, nextPos.x, nextPos.y); | |
currentPos = nextPos; | |
} | |
text.setText([ | |
"G: " + G, | |
//"traj: " + shipTrajectory[1].x + ":" + shipTrajectory[1].y + "(" + shipTrajectory.length + ")", | |
//"ship: " + shipBodyPos.x + ":" + shipBodyPos.y, | |
//"pos: " + planet.body.offset.x + " -- " + planet.y, | |
"shipAcc: " + shipAcc.x + " : " + shipAcc.y, | |
"acc: " + ship.body.acceleration.x + " : " + ship.body.acceleration.y, | |
"vel: " + ship.body.speed + "(" + ship.body.velocity.x + ":" + ship.body.velocity.y + ")", | |
//"initVel: " + initialSpeed, | |
//"initVec: " + initialVector.x + ":" + initialVector.y, | |
"shipPlanetDistance: " + shipPlanetDistance, | |
"moonPlanetDistance: " + moonPlanetDistance | |
//"planetMass: " + Math.sqrt(shipAcc.x * shipAcc.x + shipAcc.y * shipAcc.y)*distanceSquared/G, | |
]); | |
} | |
function estimateTrajectory(shipBodyPos, shipVelocity, planetBodyPos, moonBodyPos2, moonVelocity) { | |
/*currentPos = startingPosition | |
currentVel = startingVelcoity | |
resultTrajectory.append(currentPos) | |
for N times{ | |
currentForce = gatherForces() | |
currentAccel = currentForce / mass | |
deltaT = fixedTimeStep | |
nextPos = currentPos + currentVel * deltaT + currentAccel * deltaT * deltaT * 0.5 | |
nextVel = currentVel + currentAccel * deltaT | |
resultTrajectory.append(nextPos) | |
currentPos = nextPos | |
currentVel = nextVel | |
}*/ | |
var steps = 10; | |
var deltaT = 0.2; | |
var shipTrajectory = [shipBodyPos.clone()]; | |
var currentBodyShipPos = shipBodyPos.clone(); | |
var currentShipVel = shipVelocity.clone(); | |
var moonBodyPos = moonBodyPos2.clone(); | |
var currentMoonVel = moonVelocity.clone(); | |
for (var i = 0; i < steps; i++) { | |
// gather forces accs | |
var currentShipAcc = new Phaser.Math.Vector2(); | |
var shipPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, currentBodyShipPos.x, currentBodyShipPos.y); | |
var shipPlanetDistanceSquared = Math.pow(shipPlanetDistance, 2); | |
var shipPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/shipPlanetDistanceSquared, (G*planetMass)/shipPlanetDistanceSquared); | |
var shipPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - currentBodyShipPos.x, planetBodyPos.y - currentBodyShipPos.y).normalize(); | |
currentShipAcc.add(shipPlanetNormalized.clone().multiply(shipPlanetGravity)); | |
var shipMoonDistance = Phaser.Math.Distance.Between(moonBodyPos.x, moonBodyPos.y, currentBodyShipPos.x, currentBodyShipPos.y); | |
var shipMoonDistanceSquared = Math.pow(shipMoonDistance, 2); | |
var shipMoonGravity = new Phaser.Math.Vector2((G*moonMass)/shipMoonDistanceSquared, (G*moonMass)/shipMoonDistanceSquared); | |
var shipMoonNormalized = new Phaser.Math.Vector2(moonBodyPos.x - currentBodyShipPos.x, moonBodyPos.y - currentBodyShipPos.y).normalize(); | |
currentShipAcc.add(shipMoonNormalized.clone().multiply(shipMoonGravity)); | |
var moonPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, moonBodyPos.x, moonBodyPos.y); | |
var moonPlanetDistanceSquared = Math.pow(moonPlanetDistance, 2); | |
moonPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/moonPlanetDistanceSquared, (G*planetMass)/moonPlanetDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
moonPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - moonBodyPos.x, planetBodyPos.y - moonBodyPos.y).normalize(); | |
var currentMoonAcc = moonPlanetNormalized.clone().multiply(moonPlanetGravity); | |
var nextMoonBodyPos = new Phaser.Math.Vector2( | |
moonBodyPos.x + currentMoonVel.x * deltaT + currentMoonAcc.x * deltaT * deltaT * 0.5, | |
moonBodyPos.y + currentMoonVel.y * deltaT + currentMoonAcc.y * deltaT * deltaT * 0.5, | |
); | |
var nextMoonVel = new Phaser.Math.Vector2( | |
currentMoonVel.x + currentMoonAcc.x * deltaT, | |
currentMoonVel.y + currentMoonAcc.y * deltaT | |
); | |
var nextBodyShipPos = new Phaser.Math.Vector2( | |
currentBodyShipPos.x + currentShipVel.x * deltaT + currentShipAcc.x * deltaT * deltaT * 0.5, | |
currentBodyShipPos.y + currentShipVel.y * deltaT + currentShipAcc.y * deltaT * deltaT * 0.5 | |
); | |
var nextShipVel = new Phaser.Math.Vector2( | |
currentShipVel.x + currentShipAcc.x * deltaT, | |
currentShipVel.y + currentShipAcc.y * deltaT | |
) | |
shipTrajectory.push(nextBodyShipPos.clone()); | |
currentBodyShipPos = nextBodyShipPos.clone(); | |
currentShipVel = nextShipVel.clone(); | |
moonBodyPos = nextMoonBodyPos.clone(); | |
currentMoonVel = nextMoonVel.clone(); | |
} | |
return shipTrajectory; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on this example: | |
// * http://jsfiddle.net/gJ4kA/ | |
// further reads: | |
// * https://gamedev.stackexchange.com/questions/71233/planet-gravity | |
// * https://gamedev.stackexchange.com/questions/21063/2d-planet-gravity | |
// * http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ | |
// calc: https://www.ajdesigner.com/phpgravity/gravity_acceleration_equation.php#ajscroll | |
// todo: how to scale -> m/s² conversion to px/s² etc... | |
var config = { | |
type: Phaser.AUTO, | |
parent: 'planet-gravity-example', | |
width: 1024, | |
height: 768, | |
physics: { | |
default: 'arcade', | |
arcade: { | |
gravity: { y: 0, x: 0 }, | |
debug: true | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var game = new Phaser.Game(config); | |
function preload() { | |
this.load.atlas('space', 'assets/tests/space/space.png', 'assets/tests/space/space.json'); | |
this.load.image('target', 'assets/demoscene/ball.png'); | |
} | |
var planet; | |
var moon; | |
var ship; | |
var keyBackThrust; | |
var keyFwdThrust; | |
var keyLeft; | |
var keyRight; | |
var reticle; | |
//var rt; | |
//var trail; | |
var G = 0.5;//6.67e-11; | |
var planetMass = 500000000; | |
var moonMass = planetMass/20; | |
var planetRadius = 2500; | |
var moonRadius = 250; | |
var shipRadius = 10; | |
var graphics; | |
//var initialSpeed = 0; | |
//var initialVector; | |
function create() { | |
graphics = this.add.graphics(); | |
planet = this.physics.add.sprite(400, 300, 'space', 'blue-planet').setOrigin(0.5, 0.5).setDisplaySize(planetRadius*2,planetRadius*2); | |
moon = this.physics.add.sprite(400, 15600, 'space', 'moon1').setOrigin(0.5, 0.5).setDisplaySize(moonRadius*2,moonRadius*2); | |
ship = this.physics.add.sprite(400, -2500, 'space', 'ship').setDepth(2).setOrigin(0.5, 0.5).setDisplaySize(20,20); | |
//rt = this.add.renderTexture(-20000, -20000, 40000, 40000); | |
//trail = this.add.image(0, 0, 'space', 'ship').setOrigin(0.5,0.5).setDisplaySize(10,10).setVisible(false); | |
ship.body.allowGravity = true; | |
moon.body.allowGravity = true; | |
var shipBodyPos = new Phaser.Math.Vector2(ship.x, ship.y); | |
var planetBodyPos = new Phaser.Math.Vector2(planet.x, planet.y); | |
var moonBodyPos = new Phaser.Math.Vector2(moon.x, moon.y); | |
// setup ship initial velocity | |
var shipPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
// perpendicular 2d vector to gravitational vector (https://gamedev.stackexchange.com/a/146492) | |
var initialShipVector = new Phaser.Math.Vector2(-(planetBodyPos.y - shipBodyPos.y), planetBodyPos.x - shipBodyPos.x).normalize(); | |
var initialShipSpeed = Math.sqrt(G*planetMass/shipPlanetDistance); | |
ship.body.velocity.x = initialShipVector.x * initialShipSpeed; | |
ship.body.velocity.y = initialShipVector.y * initialShipSpeed; | |
// setup moon initial velocity | |
var moonPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, moonBodyPos.x, moonBodyPos.y); | |
// perpendicular 2d vector to gravitational vector (https://gamedev.stackexchange.com/a/146492) | |
var initialMoonVector = new Phaser.Math.Vector2(-(planetBodyPos.y - moonBodyPos.y), planetBodyPos.x - moonBodyPos.x).normalize(); | |
var initialMoonSpeed = Math.sqrt(G*planetMass/moonPlanetDistance); | |
moon.body.velocity.x = initialMoonVector.x * initialMoonSpeed; | |
moon.body.velocity.y = initialMoonVector.y * initialMoonSpeed; | |
text = this.add.text(32, 32).setScrollFactor(0).setFontSize(16).setColor('#ffffff'); | |
this.cameras.main.startFollow(ship); | |
this.cameras.main.zoom = 0.75; | |
keyBackThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); | |
keyFwdThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W); | |
keyLeft = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A); | |
keyRight = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); | |
reticle = this.physics.add.sprite(ship.x, ship.y + 50, 'target'); | |
reticle.setOrigin(0.5, 0.5).setDisplaySize(5, 5); | |
// Pointer lock will only work after mousedown | |
game.canvas.addEventListener('mousedown', function () { | |
game.input.mouse.requestPointerLock(); | |
}); | |
this.input.on('pointermove', function (pointer) { | |
if (this.input.mouse.locked) | |
{ | |
reticle.x += pointer.movementX; | |
reticle.y += pointer.movementY; | |
} | |
}, this); | |
} | |
function update() { | |
var shipBodyPos = new Phaser.Math.Vector2(ship.body.x + shipRadius, ship.body.y + shipRadius); | |
ship.rotation = Phaser.Math.Angle.Between(ship.x, ship.y, reticle.x, reticle.y); | |
//restrainReticle() | |
reticle.body.velocity.x = ship.body.velocity.x; | |
reticle.body.velocity.y = ship.body.velocity.y; | |
/*var reticleBodyPos = new Phaser.Math.Vector2(reticle.body.x + reticle.body.width/2, reticle.body.y + reticle.body.height/2); | |
shipReticleNormalized = new Phaser.Math.Vector2(reticleBodyPos.x - shipBodyPos.x, reticleBodyPos.y - shipBodyPos.y).normalize(); | |
if (shipBodyPos.x + shipReticleNormalized.x * 100 > reticleBodyPos.x) { | |
reticle.body.x = shipBodyPos.x + shipReticleNormalized.x * 100; | |
} else if (shipBodyPos.x + shipReticleNormalized.x * 100 < reticleBodyPos.x) { | |
reticle.body.x = shipBodyPos.x + shipReticleNormalized.x * 100; | |
} | |
if (shipBodyPos.y + shipReticleNormalized.y * 100 > reticleBodyPos.y) { | |
reticle.body.y = shipBodyPos.y + shipReticleNormalized.y * 100; | |
} else if (shipBodyPos.y + shipReticleNormalized.y * 100 < reticleBodyPos.y) { | |
reticle.body.y = shipBodyPos.y + shipReticleNormalized.y * 100; | |
}*/ | |
var noCursorDown = true; | |
var downVec = Phaser.Math.Vector2.ZERO; | |
var upVec = Phaser.Math.Vector2.ZERO; | |
var leftVec = Phaser.Math.Vector2.ZERO; | |
var rightVec = Phaser.Math.Vector2.ZERO; | |
if (keyLeft.isDown) { | |
noCursorDown = false; | |
leftVec = this.physics.velocityFromAngle(ship.angle - 90, 10); | |
} | |
if (keyRight.isDown) { | |
noCursorDown = false; | |
rightVec = this.physics.velocityFromAngle(ship.angle + 90, 10); | |
} | |
if (keyBackThrust.isDown) { | |
noCursorDown = false; | |
downVec = this.physics.velocityFromAngle(ship.angle - 180, 10); | |
} | |
if (keyFwdThrust.isDown) { | |
noCursorDown = false; | |
upVec = this.physics.velocityFromAngle(ship.angle, 200); | |
} | |
var addVec = new Phaser.Math.Vector2() | |
.add(downVec) | |
.add(upVec) | |
.add(leftVec) | |
.add(rightVec); | |
if (noCursorDown) { | |
ship.setAcceleration(0); | |
} else { | |
ship.body.acceleration = addVec; | |
} | |
var planetBodyPos = new Phaser.Math.Vector2(planet.body.x + planetRadius, planet.body.y + planetRadius); | |
var moonBodyPos = new Phaser.Math.Vector2(moon.body.x + moonRadius, moon.body.y + moonRadius); | |
var shipAcc = new Phaser.Math.Vector2(); | |
var shipPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
var shipPlanetDistanceSquared = Math.pow(shipPlanetDistance, 2); | |
shipPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/shipPlanetDistanceSquared, (G*planetMass)/shipPlanetDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
shipPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - shipBodyPos.x, planetBodyPos.y - shipBodyPos.y).normalize(); | |
shipAcc.add(shipPlanetNormalized.clone().multiply(shipPlanetGravity)); | |
// add atmospheric drag, but not with this drag since it decelerates just to 0, instead of just slowing down things | |
var shipMoonDistance = Phaser.Math.Distance.Between(moonBodyPos.x, moonBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
var shipMoonDistanceSquared = Math.pow(shipMoonDistance, 2); | |
shipMoonGravity = new Phaser.Math.Vector2((G*moonMass)/shipMoonDistanceSquared, (G*moonMass)/shipMoonDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
shipMoonNormalized = new Phaser.Math.Vector2(moonBodyPos.x - shipBodyPos.x, moonBodyPos.y - shipBodyPos.y).normalize(); | |
shipAcc.add(shipMoonNormalized.clone().multiply(shipMoonGravity)); | |
ship.body.gravity = shipAcc; | |
var moonPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, moonBodyPos.x, moonBodyPos.y); | |
var moonPlanetDistanceSquared = Math.pow(moonPlanetDistance, 2); | |
moonPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/moonPlanetDistanceSquared, (G*planetMass)/moonPlanetDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
moonPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - moonBodyPos.x, planetBodyPos.y - moonBodyPos.y).normalize(); | |
moonAcc = moonPlanetNormalized.clone().multiply(moonPlanetGravity); | |
moon.body.gravity = moonAcc; | |
graphics.clear(); | |
graphics.lineStyle(2, 0x0000ff, 1); | |
graphics.lineBetween(shipBodyPos.x, shipBodyPos.y, shipBodyPos.x + shipPlanetNormalized.x * 50, shipBodyPos.y + shipPlanetNormalized.y * 50); | |
graphics.lineStyle(2, 0xff0000, 1); | |
graphics.lineBetween(shipBodyPos.x, shipBodyPos.y, shipBodyPos.x + shipMoonNormalized.x * 50, shipBodyPos.y + shipMoonNormalized.y * 50); | |
var shipTrajectory = estimateTrajectory(shipBodyPos.clone(), ship.body.velocity.clone(), planetBodyPos.clone(), moonBodyPos.clone(), moon.body.velocity.clone()); | |
var currentPos = shipBodyPos; | |
for (var i = 0; i < shipTrajectory.length; i++) { | |
var nextPos = shipTrajectory[i]; | |
graphics.lineStyle(2, 0xffff00, 1); | |
graphics.lineBetween(currentPos.x, currentPos.y, nextPos.x, nextPos.y); | |
currentPos = nextPos; | |
} | |
text.setText([ | |
"G: " + G, | |
//"traj: " + shipTrajectory[1].x + ":" + shipTrajectory[1].y + "(" + shipTrajectory.length + ")", | |
//"ship: " + shipBodyPos.x + ":" + shipBodyPos.y, | |
//"pos: " + planet.body.offset.x + " -- " + planet.y, | |
"shipAcc: " + shipAcc.x + " : " + shipAcc.y, | |
"acc: " + ship.body.acceleration.x + " : " + ship.body.acceleration.y, | |
"vel: " + ship.body.speed + "(" + ship.body.velocity.x + ":" + ship.body.velocity.y + ")", | |
//"initVel: " + initialSpeed, | |
//"initVec: " + initialVector.x + ":" + initialVector.y, | |
"shipPlanetDistance: " + shipPlanetDistance, | |
"moonPlanetDistance: " + moonPlanetDistance | |
//"planetMass: " + Math.sqrt(shipAcc.x * shipAcc.x + shipAcc.y * shipAcc.y)*distanceSquared/G, | |
]); | |
} | |
function estimateTrajectory(shipBodyPos, shipVelocity, planetBodyPos, moonBodyPos2, moonVelocity) { | |
/*currentPos = startingPosition | |
currentVel = startingVelcoity | |
resultTrajectory.append(currentPos) | |
for N times{ | |
currentForce = gatherForces() | |
currentAccel = currentForce / mass | |
deltaT = fixedTimeStep | |
nextPos = currentPos + currentVel * deltaT + currentAccel * deltaT * deltaT * 0.5 | |
nextVel = currentVel + currentAccel * deltaT | |
resultTrajectory.append(nextPos) | |
currentPos = nextPos | |
currentVel = nextVel | |
}*/ | |
var steps = 50; | |
var deltaT = 0.1; | |
var shipTrajectory = [shipBodyPos.clone()]; | |
var currentBodyShipPos = shipBodyPos.clone(); | |
var currentShipVel = shipVelocity.clone(); | |
var moonBodyPos = moonBodyPos2.clone(); | |
var currentMoonVel = moonVelocity.clone(); | |
for (var i = 0; i < steps; i++) { | |
// gather forces accs | |
var currentShipAcc = new Phaser.Math.Vector2(); | |
var shipPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, currentBodyShipPos.x, currentBodyShipPos.y); | |
var shipPlanetDistanceSquared = Math.pow(shipPlanetDistance, 2); | |
var shipPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/shipPlanetDistanceSquared, (G*planetMass)/shipPlanetDistanceSquared); | |
var shipPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - currentBodyShipPos.x, planetBodyPos.y - currentBodyShipPos.y).normalize(); | |
currentShipAcc.add(shipPlanetNormalized.clone().multiply(shipPlanetGravity)); | |
var shipMoonDistance = Phaser.Math.Distance.Between(moonBodyPos.x, moonBodyPos.y, currentBodyShipPos.x, currentBodyShipPos.y); | |
var shipMoonDistanceSquared = Math.pow(shipMoonDistance, 2); | |
var shipMoonGravity = new Phaser.Math.Vector2((G*moonMass)/shipMoonDistanceSquared, (G*moonMass)/shipMoonDistanceSquared); | |
var shipMoonNormalized = new Phaser.Math.Vector2(moonBodyPos.x - currentBodyShipPos.x, moonBodyPos.y - currentBodyShipPos.y).normalize(); | |
currentShipAcc.add(shipMoonNormalized.clone().multiply(shipMoonGravity)); | |
var moonPlanetDistance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, moonBodyPos.x, moonBodyPos.y); | |
var moonPlanetDistanceSquared = Math.pow(moonPlanetDistance, 2); | |
moonPlanetGravity = new Phaser.Math.Vector2((G*planetMass)/moonPlanetDistanceSquared, (G*planetMass)/moonPlanetDistanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
moonPlanetNormalized = new Phaser.Math.Vector2(planetBodyPos.x - moonBodyPos.x, planetBodyPos.y - moonBodyPos.y).normalize(); | |
var currentMoonAcc = moonPlanetNormalized.clone().multiply(moonPlanetGravity); | |
var nextMoonBodyPos = new Phaser.Math.Vector2( | |
moonBodyPos.x + currentMoonVel.x * deltaT + currentMoonAcc.x * deltaT * deltaT * 0.5, | |
moonBodyPos.y + currentMoonVel.y * deltaT + currentMoonAcc.y * deltaT * deltaT * 0.5, | |
); | |
var nextMoonVel = new Phaser.Math.Vector2( | |
currentMoonVel.x + currentMoonAcc.x * deltaT, | |
currentMoonVel.y + currentMoonAcc.y * deltaT | |
); | |
var nextBodyShipPos = new Phaser.Math.Vector2( | |
currentBodyShipPos.x + currentShipVel.x * deltaT + currentShipAcc.x * deltaT * deltaT * 0.5, | |
currentBodyShipPos.y + currentShipVel.y * deltaT + currentShipAcc.y * deltaT * deltaT * 0.5 | |
); | |
var nextShipVel = new Phaser.Math.Vector2( | |
currentShipVel.x + currentShipAcc.x * deltaT, | |
currentShipVel.y + currentShipAcc.y * deltaT | |
) | |
shipTrajectory.push(nextBodyShipPos.clone()); | |
currentBodyShipPos = nextBodyShipPos.clone(); | |
currentShipVel = nextShipVel.clone(); | |
moonBodyPos = nextMoonBodyPos.clone(); | |
currentMoonVel = nextMoonVel.clone(); | |
} | |
return shipTrajectory; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var config = { | |
type: Phaser.AUTO, | |
width: 800, | |
height: 600, | |
backgroundColor: '#1b1464', | |
parent: 'phaser-example', | |
physics: { | |
default: 'matter', | |
matter: { | |
debug: true, | |
gravity: { | |
x: 0, | |
y: 0.03 | |
} | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var ship; | |
var target; | |
var cursors; | |
var game = new Phaser.Game(config); | |
function preload () | |
{ | |
this.load.image('ship', 'assets/sprites/x2kship.png'); | |
this.load.image('target', 'assets/demoscene/ball.png'); | |
} | |
function create () | |
{ | |
ship = this.matter.add.image(400, 300, 'ship').setDisplaySize(70, 30); | |
ship.setRotation(Math.PI*1.5); | |
let shipBottomCenter = ship.getTopRight(); | |
//target = this.matter.add.image(shipBottomCenter.x, shipBottomCenter.y, 'target').setDisplaySize(10,10); | |
ship.setFrictionAir(0.001); | |
ship.setMass(70); | |
//ship.setFixedRotation(); | |
this.matter.world.setBounds(0, 0, 800, 600); | |
//this.cameras.main.startFollow(ship); | |
cursors = this.input.keyboard.createCursorKeys(); | |
} | |
function update () | |
{ | |
let rotation = ship.body.angle; | |
let turnLeftRot = rotation - Math.PI / 2; | |
let turnRightRot = rotation + Math.PI / 2; | |
let turnVal = 0.002; | |
let turnLeftForce = new Phaser.Math.Vector2(turnVal * Math.cos(turnLeftRot), turnVal * Math.sin(turnLeftRot)); | |
let turnRightForce = new Phaser.Math.Vector2(turnVal * Math.cos(turnRightRot), turnVal * Math.sin(turnRightRot)); | |
if (cursors.left.isDown) { | |
let bottomRight = ship.getBottomRight(); | |
ship.applyForceFrom(bottomRight, turnLeftForce); | |
let topLeft = ship.getTopLeft(); | |
ship.applyForceFrom(topLeft, turnRightForce); | |
} | |
if (cursors.right.isDown) { | |
let topRight = ship.getTopRight(); | |
ship.applyForceFrom(topRight, turnRightForce); | |
let bottomLeft = ship.getBottomLeft(); | |
ship.applyForceFrom(bottomLeft, turnLeftForce); | |
} | |
if (cursors.up.isDown) { | |
let thrustVal = 0.005; | |
let thrustForce = new Phaser.Math.Vector2(thrustVal * Math.cos(rotation), thrustVal * Math.sin(rotation)); | |
//ship.thrust(0.08); | |
let rear = ship.getLeftCenter(); | |
//let top = ship.getTopCenter(); | |
//ship.applyForceFrom(ship.body.position, thrustForce); | |
ship.applyForceFrom(rear, thrustForce); | |
//ship.applyForceFrom(top, thrustForce); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var config = { | |
type: Phaser.AUTO, | |
width: 800, | |
height: 600, | |
backgroundColor: '#1b1464', | |
parent: 'phaser-example', | |
physics: { | |
default: 'matter', | |
matter: { | |
debug: true, | |
gravity: { | |
x: 0, | |
y: 0 | |
} | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var ship; | |
var target; | |
var cursors; | |
var game = new Phaser.Game(config); | |
function preload () | |
{ | |
this.load.image('ship', 'assets/sprites/x2kship.png'); | |
this.load.image('target', 'assets/demoscene/ball.png'); | |
} | |
function create () | |
{ | |
ship = this.matter.add.image(400, 300, 'ship').setDisplaySize(30,30); | |
let shipBottomCenter = ship.getTopRight(); | |
//target = this.matter.add.image(shipBottomCenter.x, shipBottomCenter.y, 'target').setDisplaySize(10,10); | |
ship.setFrictionAir(0); | |
ship.setMass(70); | |
//ship.setFixedRotation(); | |
this.matter.world.setBounds(0, 0, 800, 600); | |
//this.cameras.main.startFollow(ship); | |
cursors = this.input.keyboard.createCursorKeys(); | |
} | |
function update () | |
{ | |
let rotation = ship.body.angle; | |
let turnLeftRot = rotation - Math.PI / 2; | |
let turnRightRot = rotation + Math.PI / 2; | |
let turnVal = 0.002; | |
let turnLeftForce = new Phaser.Math.Vector2(turnVal * Math.cos(turnLeftRot), turnVal * Math.sin(turnLeftRot)); | |
let turnRightForce = new Phaser.Math.Vector2(turnVal * Math.cos(turnRightRot), turnVal * Math.sin(turnRightRot)); | |
if (cursors.left.isDown) { | |
let bottomRight = ship.getBottomRight(); | |
ship.applyForceFrom(bottomRight, turnLeftForce); | |
let topLeft = ship.getTopLeft(); | |
ship.applyForceFrom(topLeft, turnRightForce); | |
} | |
if (cursors.right.isDown) { | |
let topRight = ship.getTopRight(); | |
ship.applyForceFrom(topRight, turnRightForce); | |
let bottomLeft = ship.getBottomLeft(); | |
ship.applyForceFrom(bottomLeft, turnLeftForce); | |
} | |
if (cursors.up.isDown) { | |
let thrustVal = 0.005; | |
let thrustForce = new Phaser.Math.Vector2(thrustVal * Math.cos(rotation), thrustVal * Math.sin(rotation)); | |
//ship.thrust(0.08); | |
let rear = ship.getLeftCenter(); | |
//let top = ship.getTopCenter(); | |
//ship.applyForceFrom(ship.body.position, thrustForce); | |
ship.applyForceFrom(rear, thrustForce); | |
//ship.applyForceFrom(top, thrustForce); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on this example: | |
// * http://jsfiddle.net/gJ4kA/ | |
// further reads: | |
// * https://gamedev.stackexchange.com/questions/71233/planet-gravity | |
// * https://gamedev.stackexchange.com/questions/21063/2d-planet-gravity | |
// * http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ | |
// calc: https://www.ajdesigner.com/phpgravity/gravity_acceleration_equation.php#ajscroll | |
// todo: how to scale -> m/s² conversion to px/s² etc... | |
var config = { | |
type: Phaser.AUTO, | |
parent: 'planet-gravity-example', | |
width: 800, | |
height: 600, | |
physics: { | |
default: 'arcade', | |
arcade: { | |
gravity: { y: 0, x: 0 }, | |
debug: true | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var game = new Phaser.Game(config); | |
function preload() { | |
this.load.atlas('space', 'assets/tests/space/space.png', 'assets/tests/space/space.json'); | |
} | |
var planet; | |
var ship; | |
function create() { | |
ship = this.physics.add.sprite(400, 100, 'space', 'ship').setDepth(2).setOrigin(0.5, 0.5).setDisplaySize(20,20); | |
planet = this.physics.add.sprite(400, 300, 'space', 'blue-planet').setOrigin(0.5, 0.5).setDisplaySize(200,200); | |
// Use our own gravity | |
ship.body.allowGravity = true; | |
//planet.body.allowGravity = true; | |
// Set an initial motion | |
ship.body.velocity.x = 80; | |
text = this.add.text(32, 32).setScrollFactor(0).setFontSize(16).setColor('#ffffff'); | |
//text.setText("test"); | |
this.cameras.main.startFollow(ship) | |
} | |
function update() { | |
planetMass = 1500000; | |
invPlanetMass = Math.pow(planetMass, -1); | |
distance = Phaser.Math.Distance.Between(planet.x, planet.y, ship.x, ship.y); | |
invDistanceSquared = Math.pow(distance, -2); | |
// calculate with inverse numbers to prevent division through zero | |
planetGravity = new Phaser.Math.Vector2(invDistanceSquared/invPlanetMass, invDistanceSquared/invPlanetMass); | |
//distanceSquared = Math.pow(distance, 2); | |
//planetGravity2 = new Phaser.Math.Vector2(planetMass/distanceSquared, planetMass/distanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
shipGravity = new Phaser.Math.Vector2(planet.x - ship.x, planet.y - ship.y).normalize().multiply(planetGravity); | |
ship.body.gravity = shipGravity; | |
// add atmospheric drag, but not with this drag since it decelerates just to 0, instead of just slowing down things | |
/*if (distance < 100) { | |
ship.body.drag.x = 500; | |
ship.body.drag.y = 500; | |
}*/ | |
text.setText( | |
"shipGravity: " + shipGravity.x + " : " + shipGravity.y | |
//+ "\npG (inv): " + planetGravity.x + " : " + planetGravity.y | |
//+ "\npG (nor): " + planetGravity2.x + " : " + planetGravity2.y | |
+ "\nacc: " + ship.body.acceleration.x + " : " + ship.body.acceleration.y | |
+ "\nvel: " + ship.body.speed | |
+ "\ndistance: " + distance); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on this example: | |
// * http://jsfiddle.net/gJ4kA/ | |
// further reads: | |
// * https://gamedev.stackexchange.com/questions/71233/planet-gravity | |
// * https://gamedev.stackexchange.com/questions/21063/2d-planet-gravity | |
// * http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ | |
// calc: https://www.ajdesigner.com/phpgravity/gravity_acceleration_equation.php#ajscroll | |
// todo: how to scale -> m/s² conversion to px/s² etc... | |
var config = { | |
type: Phaser.AUTO, | |
parent: 'planet-gravity-example', | |
width: 800, | |
height: 600, | |
physics: { | |
default: 'arcade', | |
arcade: { | |
gravity: { y: 0, x: 0 }, | |
debug: true | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var game = new Phaser.Game(config); | |
function preload() { | |
this.load.atlas('space', 'assets/tests/space/space.png', 'assets/tests/space/space.json'); | |
} | |
var planet; | |
var ship; | |
var keyBackThrust; | |
var keyFwdThrust; | |
var keyLeft; | |
var keyRight; | |
var reticle; | |
var rt; | |
var trail; | |
function create() { | |
ship = this.physics.add.sprite(400, -300, 'space', 'ship').setDepth(2).setOrigin(0.5, 0.5).setDisplaySize(20,20); | |
planet = this.physics.add.sprite(400, 300, 'space', 'blue-planet').setOrigin(0.5, 0.5).setDisplaySize(1000,1000); | |
rt = this.add.renderTexture(-2000, -2000, 4000, 4000); | |
trail = this.add.image(0, 0, 'space', 'ship').setOrigin(0.5,0.5).setDisplaySize(10,10).setVisible(false); | |
// Use our own gravity | |
ship.body.allowGravity = true; | |
//planet.body.allowGravity = true; | |
// Set an initial motion | |
ship.body.velocity.x = 288.67513459481285; | |
text = this.add.text(32, 32).setScrollFactor(0).setFontSize(16).setColor('#ffffff'); | |
//text.setText("test"); | |
this.cameras.main.startFollow(ship); | |
keyBackThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); | |
keyFwdThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W); | |
keyLeft = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A); | |
keyRight = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); | |
reticle = this.physics.add.sprite(ship.x, ship.y + 50, 'target'); | |
reticle.setOrigin(0.5, 0.5).setDisplaySize(10, 10); | |
// Pointer lock will only work after mousedown | |
game.canvas.addEventListener('mousedown', function () { | |
game.input.mouse.requestPointerLock(); | |
}); | |
this.input.on('pointermove', function (pointer) { | |
if (this.input.mouse.locked) | |
{ | |
reticle.x += pointer.movementX; | |
reticle.y += pointer.movementY; | |
} | |
}, this); | |
} | |
function update() { | |
ship.rotation = Phaser.Math.Angle.Between(ship.x, ship.y, reticle.x, reticle.y); | |
reticle.body.velocity.x = ship.body.velocity.x; | |
reticle.body.velocity.y = ship.body.velocity.y; | |
var noCursorDown = true; | |
var downVec = Phaser.Math.Vector2.ZERO; | |
var upVec = Phaser.Math.Vector2.ZERO; | |
var leftVec = Phaser.Math.Vector2.ZERO; | |
var rightVec = Phaser.Math.Vector2.ZERO; | |
if (keyLeft.isDown) { | |
noCursorDown = false; | |
leftVec = this.physics.velocityFromAngle(ship.angle - 90, 50); | |
//ship.body.acceleration = leftVec; | |
} | |
if (keyRight.isDown) { | |
noCursorDown = false; | |
rightVec = this.physics.velocityFromAngle(ship.angle + 90, 50); | |
//ship.body.acceleration = rightVec; | |
} | |
if (keyBackThrust.isDown) { | |
noCursorDown = false; | |
downVec = this.physics.velocityFromAngle(ship.angle - 180, 75); | |
//ship.body.acceleration = downVec; | |
} | |
if (keyFwdThrust.isDown) { | |
noCursorDown = false; | |
upVec = this.physics.velocityFromAngle(ship.angle, 150); | |
//ship.body.acceleration = upVec; | |
} | |
var addVec = new Phaser.Math.Vector2( | |
downVec.x + upVec.x + leftVec.x + rightVec.x, | |
downVec.y + upVec.y + leftVec.y + rightVec.y | |
); | |
if (noCursorDown) { | |
ship.setAcceleration(0); | |
} else { | |
ship.body.acceleration = addVec; | |
} | |
planetMass = 50000000; | |
invPlanetMass = Math.pow(planetMass, -1); | |
distance = Phaser.Math.Distance.Between(planet.x, planet.y, ship.x, ship.y); | |
distanceSquared = Math.pow(distance, 2); | |
// calculate with inverse numbers to prevent division through zero | |
//planetGravity = new Phaser.Math.Vector2(invDistanceSquared/invPlanetMass, invDistanceSquared/invPlanetMass); | |
//distanceSquared = Math.pow(distance, 2); | |
planetGravity = new Phaser.Math.Vector2(planetMass/distanceSquared, planetMass/distanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
normalized = new Phaser.Math.Vector2(planet.x - ship.x, planet.y - ship.y).normalize(); | |
shipAcc = normalized.clone().multiply(planetGravity); | |
//ship.body.gravity = shipGravity; | |
// add atmospheric drag, but not with this drag since it decelerates just to 0, instead of just slowing down things | |
/*if (distance < 100) { | |
ship.body.drag.x = 500; | |
ship.body.drag.y = 500; | |
}*/ | |
var G = 6.67e-11; | |
//var Me = | |
var velWanted = Math.sqrt(planetMass/distance); | |
ship.body.acceleration = shipAcc.clone(); | |
trail.x = ship.x + 2000; | |
trail.y = ship.y + 2000; | |
rt.draw(trail); | |
text.setText([ | |
"G: " + G, | |
"shipAcc: " + shipAcc.x + " : " + shipAcc.y, | |
"acc: " + ship.body.acceleration.x + " : " + ship.body.acceleration.y, | |
"vel: " + ship.body.speed, | |
"velWanted: " + velWanted, | |
"distance: " + distance, | |
"planetMass: " + Math.sqrt(shipAcc.x * shipAcc.x + shipAcc.y * shipAcc.y)*distanceSquared, | |
]); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on this example: | |
// * http://jsfiddle.net/gJ4kA/ | |
// further reads: | |
// * https://gamedev.stackexchange.com/questions/71233/planet-gravity | |
// * https://gamedev.stackexchange.com/questions/21063/2d-planet-gravity | |
// * http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ | |
// calc: https://www.ajdesigner.com/phpgravity/gravity_acceleration_equation.php#ajscroll | |
// todo: how to scale -> m/s² conversion to px/s² etc... | |
var config = { | |
type: Phaser.AUTO, | |
parent: 'planet-gravity-example', | |
width: 800, | |
height: 600, | |
physics: { | |
default: 'arcade', | |
arcade: { | |
gravity: { y: 0, x: 0 }, | |
debug: true | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var game = new Phaser.Game(config); | |
function preload() { | |
this.load.atlas('space', 'assets/tests/space/space.png', 'assets/tests/space/space.json'); | |
} | |
var planet; | |
var ship; | |
var keyBackThrust; | |
var keyFwdThrust; | |
var keyLeft; | |
var keyRight; | |
var reticle; | |
var rt; | |
var trail; | |
var G = 1;//6.67e-11; | |
var planetMass = 50000000; | |
var planetRadius = 500; | |
var shipRadius = 10; | |
var initialSpeed = 0; | |
function create() { | |
ship = this.physics.add.sprite(400, -300, 'space', 'ship').setDepth(2).setOrigin(0.5, 0.5).setDisplaySize(20,20); | |
planet = this.physics.add.sprite(400, 300, 'space', 'blue-planet').setOrigin(0.5, 0.5).setDisplaySize(1000,1000); | |
rt = this.add.renderTexture(-2000, -2000, 4000, 4000); | |
trail = this.add.image(0, 0, 'space', 'ship').setOrigin(0.5,0.5).setDisplaySize(10,10).setVisible(false); | |
// Use our own gravity | |
ship.body.allowGravity = false; | |
ship.body.allowDrag = false; | |
//planet.body.allowGravity = true; | |
// Set an initial motion | |
var shipBodyPos = new Phaser.Math.Vector2(ship.x, ship.y); | |
var planetBodyPos = new Phaser.Math.Vector2(planet.x, planet.y); | |
var distance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
initialSpeed = Math.sqrt(G*planetMass/distance); | |
ship.body.velocity.x = 288.67;//initialSpeed; //288;//Math.sqrt(G*planetMass/distance); | |
text = this.add.text(32, 32).setScrollFactor(0).setFontSize(16).setColor('#ffffff'); | |
//text.setText("test"); | |
this.cameras.main.startFollow(ship); | |
this.cameras.main.zoom = 0.75; | |
keyBackThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); | |
keyFwdThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W); | |
keyLeft = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A); | |
keyRight = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); | |
reticle = this.physics.add.sprite(ship.x, ship.y + 50, 'target'); | |
reticle.setOrigin(0.5, 0.5).setDisplaySize(10, 10); | |
// Pointer lock will only work after mousedown | |
game.canvas.addEventListener('mousedown', function () { | |
game.input.mouse.requestPointerLock(); | |
}); | |
this.input.on('pointermove', function (pointer) { | |
if (this.input.mouse.locked) | |
{ | |
reticle.x += pointer.movementX; | |
reticle.y += pointer.movementY; | |
} | |
}, this); | |
} | |
function update() { | |
ship.rotation = Phaser.Math.Angle.Between(ship.x, ship.y, reticle.x, reticle.y); | |
reticle.body.velocity.x = ship.body.velocity.x; | |
reticle.body.velocity.y = ship.body.velocity.y; | |
var noCursorDown = true; | |
var downVec = Phaser.Math.Vector2.ZERO; | |
var upVec = Phaser.Math.Vector2.ZERO; | |
var leftVec = Phaser.Math.Vector2.ZERO; | |
var rightVec = Phaser.Math.Vector2.ZERO; | |
var shipBodyPos = new Phaser.Math.Vector2(ship.body.x + shipRadius, ship.body.y + shipRadius); | |
var planetBodyPos = new Phaser.Math.Vector2(planet.body.x + planetRadius, planet.body.y + planetRadius); | |
//reticle.x = planetBodyPos.x; | |
//reticle.y = planetBodyPos.y; | |
if (keyLeft.isDown) { | |
noCursorDown = false; | |
leftVec = this.physics.velocityFromAngle(ship.angle - 90, 10); | |
//ship.body.acceleration = leftVec; | |
} | |
if (keyRight.isDown) { | |
noCursorDown = false; | |
rightVec = this.physics.velocityFromAngle(ship.angle + 90, 10); | |
//ship.body.acceleration = rightVec; | |
} | |
if (keyBackThrust.isDown) { | |
noCursorDown = false; | |
downVec = this.physics.velocityFromAngle(ship.angle - 180, 10); | |
//ship.body.acceleration = downVec; | |
} | |
if (keyFwdThrust.isDown) { | |
noCursorDown = false; | |
upVec = this.physics.velocityFromAngle(ship.angle, 50); | |
//ship.body.acceleration = upVec; | |
} | |
var addVec = new Phaser.Math.Vector2( | |
downVec.x + upVec.x + leftVec.x + rightVec.x, | |
downVec.y + upVec.y + leftVec.y + rightVec.y | |
); | |
if (noCursorDown) { | |
ship.setAcceleration(0); | |
} else { | |
ship.body.acceleration = addVec; | |
} | |
var invPlanetMass = Math.pow(planetMass, -1); | |
var distance = Phaser.Math.Distance.Between(planetBodyPos.x, planetBodyPos.y, shipBodyPos.x, shipBodyPos.y); | |
var distanceSquared = Math.pow(distance, 2); | |
// calculate with inverse numbers to prevent division through zero | |
//planetGravity = new Phaser.Math.Vector2(invDistanceSquared/invPlanetMass, invDistanceSquared/invPlanetMass); | |
//distanceSquared = Math.pow(distance, 2); | |
planetGravity = new Phaser.Math.Vector2((G*planetMass)/distanceSquared, (G*planetMass)/distanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
normalized = new Phaser.Math.Vector2(planetBodyPos.x - shipBodyPos.x, planetBodyPos.y - shipBodyPos.y).normalize(); | |
shipAcc = normalized.clone().multiply(planetGravity); | |
//ship.body.gravity = shipGravity; | |
// add atmospheric drag, but not with this drag since it decelerates just to 0, instead of just slowing down things | |
/*if (distance < 100) { | |
ship.body.drag.x = 500; | |
ship.body.drag.y = 500; | |
}*/ | |
//var Me = | |
//var velWanted = Math.sqrt(G*planetMass/distance); | |
ship.body.acceleration.add(shipAcc); | |
//var velCalc = Math.sqrt(Math.pow(shipAcc.x, 2) + Math.pow(shipAcc.y, 2)) * (16/1000); | |
//velCalcX = normalized.y * velWanted; | |
//velCalcY = normalized.x * velWanted * -1; | |
//velCalc = Math.sqrt(Math.pow(velCalcX, 2) + Math.pow(velCalcY, 2)); | |
//ship.body.velocity.x = velCalcX; | |
//ship.body.velocity.y = velCalcY; | |
// v = a/t (m/s) | |
trail.x = ship.x + 2000; | |
trail.y = ship.y + 2000; | |
rt.draw(trail); | |
text.setText([ | |
"G: " + G, | |
//"pos: " + planet.body.offset.x + " -- " + planet.y, | |
"shipAcc: " + shipAcc.x + " : " + shipAcc.y, | |
"acc: " + ship.body.acceleration.x + " : " + ship.body.acceleration.y, | |
"vel: " + ship.body.speed + "(" + ship.body.velocity.x + ":" + ship.body.velocity.y + ")", | |
"initVel: " + initialSpeed, | |
"distance: " + distance, | |
"planetMass: " + Math.sqrt(shipAcc.x * shipAcc.x + shipAcc.y * shipAcc.y)*distanceSquared/G, | |
]); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on this example: | |
// * http://jsfiddle.net/gJ4kA/ | |
// further reads: | |
// * https://gamedev.stackexchange.com/questions/71233/planet-gravity | |
// * https://gamedev.stackexchange.com/questions/21063/2d-planet-gravity | |
// * http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ | |
// calc: https://www.ajdesigner.com/phpgravity/gravity_acceleration_equation.php#ajscroll | |
// todo: how to scale -> m/s² conversion to px/s² etc... | |
var config = { | |
type: Phaser.AUTO, | |
parent: 'planet-gravity-example', | |
width: 800, | |
height: 600, | |
physics: { | |
default: 'arcade', | |
arcade: { | |
gravity: { y: 0, x: 0 }, | |
debug: true | |
} | |
}, | |
scene: { | |
preload: preload, | |
create: create, | |
update: update | |
} | |
}; | |
var game = new Phaser.Game(config); | |
function preload() { | |
this.load.atlas('space', 'assets/tests/space/space.png', 'assets/tests/space/space.json'); | |
} | |
var planet; | |
var ship; | |
var keyBackThrust; | |
var keyFwdThrust; | |
var keyLeft; | |
var keyRight; | |
var reticle; | |
function create() { | |
ship = this.physics.add.sprite(400, -300, 'space', 'ship').setDepth(2).setOrigin(0.5, 0.5).setDisplaySize(20,20); | |
planet = this.physics.add.sprite(400, 300, 'space', 'blue-planet').setOrigin(0.5, 0.5).setDisplaySize(1000,1000); | |
// Use our own gravity | |
ship.body.allowGravity = true; | |
//planet.body.allowGravity = true; | |
// Set an initial motion | |
ship.body.velocity.x = 275; | |
text = this.add.text(32, 32).setScrollFactor(0).setFontSize(16).setColor('#ffffff'); | |
//text.setText("test"); | |
this.cameras.main.startFollow(ship); | |
keyBackThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); | |
keyFwdThrust = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W); | |
keyLeft = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A); | |
keyRight = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); | |
reticle = this.physics.add.sprite(ship.x, ship.y + 50, 'target'); | |
reticle.setOrigin(0.5, 0.5).setDisplaySize(10, 10); | |
// Pointer lock will only work after mousedown | |
game.canvas.addEventListener('mousedown', function () { | |
game.input.mouse.requestPointerLock(); | |
}); | |
this.input.on('pointermove', function (pointer) { | |
if (this.input.mouse.locked) | |
{ | |
reticle.x += pointer.movementX; | |
reticle.y += pointer.movementY; | |
} | |
}, this); | |
} | |
function update() { | |
ship.rotation = Phaser.Math.Angle.Between(ship.x, ship.y, reticle.x, reticle.y); | |
reticle.body.velocity.x = ship.body.velocity.x; | |
reticle.body.velocity.y = ship.body.velocity.y; | |
var noCursorDown = true; | |
var downVec = Phaser.Math.Vector2.ZERO; | |
var upVec = Phaser.Math.Vector2.ZERO; | |
var leftVec = Phaser.Math.Vector2.ZERO; | |
var rightVec = Phaser.Math.Vector2.ZERO; | |
if (keyLeft.isDown) { | |
noCursorDown = false; | |
leftVec = this.physics.velocityFromAngle(ship.angle - 90, 50); | |
//ship.body.acceleration = leftVec; | |
} | |
if (keyRight.isDown) { | |
noCursorDown = false; | |
rightVec = this.physics.velocityFromAngle(ship.angle + 90, 50); | |
//ship.body.acceleration = rightVec; | |
} | |
if (keyBackThrust.isDown) { | |
noCursorDown = false; | |
downVec = this.physics.velocityFromAngle(ship.angle - 180, 75); | |
//ship.body.acceleration = downVec; | |
} | |
if (keyFwdThrust.isDown) { | |
noCursorDown = false; | |
upVec = this.physics.velocityFromAngle(ship.angle, 150); | |
//ship.body.acceleration = upVec; | |
} | |
var addVec = new Phaser.Math.Vector2( | |
downVec.x + upVec.x + leftVec.x + rightVec.x, | |
downVec.y + upVec.y + leftVec.y + rightVec.y | |
); | |
if (noCursorDown) { | |
ship.setAcceleration(0); | |
} else { | |
ship.body.acceleration = addVec; | |
} | |
planetMass = 50000000; | |
invPlanetMass = Math.pow(planetMass, -1); | |
distance = Phaser.Math.Distance.Between(planet.x, planet.y, ship.x, ship.y); | |
invDistanceSquared = Math.pow(distance, -2); | |
// calculate with inverse numbers to prevent division through zero | |
planetGravity = new Phaser.Math.Vector2(invDistanceSquared/invPlanetMass, invDistanceSquared/invPlanetMass); | |
//distanceSquared = Math.pow(distance, 2); | |
//planetGravity2 = new Phaser.Math.Vector2(planetMass/distanceSquared, planetMass/distanceSquared); | |
// Normalize and multiply by actual strength of gravity desired | |
shipGravity = new Phaser.Math.Vector2(planet.x - ship.x, planet.y - ship.y).normalize().multiply(planetGravity); | |
ship.body.gravity = shipGravity; | |
// add atmospheric drag, but not with this drag since it decelerates just to 0, instead of just slowing down things | |
/*if (distance < 100) { | |
ship.body.drag.x = 500; | |
ship.body.drag.y = 500; | |
}*/ | |
text.setText( | |
"shipGravity: " + shipGravity.x + " : " + shipGravity.y | |
//+ "\npG (inv): " + planetGravity.x + " : " + planetGravity.y | |
//+ "\npG (nor): " + planetGravity2.x + " : " + planetGravity2.y | |
+ "\nacc: " + ship.body.acceleration.x + " : " + ship.body.acceleration.y | |
+ "\nvel: " + ship.body.speed | |
+ "\ndistance: " + distance); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment