I was wondering if anyone can give me pointers on how to achieve the following using Box2D on the iphone:
1) I have a Box2D world with normal gravity of -9.8
2) The bottom half of the screen is a body of water
So when my sprite hits the body of water, I want him to react with buoyancy (similar to what's going on in this video: http://www.youtube.com/watch?v=0uX-1GXYIss)
Is the best way to achieve this to
1) simply calculate the y position of the main character sprite and then switch the gravity variable accordingly
or 2) is there a specific feature built into Box2D that will allow me to set my "water" sprite to behave as water in my world and "push" my main character sprite up (while still respecting the world gravity of 9.8)
Any info would be appreciated
The buoyant force is equal to the density of the fluid times the volume of the fluid displaced (which gives you the mass of the fluid displaced) times the acceleration due to gravity. The volume of fluid displaced can be costly to compute however. I would suggest making a simple estimate of the volume displaced based on the size of the object and how far it is submerged in the liquid.
Another very important force in fluid is the drag force. This is what makes it more difficult to move objects at high velocity through thick fluids. The drag force can easily be estimated by simply damping the velocity by some constant value: Force_drag = -b * v where b is your damping value and v is the object's velocity.
Related
I‘m trying to create real physics simulation of the universal joint in unity. In my case universal joint is in vertical position. The whole mechanism consists of four objects: white ceiling, green shaft, blue universal joint and red shaft. All parts have Rigidbody component, with specific mass (ceiling – 1kg, green shaft – 0,05 kg, blue universal joint - 0,01 kg, red shaft – 0,05 kg). The mass of center of the parts are represented in the pictures. All objects dimensions are NOT scaled and represent the real dimensions of an object in cm. The Box Colliders or Mesh Colliders were not added to the objects.
Green shaft center of mass point, Blue universal joint center of mass point, Red shaft center of mass point
The parameters for all objects are represented in the pictures: Green shaft parameters, Blue universal joint parameters and Red shaft parameters. To the ceiling object only Rigidbody component was added with an “Is Kinematic” option, without the “Use Gravity” option. One Fixed Joint and two Hinge Joints are used for objects. My aim is to create realistic physics behavior of this universal joint in simulation. For example, while playing the scene I want to be able to move the red shaft end, let go it and see how because of gravity and friction red shaft swings back to initial position. I want to do this with object components and project settings, not with a script if possible. If I succeed with universal joint physics I will later plan to add a point on the red shaft object end, which would have Constant Force component and would pull the red shaft end on demand with force to the certain direction. But the force which would pull the red shaft end would be based on real measurements.
The problem that I’m currently facing right now is with the object swinging back to initial position. If I leave Rigidbody and Hinge Joint parameters as it is represented in pictures and try to move red shaft end in scene play mode, the red shaft and blue joint swings back to initial position very very slowly. Like it would have no mass or would have very high friction. But if I turn on red shaft and blue Use Spring parameter in the Hinge Joint and set Spring value for example to 0.2 the shaft as expected goes back to initial position much faster. I also noticed that if I increase object Scale parameters (increase object size) for example from 1 to 100 it swings faster without the spring parameter turned on.
My first question which component or project parameters have the most impact on pulling object down in gravity direction?
Is where more friction friction parameters about which I should know while creating this universal joint model? Because so far I have changed only Drag, Angular Drag to 0, I have created a PhysicMaterial with almost no friction and added it to Default Material field in Project Settings->Physics. I have increased Default Solver Iterations and Default Solver Velocity Iterations almost to the maximum.
My third question would be, is it even possible to create a realistic universal joint shaft swinging without Spring option turned on in the Hinge Joint? Or should I better write the script that would define the red shaft swinging with gravity behavior?
First, Unity physics are not real physics, they are real-looking physics.
Second, Unity units are typically assumed to be in meters. When you set a position to <1, 0, 0> you should assume your object is at 1 meter in x.
Third, Unity physics uses colliders to determine volumes, for the purposes of moments of inertia.
So, when you say that
The mass of center of the parts are represented in the pictures. All objects dimensions are NOT scaled and represent the real dimensions of an object in cm. The Box Colliders or Mesh Colliders were not added to the objects.
It makes me think that (1) you are using the wrong scaling, like 1 = 1 centimeter instead of the assumed 1 = 1 meter, and (2) you're preventing Unity from being able to really run the physics calculations correctly because you're not providing volumetric information to the physics engine (which again is done via the collider volumes).
Also, your masses seem very, very, very small. You've got the universal joint at 10 grams, which is really not much at all.
You're seeing better results when you add a spring because the spring is adding a force, where your weights are small and your missing colliders are failing to do much with physics.
I would suggest adding mesh colliders and increasing the weights to get the behavior you want to see.
I am creating a game where i need to be able to change the speed of the player sprite. I think the best option is to effect the sprites by gravity. To give the user the feeling of movement I want the background to move in the exact same speed just in the opposite direction.
How can i give the background a different gravity then the player sprite?
If you know about a better approach I would really appreciate your suggestions as well.
You can change the linearDamping property of a node to change the rate that it falls. From the docs,
This property is used to simulate fluid or air friction forces on the
body. The property must be a value between 0.0 and 1.0. The default
value is 0.1. If the value is 0.0, no linear damping is applied to the
object.
Note that linear damping will also affect the node's side-to-side movement as well.
How does SpriteKit's physics engine (Box2d) move bodies and apply gravity to them?
is it just the standard:
velocity = velocity + gravity
position = position + velocity * deltaTime
or is there a more complex equation.
I ask this because I am trying to calculate the trajectory of the body and plot it.
Simplified, this is correct. However there can be other forces acting on a body (collisions, joints) and thresholds (ie stop moving if velocity below threshold, etc) and floating point rounding errors can add up.
So if you're looking for a forward calculation it depends on how precise it needs to be.
The most precise option would be to actually run the simulation to advance it to see where bodies will be - however since SK doesn't give you the Box2D sources this can't be done, ie you can't copy the world state and advance it manually in a copy of the current world.
I am using Box2d to simulate a top-down space like environment. I have an object that has an impulse applied and will be flying (through space) near to a "planet". The world itself has no gravity but I would like to set up Planets and Stars with individual gravity such that other dynamic objects will fall / be pulled in towards them. How can I achieve this?
If you have small count of bodies/stars you can just apply gravity forces to your bodies each time before calling Step() function.
But I think it will become really slow if the system gets big. If your stars and planets are not moving you are able to precalculate the total gravity force in each point of 2D space. Store this precalculated values of gravity in some 2D array (with some step) and then apply the forces from this lookup table
I have a ball that you blow on with air. I want the ball to be blown more if it is close to the blower and blown less if it is farther away from the blower. I am using box2d and I am using the impulse function."body->ApplyLinearImpulse(force, body->GetPosition())". I can't seem to find a formula or a way to accomplish this. If I want the ball to blow to a total distance of 300 pixels right, how could I accomplish this? Please help.
If you want to calculate the distance before simulation you have to take a look at box2d sources. When simulating the velocity of the body is modified according to gravity, extra applied forces, linear damping, angular damping and possibly something more. Also velocity relies on velocity iterations.
But I think if you want a really smooth motion (like from a blow) you'd better use applyForce function instead of impulse. But be sure you are applying the force each simulation step.
EDIT:
Also you can simulate the air resistance as:
Fa = -k*V*V. I've simulated movement in the pipe this way. Worked great.
So each step you can make something like this:
BlowForce = k1 / distance; // k1 - coefficient
Resistance = -k2 * V * V; //k2 - another coefficient
TotalForce = BlowForce + Resistance;
body->ApplyForce(TotalForce);
I am not a box 2d expert but what i would do is create a small box which is actually invisible and let the ball hit the box...if the blower is blowing more i would give more speed to the box in opposite direction. As far as 300 pixel length is concerned you have to adjust the forces and velocity such that the ball goes
300/<your_rendering_window_to_physics_world_ratio>
in physical world.
Force = mass * acceleration, so take the mass you set your body to, calculate the acceleration you want (remember to divide 300px by PTM_RATIO) and then multiply the two together.