Taming the physics engine..
by Jason Booth · in Torque Game Builder · 02/09/2006 (6:46 pm) · 9 replies
So I'm having a little trouble getting the physics engine under control. Basically, I have a series of polygons which act as a landscape for sprites to move across. If my polygons are completely flat, things seem to work ok; but as soon as I add any real slope to the polygons, the objects which are supposed to glide along them freak out and fly off to one side.
What I really want is for the physics to not respond to the slope at all, and rather have the objects move across the landscape following the slope. Eventually, the subdevision on the landscape will be higher res than the objects which moves across it, meaning the object might sit on a landscape which looks something like this:
____
/____\
/\/\/\/\/\/\/\/\
Well, maybe not quite that extreme, but you get the idea. I've tried playing with different collision response modes, changing mass, etc, but nothing seems to make much difference. Has anyone done anything like this? Eventually, I'd like the object to follow the average terrain slope as well, but for now I'd be happy just getting it to not fly off the screen.
Any help is appreciated..
What I really want is for the physics to not respond to the slope at all, and rather have the objects move across the landscape following the slope. Eventually, the subdevision on the landscape will be higher res than the objects which moves across it, meaning the object might sit on a landscape which looks something like this:
____
/____\
/\/\/\/\/\/\/\/\
Well, maybe not quite that extreme, but you get the idea. I've tried playing with different collision response modes, changing mass, etc, but nothing seems to make much difference. Has anyone done anything like this? Eventually, I'd like the object to follow the average terrain slope as well, but for now I'd be happy just getting it to not fly off the screen.
Any help is appreciated..
About the author
#2
02/11/2006 (1:28 pm)
What you're looking for is:t2dSceneObject.setCollisionMaxIterations(2);The default collision iterations is 1 for performance purposes. It works in most cases. The reason it's not working for you is because not all of the elapsed time is being used in calculating the collision response and something like what you're doing needs it to.
#3
02/11/2006 (3:41 pm)
Thanks for the help, Adam, but unfortunately I've allready experimented with that setting to no avail. I just don't get it, having one object move over another (car on terrain) seems like a pretty standard thing to do; why is it so hard? It's not like I'm trying to do anything complex.
#4
Anyway, for now, I have some hacks in place that almost work. Basically, I now update the player every frame and set it's velocity, but this produces some small jerkyness in motion, and doesn't seem like the correct way to do things since it requires both a per frame update and produces inconsistant results.
02/11/2006 (6:51 pm)
Ok, this physics engine is making no sense to me. For some reason, increasing the mass of the object makes gravity effect it less. That just doesn't seem right. Hmm. Could it be because there isn't really gravity in t2d, only constant force, and that constant force is being applied in reference to mass? Does that mean things like friction/force/mass/etc are all being applied as if the screen is the ground? Is there a way to change this behavior, since my game is from the side and that behavior is undesirable?Anyway, for now, I have some hacks in place that almost work. Basically, I now update the player every frame and set it's velocity, but this produces some small jerkyness in motion, and doesn't seem like the correct way to do things since it requires both a per frame update and produces inconsistant results.
#5
02/11/2006 (6:59 pm)
Did you set it as gravitic ?
#6
I'm going to give this some sleep, and probrably give up on t2d physics and just write my own code tommorow. It's not like the physics I need is very complex, all it really has to do is a) collide with the surface, and b) allow the other object to move along that surface based on the angle of the surface normal.
It just seems like something so simple should be possible in the physics engine. It makes me wonder, is anyone using the physics engine and getting good results? Has anyone made a platformer with platforms that are not axis aligned? Or collition polygons which *gasp* touch each other? I don't mean to sound pissy, but I've wasted an amazing amount of time on this and it just seems absurd that this doesn't work. In case anyone can spot anything wrong, here's the relivant parts of the definitions:
terain polys are created in a loop; right now, the height is a constant, so it's just a bunch of boxes that are all of equal height:
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionCallback = false;
CollisionMaxIterations = 2;
CollisionPolyList = (%x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
CollisionMaterial = terrainMaterial;
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "0";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
};
%poly.setImmovable(true);
%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
player definition:
%this.sprite = new t2dStaticSprite() {
scenegraph = t2dScene;
lifetime = "0";
Position = "0 25";
size = "5 4";
layer = "1";
group = "1";
collisionDetectionMode = "POLYGON";
collisionResponseMode = "RIGID";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
CollisionPolyList = "-1.000000 0.985611 -0.980815 0.529976 -0.410072 -0.107914 0.050360 -0.213429 0.472422 -0.059952 0.990408 0.510791 0.990408 0.995204";
collisionCircleScale = "1";
collisionPolyScale = "1 1";
collisionCircleSuperscribed = "1";
linearVelocity = "0 0";
minlinearVelocity = "0";
maxLinearVelocity = "10000";
angularVelocity = "0";
minAngularVelocity = "0";
maxAngularVelocity = "10";
immovable = "0";
constantForce = "0" SPC $gravity;
gravitic = true;
forceScale = "1";
density = "1.0";
autoMassInertia = "1";
mass = "1";
inertialMoment = "1";
damping = "0";
friction = "0.3";
restitution = "1";
imageMap = "tankbaseIMap";
};
%this.sprite.setConstantForce(0 SPC $gravity, true);
%this.sprite.setCollisionMaxIterations(2);
If the player hits a single terain poly, he's fine. However, if he moves to touch two polygons, he gets thrown to the other side of the screen.
02/12/2006 (1:11 am)
Yes, setting gravic seems to fix the mass issue; but I'll be damned if I can get the physics to stop freaking out whenever there;s more than one polygon involved. Basically, the second you come into contact with two polygons (even if the polygons are the exact same height and perfectly aligned), the other object gets thrown out of the scene.I'm going to give this some sleep, and probrably give up on t2d physics and just write my own code tommorow. It's not like the physics I need is very complex, all it really has to do is a) collide with the surface, and b) allow the other object to move along that surface based on the angle of the surface normal.
It just seems like something so simple should be possible in the physics engine. It makes me wonder, is anyone using the physics engine and getting good results? Has anyone made a platformer with platforms that are not axis aligned? Or collition polygons which *gasp* touch each other? I don't mean to sound pissy, but I've wasted an amazing amount of time on this and it just seems absurd that this doesn't work. In case anyone can spot anything wrong, here's the relivant parts of the definitions:
terain polys are created in a loop; right now, the height is a constant, so it's just a bunch of boxes that are all of equal height:
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionCallback = false;
CollisionMaxIterations = 2;
CollisionPolyList = (%x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
CollisionMaterial = terrainMaterial;
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "0";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
};
%poly.setImmovable(true);
%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
player definition:
%this.sprite = new t2dStaticSprite() {
scenegraph = t2dScene;
lifetime = "0";
Position = "0 25";
size = "5 4";
layer = "1";
group = "1";
collisionDetectionMode = "POLYGON";
collisionResponseMode = "RIGID";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
CollisionPolyList = "-1.000000 0.985611 -0.980815 0.529976 -0.410072 -0.107914 0.050360 -0.213429 0.472422 -0.059952 0.990408 0.510791 0.990408 0.995204";
collisionCircleScale = "1";
collisionPolyScale = "1 1";
collisionCircleSuperscribed = "1";
linearVelocity = "0 0";
minlinearVelocity = "0";
maxLinearVelocity = "10000";
angularVelocity = "0";
minAngularVelocity = "0";
maxAngularVelocity = "10";
immovable = "0";
constantForce = "0" SPC $gravity;
gravitic = true;
forceScale = "1";
density = "1.0";
autoMassInertia = "1";
mass = "1";
inertialMoment = "1";
damping = "0";
friction = "0.3";
restitution = "1";
imageMap = "tankbaseIMap";
};
%this.sprite.setConstantForce(0 SPC $gravity, true);
%this.sprite.setCollisionMaxIterations(2);
If the player hits a single terain poly, he's fine. However, if he moves to touch two polygons, he gets thrown to the other side of the screen.
#7
I think there's your problem.
Platformers don't tend to want to use physically-based rigid-body collision responses. They're generally more wanting behavior like clamp.
02/12/2006 (10:25 am)
Quote:collisionResponseMode = "RIGID";
I think there's your problem.
Platformers don't tend to want to use physically-based rigid-body collision responses. They're generally more wanting behavior like clamp.
#8
02/12/2006 (10:31 am)
Yeah; I've tried to use clamp as well, but it does the same thing; the player just fly's across the screen once it hits more than one poly.
#9
My terrain is made up of tons of small virtical sliver polygons (100, for right now). The algorithm which generates the terrain outputs a height value for each upper vertex between 0.2 and 0.8. The bottom is at a y value of 1.
Collision polygons are defined by values between -1 and 1 (not 0 and 1). a value between 0.2 and 0.8 means that the center point of the polygon is often outside of the actual polygon. It's in this case I believe the bug exists. If I change my algorithm to output a value between -0.2 and -0.8 instead, everything works fine and the physics system is stable.
Here's the working and non working versions:
working:
function GenerateTerrain()
{
// starting height from 20 to 60
%h = (getrandom() * 20) + 40;
for (%i = 0; %i < 99; %i++)
{
%nh = %h + ((getrandom() * 8) - 4);
if (%nh > 80)
%nh = 80;
if (%nh < 20)
%nh = 20;
%x = (%i * 0.02) - 1;
%x2 = %x + 0.02;
%y = (%h * -0.01);
%y2 = (%nh * -0.01);
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionMaxIterations = 2;
collisionPolyList = "-1.00 " @ %y @ " 0.99 " @ %y2 @" 0.99 0.99 -1.00 0.99";
//collisionPolyList = (-1 SPC -1 SPC 1 SPC -1 SPC 1 SPC 1 SPC -1 SPC 1);
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
collisionCircleScale = "1";
collisionPolyScale = "1 1";
collisionCircleSuperscribed = "1";
};
%poly.setImmovable(true);
//%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
%poly.setPolyCustom(4, -1 SPC %y SPC 1 SPC %y2 SPC 1 SPC 1 SPC -1 SPC 1);
%poly.setFillMode(true);
%poly.setFillColor("0.5 0.5 0.5 1");
%poly.setLineColor("0.5 1 0.5 0.2");
%poly.setPosition((%i - 50) SPC 30);
%poly.setSize("1 70");
%h = %nh;
}
}
non-working:
function GenerateTerrain()
{
// starting height from 20 to 60
%h = (getrandom() * 20) + 40;
for (%i = 0; %i < 99; %i++)
{
%nh = %h + ((getrandom() * 8) - 4);
if (%nh > 80)
%nh = 80;
if (%nh < 20)
%nh = 20;
%x = (%i * 0.02) - 1;
%x2 = %x + 0.02;
%y = (%h * 0.01); // working requires a - value for some reason
%y2 = (%nh * 0.01); // why?
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionMaxIterations = 2;
collisionPolyList = "-1.00 " @ %y @ " 0.99 " @ %y2 @" 0.99 0.99 -1.00 0.99";
//collisionPolyList = (-1 SPC -1 SPC 1 SPC -1 SPC 1 SPC 1 SPC -1 SPC 1);
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
collisionCircleScale = "1";
collisionPolyScale = "1 1";
collisionCircleSuperscribed = "1";
};
%poly.setImmovable(true);
//%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
%poly.setPolyCustom(4, -1 SPC %y SPC 1 SPC %y2 SPC 1 SPC 1 SPC -1 SPC 1);
%poly.setFillMode(true);
%poly.setFillColor("0.5 0.5 0.5 1");
%poly.setLineColor("0.5 1 0.5 0.2");
%poly.setPosition((%i - 50) SPC 5); // the position needs to be offset to see the mesh
%poly.setSize("1 70");
%h = %nh;
}
}
02/12/2006 (11:18 am)
AHA! I figured it out, and I believe it's a bug in torque; one likely that others wouldn't hit. So here's the deal:My terrain is made up of tons of small virtical sliver polygons (100, for right now). The algorithm which generates the terrain outputs a height value for each upper vertex between 0.2 and 0.8. The bottom is at a y value of 1.
Collision polygons are defined by values between -1 and 1 (not 0 and 1). a value between 0.2 and 0.8 means that the center point of the polygon is often outside of the actual polygon. It's in this case I believe the bug exists. If I change my algorithm to output a value between -0.2 and -0.8 instead, everything works fine and the physics system is stable.
Here's the working and non working versions:
working:
function GenerateTerrain()
{
// starting height from 20 to 60
%h = (getrandom() * 20) + 40;
for (%i = 0; %i < 99; %i++)
{
%nh = %h + ((getrandom() * 8) - 4);
if (%nh > 80)
%nh = 80;
if (%nh < 20)
%nh = 20;
%x = (%i * 0.02) - 1;
%x2 = %x + 0.02;
%y = (%h * -0.01);
%y2 = (%nh * -0.01);
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionMaxIterations = 2;
collisionPolyList = "-1.00 " @ %y @ " 0.99 " @ %y2 @" 0.99 0.99 -1.00 0.99";
//collisionPolyList = (-1 SPC -1 SPC 1 SPC -1 SPC 1 SPC 1 SPC -1 SPC 1);
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
collisionCircleScale = "1";
collisionPolyScale = "1 1";
collisionCircleSuperscribed = "1";
};
%poly.setImmovable(true);
//%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
%poly.setPolyCustom(4, -1 SPC %y SPC 1 SPC %y2 SPC 1 SPC 1 SPC -1 SPC 1);
%poly.setFillMode(true);
%poly.setFillColor("0.5 0.5 0.5 1");
%poly.setLineColor("0.5 1 0.5 0.2");
%poly.setPosition((%i - 50) SPC 30);
%poly.setSize("1 70");
%h = %nh;
}
}
non-working:
function GenerateTerrain()
{
// starting height from 20 to 60
%h = (getrandom() * 20) + 40;
for (%i = 0; %i < 99; %i++)
{
%nh = %h + ((getrandom() * 8) - 4);
if (%nh > 80)
%nh = 80;
if (%nh < 20)
%nh = 20;
%x = (%i * 0.02) - 1;
%x2 = %x + 0.02;
%y = (%h * 0.01); // working requires a - value for some reason
%y2 = (%nh * 0.01); // why?
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionMaxIterations = 2;
collisionPolyList = "-1.00 " @ %y @ " 0.99 " @ %y2 @" 0.99 0.99 -1.00 0.99";
//collisionPolyList = (-1 SPC -1 SPC 1 SPC -1 SPC 1 SPC 1 SPC -1 SPC 1);
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
collisionCircleScale = "1";
collisionPolyScale = "1 1";
collisionCircleSuperscribed = "1";
};
%poly.setImmovable(true);
//%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
%poly.setPolyCustom(4, -1 SPC %y SPC 1 SPC %y2 SPC 1 SPC 1 SPC -1 SPC 1);
%poly.setFillMode(true);
%poly.setFillColor("0.5 0.5 0.5 1");
%poly.setLineColor("0.5 1 0.5 0.2");
%poly.setPosition((%i - 50) SPC 5); // the position needs to be offset to see the mesh
%poly.setSize("1 70");
%h = %nh;
}
}
Torque Owner Jason Booth
I've reduced the complexity down all the way. I'm trying to get one sprite to move along one polygon, with no luck what so ever. If that polygon is completely flat, then things seem to work. But if there is any slope at all, the obejct is barely moveable and produces unpredictable results. If the object touches more than one polygon, then physics freaks out and sends the object flying across the scene.
So now I'm playing around with bounce, because I've tried just about everything I can think of with the other modes. I've tried setting restitution and damping to extremely high and low values, and no matter what they are set to, I see the exact same result. The object simply bounces up and down never loosing any energy. Yet, from what I can tell, I should be able to use these values to make the object bounce less after each impact.
So, is the physics system just completely broken in this release? Is it useful for anything other than pong balls and flat platforms? Has anyone successfully gotten an object moving up a slope with it, and if so, how!?!