Gravity Wells and Black Holes
by Russell Tracey · in Torque Game Builder · 03/31/2005 (4:52 pm) · 44 replies
I'm attempting to produce a gravity well type effect which sucks objects towards it in a black hole like way. I've tried a mounting an object to the centre of the black hole and setting it to chase the mount point but this doesn't seem to work. I have tried several different force values but they are either too weak or too strong. If its too much then the objects go straight to the centre, if its not enough they fly right past but gradually slow until they are stop half way off the screen.
What I am trying to achieve is a black hole that will start to drag a ship into it if the ship gets too close, if the ship however has enough force it can escape the black hole but its direction will be altered slightly due to the effects of the black hole.
Has anyone got something like this working?
What I am trying to achieve is a black hole that will start to drag a ship into it if the ship gets too close, if the ship however has enough force it can escape the black hole but its direction will be altered slightly due to the effects of the black hole.
Has anyone got something like this working?
About the author
#2
I haven't tackled this yet, but it should be pretty easy and its on my todo list for Exodus2D. Blackholes. I will probably just determine the angle between the player and the black hole then use setConstantForcePolar(); to apply the gravitational effect of the black hole.
03/31/2005 (6:00 pm)
SetConstantForce[Polar]();I haven't tackled this yet, but it should be pretty easy and its on my todo list for Exodus2D. Blackholes. I will probably just determine the angle between the player and the black hole then use setConstantForcePolar(); to apply the gravitational effect of the black hole.
#3
03/31/2005 (7:05 pm)
The problem with that suggestion is that it doesn't change based on the movement of the target being affected. That force must be updated every tick, and I don't know of an easy TScript way to do that.
#4
03/31/2005 (7:07 pm)
Its a CONSTANT force so my assumption is it is updated every tick. It acts that way at any rate.
#5
edit: also, you'll have to schedule a loop in order to keep the force updated (smaug is correct here). However, you don't absolutely need to update every tick.
03/31/2005 (7:09 pm)
One thing you may have to be aware of is if your player movements are using setConstantForcePolar() as well. I would consider using impulse for player movement, and constant for the black hole / gravity well. If both are using constantforce, they'll end up overriding each other.edit: also, you'll have to schedule a loop in order to keep the force updated (smaug is correct here). However, you don't absolutely need to update every tick.
#6
That all depends on the relative velocities between the objects and precisely how much error you wish to tolerate for said forces.
03/31/2005 (7:12 pm)
Quote:However, you don't absolutely need to update every tick.
That all depends on the relative velocities between the objects and precisely how much error you wish to tolerate for said forces.
#7
03/31/2005 (7:14 pm)
You could use the onUpdateScene() callback from fxSceneGraph2D to update the direction each frame. Otherwise, schedule() works just fine for updating an Asteroids-type ship's thrust direction while rotating, even at relatively high (say 100 ms) intervals.
#8
03/31/2005 (7:36 pm)
Are you guys sure about this? I havent' tested it directly but when I Was messing around with various functions I could have sworn that the effect of this function remained constant until such time as I explicitly set it to 0. IE one call to setConstantForcePolar() would continue to act on the object until such time as I zeroed it out. Even looking at the description it seems this funciton is designed SPECIFICLY for this type of use.
#9
03/31/2005 (7:43 pm)
If there are no other forces acting upon the object, and no other factors affecting its velocity (friction, damping, etc), and you want it to go in a straoght line, then no, you do not need to repeatedly call setConstantForce. Note that none of the above apply in such a situation where there's a gravity well, and player movement input.
#10
Now, maybe John is right as well, and Melv's physics model takes this into account when you define the polar force in the first place--knowing Melv and his attention to detail, that may very well be the case! If true, that would mean that Smaug is correct, but that John is correct as well--because T2D handles it!
Quick question to prove or disprove: when you apply a constant force, either linear or polar, does the object continue to accelerate, or does it just move at a constant speed (assuming no other forces are interacting with the object). If it continues to accelerate, then the "force" really is a force--otherwise, it's an impulse.
03/31/2005 (7:50 pm)
Been banging my head back and forth on this trying to remember my gravitational physics, but Smaug is correct in that while the scalar of the force is constant, it's vector (direction) has to be constantly updated to point back to the gravitational source. Each tick of movement processing is going to need to have the direction of the force applied appropriately to get accurate movement.Now, maybe John is right as well, and Melv's physics model takes this into account when you define the polar force in the first place--knowing Melv and his attention to detail, that may very well be the case! If true, that would mean that Smaug is correct, but that John is correct as well--because T2D handles it!
Quick question to prove or disprove: when you apply a constant force, either linear or polar, does the object continue to accelerate, or does it just move at a constant speed (assuming no other forces are interacting with the object). If it continues to accelerate, then the "force" really is a force--otherwise, it's an impulse.
#11
03/31/2005 (7:59 pm)
Yup, setConstantForce*() does just that, but the direction of the force still needs to be manually updated to match the changing direction vector from object->black hole.
#12
Impulse
Adds the specified force to the object instantaneously. This means that the whole force is applied without time considerations. An instance change in velocity occurs.
Constant
Adds the specified force continuously until told to stop. The specified force is applied per/sec (integrated over the second). A continuous change in velocity occurs.
When applying a force, you can select whether the force takes into account the objects mass. If the mass is taken into account, the actual change in velocity is inversely proportional to the objects mass e.g. as the mass increases, it takes more force to create a change in velocity. This is the "gravitic?" option (see ref doco).
The "polar" versions of functions are just shortcut-helpers to the non-polar versions and save you from calculating the X/Y components yourself. T2D objects don't have a sense of forward or up so the angle you use in these functions is always with reference to the world-coordinate system, in other words, zero-deg will always be "up" (negative Y-axis).
Using something like "setImpulseForcePolar(90, 10)" always means apply a one-time instant force along the postive X axis.
Using something like "setConstantForcePolar(90, 10)" always means apply a continuous force along the postive X axis. If the object rotates, the force will still be along the postive X-axis. Don't forget that objects don't have the sense of forward.
Smaug and others are quite correct in that you really should update the forces each frame either in script or via a simple override of the "integrateObject()" in C++, possibly on a custom object. This, of course, depends on how accurate and/or sensitive the forces are/need to be.
My friend and I did this for one of our Game-in-a-day attempt for "KinetiK". The way I did this was to create a new T2D object. I setup this object so that I could pass T2D (fxSceneObject2D) object references to it and give it a value that was the force it would use to either attract or repel those objects in its "integrateObject()" function using their "setConstantForcePolar()" C++ calls. It just cycled its vector of fxSceneObject2D objects and calculated the direction and distance from the object and adjusted the constant force on it. You could use an "impulse" force so that you don't tie-up the constant-force but you need to be careful as an impulse force is instantaneous and you should integrate the force over time yourself e.g. the product of the force and elapsed time.
We just then mounted this object to the graphics of black-holes/star-bursts in the game.
This is suprisingly really simple code to get running. Took less than an hour to get that object working, it's that simple.
See this .plan for more details on the GID entry.
I'll try to remember to dig this code out and post it, if that would be helpful. It was on an old T2D codebase so there may be minor mods needed but it should do what it says on the tin.
Hope this helps,
- Melv.
04/01/2005 (12:03 am)
Just to clarify on forces...Impulse
Adds the specified force to the object instantaneously. This means that the whole force is applied without time considerations. An instance change in velocity occurs.
Constant
Adds the specified force continuously until told to stop. The specified force is applied per/sec (integrated over the second). A continuous change in velocity occurs.
When applying a force, you can select whether the force takes into account the objects mass. If the mass is taken into account, the actual change in velocity is inversely proportional to the objects mass e.g. as the mass increases, it takes more force to create a change in velocity. This is the "gravitic?" option (see ref doco).
The "polar" versions of functions are just shortcut-helpers to the non-polar versions and save you from calculating the X/Y components yourself. T2D objects don't have a sense of forward or up so the angle you use in these functions is always with reference to the world-coordinate system, in other words, zero-deg will always be "up" (negative Y-axis).
Using something like "setImpulseForcePolar(90, 10)" always means apply a one-time instant force along the postive X axis.
Using something like "setConstantForcePolar(90, 10)" always means apply a continuous force along the postive X axis. If the object rotates, the force will still be along the postive X-axis. Don't forget that objects don't have the sense of forward.
Smaug and others are quite correct in that you really should update the forces each frame either in script or via a simple override of the "integrateObject()" in C++, possibly on a custom object. This, of course, depends on how accurate and/or sensitive the forces are/need to be.
My friend and I did this for one of our Game-in-a-day attempt for "KinetiK". The way I did this was to create a new T2D object. I setup this object so that I could pass T2D (fxSceneObject2D) object references to it and give it a value that was the force it would use to either attract or repel those objects in its "integrateObject()" function using their "setConstantForcePolar()" C++ calls. It just cycled its vector of fxSceneObject2D objects and calculated the direction and distance from the object and adjusted the constant force on it. You could use an "impulse" force so that you don't tie-up the constant-force but you need to be careful as an impulse force is instantaneous and you should integrate the force over time yourself e.g. the product of the force and elapsed time.
We just then mounted this object to the graphics of black-holes/star-bursts in the game.
This is suprisingly really simple code to get running. Took less than an hour to get that object working, it's that simple.
See this .plan for more details on the GID entry.
I'll try to remember to dig this code out and post it, if that would be helpful. It was on an old T2D codebase so there may be minor mods needed but it should do what it says on the tin.
Hope this helps,
- Melv.
#13
Basically I just added a new physics property -- gravitational attraction. This gets scaled by the mass, and falls off based on distance, just like real gravitational force.
I implemented this as applied impulse, as that lets Melv's physics code handle the rest of it. It's all C++ code though, as it must loop through all fxsceneobject's to calculate accumulated gravitational attraction.
04/01/2005 (12:50 am)
I've done this myself (See here for an example) but I did a little differently.Basically I just added a new physics property -- gravitational attraction. This gets scaled by the mass, and falls off based on distance, just like real gravitational force.
I implemented this as applied impulse, as that lets Melv's physics code handle the rest of it. It's all C++ code though, as it must loop through all fxsceneobject's to calculate accumulated gravitational attraction.
#14
If anyone wants the code for the 'KinetiK' gravity object then I'd be happy to email it.
It's a little raw but is quite functional.
- Melv.
04/01/2005 (1:32 am)
Very cool David. :)If anyone wants the code for the 'KinetiK' gravity object then I'd be happy to email it.
It's a little raw but is quite functional.
- Melv.
#15
04/01/2005 (6:32 am)
Use schedule to call a function that itself schedules itself at regular intervals. Let the function give the the objects an impulse whose magnitude is proportional to 1/r^2. The interval between schedules should be fairly short, I guess 30 times a second would be enough. Note that only 1/r^2 will produce stable orbits (they may still not be that stable depending on the strength of the force and interval between schedules and physics updates).
#16
- Melv.
04/01/2005 (9:23 am)
Just thought I'd repeat that if anyone wants the code, I'll be happy to sent it but it will be unsupported. ;)- Melv.
#17
I'd love that code please Melv, russell.tracey@gmail.com.
04/01/2005 (10:08 am)
Thanks for all the ideas everyone. I'll post my results when i've got something working as it seems it would be useful to others.I'd love that code please Melv, russell.tracey@gmail.com.
#18
You can compile this code and it will run immediately from the SDK without modifications. Read the "readme.txt" for instructions.
- Melv.
04/01/2005 (10:23 am)
Email sent. :)You can compile this code and it will run immediately from the SDK without modifications. Read the "readme.txt" for instructions.
- Melv.
#19
04/02/2005 (11:20 am)
Will something like this be included in future releases of t2d?
#20
- Melv.
04/03/2005 (1:41 am)
@Alex: It's a very specific effect so at first I wouldn't think so. If it was generally useful (and I'm willing to accept that) then I wouldn't see why not. I don't want to clutter-up the SDK with lots of different, very specific objects. Davids approach of having some internal attribute is interesting though.- Melv.
Torque Owner Smaug
Basically, you need to create a constant force, whose magnitude is based on distance and whose direction points towards the gravity well. The magnitude and direction must be constantly updated. Its the kind of thing you'd want to specifically add to the physics system.