How can one make a box2d body move in a spiral motion? I believe it will require applying some force but I am not sure how. I would appreciate any assistance.
You can chain joints together using intermediate invisible bodies. Pin a body at the center to the ground with a revolute joint, and a prismatic from that body to the real one. Two joints = two motors = two controllable degrees of freedom.
You'll have two forces, a tangential force, and a radial force.
The tangential force accelerates the body around the center.
The radial force accelerates the body towards or away from the center.
radialVector = (objectPosition - spiralCenter).normalize();
tangentialVector = radialVector.perpendicularVector();
forceTangential = tangentialForceMagnitude * tangentialVector;
forceRadial = radialForceMagnitude * radialVector;
force = forceTangential + forceRadial;
object.applyForce(force);
The specific values for your force magnitudes will determine the behaviour of the spiral; things like wether it's an inward or outward motion, and how fast.
I answered a related question about making a whirlpool/vortex: SO: How to create whirlpool/vortex effect?
Related
I am currently programming a 3D physics engine in C++ and have two spheres in my scene. I can detect when said spheres are colliding and they have some basic collision as a response but the spheres go inside each other a lot and act minimally upon each other so I'm looking to change this to be a RigidBody collision. I've looked online and many tutorials are on 2D collisions and use Elastic collision which is already hard enough to translate into 2D. Any advice on where to look for Rigidbody sphere collision would be a huge help and I'll put below the code I am currently using for my collision. Thanks in advance!
for (size_t i = 0; i < pool.size(); i++)
{
if (pool.at(i) == this)
{
continue;
}
DynamicObjects* other = pool.at(i);
SScollision = PFG::SphereToSphereCollision(pos, other->GetPosition(), rad, other->GetRadious(), contactPoint);
if (SScollision)
{
glm::vec3 relativeVel = this->GetVelocity() - other->GetVelocity();
float eCof = -(1.0f + 1.0f) * glm::dot(relativeVel, contactPoint);
float jLin = eCof / (1.0f / this->GetMass() + 1.0f / other->GetMass());
glm::vec3 collision_impulse_force = jLin * contactPoint / deltaTs;
//ClearForces();
AddForce(1.0f / this->GetMass() * collision_impulse_force);
//pool.at(otherI)->ClearForces();
other->AddForce(-(1.0f / other->GetMass() * collision_impulse_force));
}
}
When dealing with forces (as opposed to pressure, stress, or potentials), you will need to use a mass-spring-damper model. You can look into the discrete particle method for a technique that is used in many fields.
To learn for yourself, try to understand your state variables and your system. Take the acceleration you are seeing and divide the sphere's velocity (or velocity difference) by that acceleration. This will give you an idea of the time scale that the sphere needs to slow down on impact. Multiply by the velocity and you get a displacement, you can get an idea of how far that sphere will travel before slowing down.
Also, take a look at your time step. If the velocity multiplied by the time step allows the sphere to travel further than your threshold for detecting contact, then the sphere's will pass through each other. The same is true if your contact force doesn't increase as the sphere's begin to intersect.
If you want to take a deeper look at collision mechanics, look for topics under "dynamic behavior of materials". There you will see concepts for wave mechanics and elastic behavior. Most numerical methods transition to energy potential models rather than mass-spring-damper models, you can check out methods such as molecular dynamics, smoothed particle hydrodynamics, and peri-dynamics.
The main point is that these numerical methods operate on governing equations that don't allow particles (or your spheres) to pass through each other. The spring models, or potentials often have very (very) stiff responses when objects begin to intersect, as compared to the normal contact between objects.
A couple of points to take away:
Your integrator (i.e. time step) is likely too coarse or your collision detection is too fine, allowing the spheres to intersect.
Look up the discrete particle method (sometimes called the discrete element method), it is very popular and has many, many people using, studying, and publishing. You will find code, mass-spring-damper models, parameters, and other methods to help you reach your goal.
I am building an IOS game in Cocos2d - Chipmunk - Spritebuilder. I need to make a characters orbit around around a point, and I was having quite some difficulty in implementing orbits with real physics.
So far, I have tried two methods, one is creating a distance joint from the player to the planet, and then applying a 90 degree force on the player where an angle is created between the end of the distance joint and an imaginary line drawn at a 90 angle to it. He moves around crazily and this method is not working for me.
I then tried calculating 180 points on the circumference at a radius from the planet (which is the bounds of detecting and implementing its effects on the player) - and then in a scheduled update method [character.physicsbody applyForce:nextCircumferencePoint]; This does not work, as he does not follow the path exactly and is quite far from it. I am thinking that I need to also apply a gravitational force towards the planet which would cause him to circle it. Though I don't know how to calculate that force, apply it, or if it would even help.
A third method which would never work, but was used for testing was to set his position to the next circumference point. He does orbit, but any collision won't work (such as if a piece of space junk goes in his way.) He will simply be positioned right over any other object. This world great if you don't need collisions, are writing your own physics engine. This is not a polished way of doing things, so will avoid it.
Please correct anything I have already done and tell me how it would work, or shed light on other options and how to implement them.
Check out my answer here. It's for box2d, but you can do it with Chipmunk. If bodyA position will change, orbit will be same. You just need to change speed of body movement for your needs, just increase smoothness and slow down your update method.
I'm working on a Little Mobile Game with Cocos2D-X and Box2D.
The Point where I got stuck is the movement of a box2d-body (the main actor) and the according Sprite. Now I want to :
move this Body with a constant velocity along the x-axis, no matter if it's rolling (it's a circleshape) upwards or downwards
keep the body nearly sticking to the ground on which it's rolling
keep the Body and the according Sprite in the Center of the Screen.
What I tried :
in the update()- method I used body->SetLinearVelocity(b2Vec2(x,y)) to higher/lower values, if the Body was passing a constant value for his velocity
I used to set very high y-Values in body->SetLinearVelocity(b2Vec2(x,y))
First tried to use CCFollow with my playerSprite, which was also Scrolling along the y-axis, as i only need to scroll along the x-axis, so I decided to move the whole layer which is containing the ambience (platforms etc.) to the left of my Screen and my Player Body & Player sprite to the right of the Screen, adjusting the speed values to Keep the Player in the Center of the Screen.
Well...
...didn't work as i wanted it to, because each time i set the velocity manually (I also tried to use body->applyLinearImpulse(...) when the Body is moving upwards just as playing around with the value of velocityIterations in world->Step(...)) there's a small delay, which pushes the player Body more or less further of the Center of the Screen.
... didn't also work as I expected it to, because I needed to adjust the x-Values, when the Body was moving upwards to Keep it not getting slowed down, this made my Body even less sticky to the ground....
... CCFollow did a good Job, except that I didn't want to scroll along the y-axis also and it Forces the overgiven sprite to start in the Center of the Screen. Moving the whole Layer even brought no good results, I have tried a Long time to adjust values of the movement Speed of the layer and the Body to Keep it negating each other, that the player stays nearly in the Center of the Screen....
So my question is :
Does anyone of you have any Kind of new Approach for me to solve this cohesive bunch of Problems ?
Cheers,
Seb
To make it easy to control the body, the main figure to which the force is applied should be round. This should be done because of the processing mechanism of collisions. More details in this article: Why does the character get stuck?.
For processing collisions with the present contour of the body you can use the additional fixtures and sensors with an id or using category and mask bits. For of constant velocity is often better to use SetLinearVelocity, because even when using impulse velocity gets lost at sharp uphill or when jumping. If you want to use the implulse to change the position of the body, then you need to use the code for the type of this:
b2Vec2 vel = m_pB2Body->GetLinearVelocity();
float desiredVel = mMoveSpeed.x; //set there your speed x value
float velChange = desiredVel - vel.x;
float impulse = m_pB2Body->GetMass() * velChange;
m_pB2Body->ApplyLinearImpulse( b2Vec2(impulse, mMoveSpeed.y), m_pB2Body->GetWorldCenter());
This will allow maintain a constant speed most of the time. Do not forget that these functions must be called every time in your game loop. You can combine these forces, depending on the situation. For example, if the at the beginning you need to make a small acceleration, it is possible to use ApplyForce to the body, and when a desired speed is to use ApplyLinearImpulse or SetLinearVelocity. How correctly to use it is described here: Moving at constant speed
If you use world with the normal gravity(b2Vec2(0, -9.81)), then it should not be a problem.
I answer for this question here: Cocos2D-x - Issues when with using CCFollow. I use this code, it may be useful to you:
CCPoint position = ccpClamp(playerPosition, mLeftBounds, mRightBounds);
CCPoint diff = ccpSub(mWorldScrollBound, mGameNode->convertToWorldSpace(position));
CCPoint newGameNodePosition = ccpAdd(mGameNode->getPosition(), mGameNode->getParent()->convertToNodeSpace(diff));
mGameNode->setPosition(newGameNodePosition);
P.S. If you are new to box2d, it is advisable to read all the articles iforce2d(tuts), they are among the best in the network, as well as his Box2D Editor - RUBE. At one time they really helped me.
I do not know if this is possible but I have an idea:
Keep the circle at a fixed position and move the background relatively. For example, during the course of the game, if the circle has a velocity of 5 towards left then keep circle fixed and move screen with velocity 5 towards right. If circle has 5 velocity towards left and screen has 3 velocity towards right, then keep circle fixed and move screen with 8 velocity towards left and so on. This should allow you to fix the circle at the center of the screen.
Another method would be to translate the entire screen along with the ball. Make everything on the screen an object that can have a velocity. And the x-component of the velocity of the ball (circle) should be the velocity of all other objects. This way, whenever the circle moves, all the other objects will try and keep up with it.
I am developing third-person shooting game using Bullet and Ogre. When the character model collides with an object in the world, such as a power-up, the collision applies a force to the character and causes them to spin. How can I prevent the collision applying a force to the character?
I have set a method for btDynamicsWorld::setInternalTickCallback and so I know which bodies are colliding and the btManifoldPoint.
Note that I applyTorque to the body in order to rotate them smoothly so I cannot simply prevent rotation.
Thanks for your help.
I am unfamiliar with the physics engines you mentioned, but I know a thing or two about real physics...
Basically if you draw a free body diagram and arrows that represent the forces, you can determine the net effect. Or if you know the desired net effect, you can figure out where you need to add forces or remove forces.
You could add an equal and opposite force/torque at the time of impact. This would make the net forces on your object zero.
Or you could take the elements that are causing the forces and make them massless. Force = mass * acceleration. If the mass is zero and your physics engine is based on real world physics, then it shouldn't cause any net forces on collision.
Hope that helps.
So, I have a Triangle->AABB collision algorithm and I have it returning the triangle that the AABB collided with. I was hoping with the 3 vectors of the triangle and the direction/magnitude of the movement would let me determine a deflected vector so that when you run against the wall at an angle you move slower, depending on the angle of collision, but along side the wall. This would remove the sticky collision problem with only moving when there is not a collision. Any suggestions or references would be greatly appreciated! Thanks.
First, I would convert magnitude/direction to a vector (it's much more convenient).
Then (c++):
float towards=dot(velocity,norm); // velocity component into triangle
if(towards<0) // is moving into triangle
velocity-=towards*norm; // remove component
Then it can't move into the triangle. towards<0 might need to be reversed depending on your normal. It's also nice to have a spring force pushing it out.
Remove the component of the velocity along the normal of the triangle.
The idea is that you can represent the movement as the part that's moving "into" the triangle and the remainder (which will be in perpendicular directions). If you then just move with the remainder, you will no longer be getting any closer to the triangle by the movement (or further, but you shouldn't be detecting a collision in that case).
In pseudo-code:
// v := velocity vector of moving object
// p[3] := points that make up the triangle
triangle_normal = cross(p[2]-p[0], p[1]-p[0])
problematic_v = project(v, onto=triangle_normal)
safe_movement = v - problematic_movement
Note that this intentionally doesn't preserve the magnitude of the movement vector, as doing so would make you slide along a wall very quickly when running straight at it.
For more details and some nice pictures, see Pool Hall Lessons: Fast, Accurate Collision Detection Between Circles or Spheres at Gamasutra. You're not using spheres, but you are essentially doing a perfectly plastic (since you don't bounce) collision.