Box2D max speed

erryox

Member
I'm trying to do movement by applying force. But at the same time I want to limit the max speed of the instance. Does anyone know how to do this?
I know that the physical engine in Game Maker works separately in its own cycle. And a simple speed limit like:
Code:
phy_speed_x = clamp(phy_speed_x, -3, 3);
does not work well.
Then the question to YoYo Games, why not just add something like phy_speed_x_max and do a speed limit check right in the physics engine? In Unity, for example, this is very simple. But because of one feature I do not want to leave my favorite engine :\
 

Jezla

Member
Check the read-only phy_speed variable. If phy_speed is less than your desired max speed, then apply the force. When you're at your max speed, then either stop applying the force, or reduce it to where it just counter's the object's linear damping.
 

erryox

Member
Check the read-only phy_speed variable. If phy_speed is less than your desired max speed, then apply the force. When you're at your max speed, then either stop applying the force, or reduce it to where it just counter's the object's linear damping.
I'm already doing this. But the instance to which I apply the force is pushing another instance or even a few. That is, it is impossible to know in advance what force should be applied so that all instances move at a constant speed.

If I make the motion just making
Code:
phy_speed_x = 5
for example.
The first object simply might not have enough "power" to move the other. So this option is also not suitable.
 

Jezla

Member
I'm already doing this. But the instance to which I apply the force is pushing another instance or even a few. That is, it is impossible to know in advance what force should be applied so that all instances move at a constant speed.
You should still be able to calculate the force needed by calculating the mass of the instances being pushed, or adjusting the force to maintain a desired level of acceleration to reach the max speed. It probably isn't really that complex, even, as everything still depends on the speed of the pushing instance. If you limit it's speed, the instances being pushed shouldn't exceed that speed either, as long as no other forces act on them.
 

toxigames

Member
How about this? It works when I tested it. The object will decelerate until phy_speed does not exceed phySpdMax anymore. The multiplication should (I hope) guarantee that the correct component speed ratios are preserved such that the direction are not altered.

However you mentioned something about when the object collides with other objects it might not have enough force to move those other objects. Inherently that is how physics work: in a collision between two objects kinetic energy will be exchanged (and some released aka "lost" for example as heat energy. In Box2D some of the "energy" is transferred to the other and I believe that some of the energy just "disappears".). Just like IRL you can alleviate this by increasing the density of one of the objects. Logically an object with larger density at some speed of some size will contain more "energy" than an object with less density of same size traveling at the same speed. Thus the "lighter" of the two objects will be the one seeing the most change in speed and direction while the "heavier" one will see less change in speed and direction.

If all objects must have the same density and at the same time all must also move at the same speed after collision, I don't see much other choice than to hardcode the speed of the objects when there is a collision.


Code:
phySpdMax = 5;
phySpdDecMod= 0.9;

if(phy_speed > phySpdMax){
    phy_speed_x *= phySpdDecMod;
    phy_speed_y *= phySpdDecMod;
}
 
Last edited:

erryox

Member
You should still be able to calculate the force needed by calculating the mass of the instances being pushed, or adjusting the force to maintain a desired level of acceleration to reach the max speed. It probably isn't really that complex, even, as everything still depends on the speed of the pushing instance. If you limit it's speed, the instances being pushed shouldn't exceed that speed either, as long as no other forces act on them.
That is, you say that in such situation

I can calculate in advance what force should be applied to push this two objects using the Game Maker functions? In my opinion, having no access to the physical engine it is impossible;) In this situation, I can increase the force until the objects begin to move. But then at least for a moment, the character will still exceed maximum speed.

If all objects must have the same density and at the same time all must also move at the same speed after collision, I don't see much other choice than to hardcode the speed of the objects when there is a collision.
I'll try to do something like this. Thanks for the idea.
 
Last edited:

Jezla

Member
Yes, if you know the mass of the objects (which you can find out by checking the phy_mass variable), and the desired acceleration, you can calculate the force needed.
 

erryox

Member
Ok, if it's not so difficult for you, could you give an example of code that would do this for at least two objects, please? That is, the character pushes the box, and nothing more, on the complex surface. For example, in the path of the box there can be a hill. Because of which it will not go straight but begins to turn to the other side. In your opinion, this is not equivalent to writing another physics engine?
 

Jezla

Member
Ok, if it's not so difficult for you, could you give an example of code that would do this for at least two objects, please? That is, the character pushes the box, and nothing more, on the complex surface. For example, in the path of the box there can be a hill. Because of which it will not go straight but begins to turn to the other side. In your opinion, this is not equivalent to writing another physics engine?
No, it's not equivalent to writing another engine, and I never said it would be easy, just possible. Since you ask, I'll try and give an example. Give me a bit to work it up.

Edit: I think I have something here, you can see if it works for you. It doesn't rely on calculating masses, but on maintaining acceleration of the pushing object. Here's the code:

Code:
//Create event
max_spd = 3; //Desired max speed
d_vel = 0; //desired acceleration
force = 0; //force required

//Step event
d_vel = max_spd - phy_speed;  //Calculate desired acceleration
force = phy_mass * d_vel/(1/room_speed);  //Calculate needed force

if (phy_speed < max_spd)
     {
          physics_apply_force(x, y, force, 0);
     }
You can find the source info I used here. You can download an example here to play around with.
 
Last edited:
I seem to remember, I might be wrong, that you can't modify phy_speed directly, but you can modify phy_speed_x, and phy_speed_y.

var _scale = min(phy_speed, max_speed) / phy_speed;
phy_speed_x *= _scale;
phy_speed_y *= _scale;

You can also use a drag force, but that will cause the instance to decelerate constantly, the drag can be linear according to speed, quadratic, cubic, or greater. The effect will be that the drag will seem to kick in more or less suddenly as you approach the maximum speed.
 

erryox

Member
Edit: I think I have something here, you can see if it works for you. It doesn't rely on calculating masses, but on maintaining acceleration of the pushing object. Here's the code.
Many thanks! This is practically what I had in mind. But the main thing is that it works very well for my game. Only now I will add to your code so that the instance is not accelerated infinitely on the slopes by the gravity.
 

Jezla

Member
Many thanks! This is practically what I had in mind. But the main thing is that it works very well for my game. Only now I will add to your code so that the instance is not accelerated infinitely on the slopes by the gravity.
Glad I could help!
 
Top