Swift 2: Stop movement after applyImpulse - swift

How can I stop a sprite after it has been applied an impulse like this:
player.physicsBody!.applyImpulse(CGVectorMake(50, 0))
And is it possible to make the movement decrease over a time period? (2 seconds)

In order to stop the movement of the physicsBody, you can utilise the 'velocity' variable like so:
//this will reset the x, y based velocity to a halt/stop
player.physicsBody?.velocity = CGVectorMake(0, 0)
//if you would also like to stop any rotation that may be present
player.physicsBody?.angularVelocity = 0
To address your second question you should look into 'linearDamping' to affect velocity and 'angularDamping' to affect angularVelocity (rotation). These physicsBody parameters allow you to slow the velocity over time once an impulse is applied (similar to friction).
//These values should be set when creating the physicsBody.
//should experiment with these values to get the desired effect.
player.physicsBody?.linearDamping = 1.10
player.physicsBody?.angularDamping = 0.25

Related

Rejecting gravity effect SceneKit

This's my first project using SpriteKit.
I'm using these nodes
let physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
physicsBody.isAffectedByGravity = true
physicsBody.mass = 1
geometryNode.physicsBody = physicsBody
let force = SCNVector3(0, 9.8, 0)
let position = SCNVector3(0, 0, 0)
geometryNode.physicsBody?.applyForce(force, at: position, asImpulse: false)
scnScene.rootNode.addChildNode(geometryNode)
My goal is to see the object stuck in the centre of my scene.
As read within SceneKit's documentation, SceneKit uses SI so Mass 1 means 1 kg.
Gravity force applied to the mass centre of this object is -9.8N ( 1kg * 9.8 m/s^2 ) on the Y-axis.
Applying 9.8N to the mass centre should bring the resultant force equal to 0 so no one force is applied and the object should be stuck in the centre but in my project, it falls down.
Where am I wrong?
It looks to me like you apply the force when you create the node.
From the developer docs on applyForce:
Discussion This method accelerates the body without imparting any
angular acceleration to it. The acceleration is applied for a single
simulation step (one frame).
I think you need to move your applyForce call to your update method in the scene. so that the force is constantly applied.

Stop an SKPhysicsBody mid-motion

If an SKSpriteNode has had an impulse applied to its SKPhysicsBody so that it now has momentum, is there a way I can get it to immediately stop moving? Applying an equal and opposite impulse would probably work in theory, but I would like to know if there is a simpler way. Thanks (:
You can set its velocity to zero:
body.velocity = CGVectorMake(0, 0)
You might also want to set its angular velocity to zero:
body.angularVelocity = 0
And if you want it to become immune to forces and impulses, turn off dynamic:
body.dynamic = false

Add a constant force in Unity2D

I have a ball and I want to move it on the X axis, so, in the FixedUpdate method I added a force:
rigidbody2D.AddForce(Vector2.right * speed);
The ball's speed increases because of this code I wrote. I want to make this force to be constant, so the ball's speed not to increase. How can I do that? Thanks a lot!
Applying a constant force will accelerate the object, because that's how real physics work:
Force = mass * acceleration
In your case, the resulting acceleration is:
Acceleration = Force / mass
If you want to set the object speed to be constant, you should modify the rigidBody's velocity:
http://docs.unity3d.com/ScriptReference/Rigidbody2D-velocity.html
Something like this:
rigidbody2D.velocity = new Vector2(speed, 0);

Giving a physicsBody a constant force

I have a ball bouncing up and down. I've accomplished this by setting it's physics body up like this:
linearDamping = 0
friction = 0
restitution = 1
And then just applyForce(CGVectorMake(0, 10)) in the setup call. The ball is now bouncing up and down, up and down with not interruption.
Now I want to add player control. The player can move the ball sideways. I could do this by just setting the balls velocity when the controls are pressed. BUT by doing that I lose all the stuff the physics engine gives me.
Here's a short snippet of code I have right now:
override func update(currentTime: CFTimeInterval) {
/* Apply damping only in x */
if !movingLeft && !movingRight {
let dx = ball!.physicsBody!.velocity.dx * xAlpha
let dy = ball!.physicsBody!.velocity.dy
ball!.physicsBody?.velocity = CGVectorMake(dx, dy)
}
if movingRight {
ball!.physicsBody?.applyImpulse(CGVectorMake(ballVelocityX, 0))
}
if movingLeft {
ball!.physicsBody?.applyImpulse(CGVectorMake(-ballVelocityX, 0))
}
}
The problem, as you might imagine, is that applying impulse upon impulse on each frame like this makes the ball go superfast, which is not what I want, when the controls are held down. But if I apply the force only on keyDown the ball will stop moving in that direction once the ball hits something. And also the keyDown event works wonky on OS X (because of key repeat settings).
So what I want to do is apply an impulse in the update function in a way that makes the force of the ball not exceed my limit but also not go away completely if the ball hits something.

accelerated addforce for rigidbody

I need a method for accelerating the addforce method to the object.
Force Result feels too slow and I want it to be applied faster and for the final result time lapse shorten.
void FixedUpdate()
{....
Vector3 v_x = new Vector3(keyb_x, 0, 0);
Vector3 force_ = v_x * kspeed * Time.deltaTime;
float speed = rigidbody.velocity.magnitude;
rigidbody.AddForce(force_, ForceMode.Impulse);
....}
Raising gravity from -9 to -19 or more in the y direction gives the expected result, but all other objects are affected. I want only it to apply to a specific object only.
All gravity does is apply a downward force to all of your rigidbodies every physics update. For 2D unity physics you could use rigidbody2D.GravityScale, which scales gravity's effect on a per-rigidbody basis, but for 3D rigid bodies you should apply a constant force equal to the change in gravity you want for your object
e.g.
//adds a downforce of 10 per second
rigidbody.AddForce(Vector3.down * 10f * Time.fixedDeltaTime);
You'll want to put this in your fixed update function.
object_Rigid2D.gravityScale += gravity_Increase * Time.deltaTime;
I found an easy way to reach this. Consider you have an object which you move with addForce (I use impulse, other modes probably work too) by 1 unit (so vector is something like (1, 0, 0)) and object mass and drag are both 1, so the object moves properly but you want to make it quicker/slower. In that case you need to reduce it's mass and increase drag to make it quick and vice versa. For example you can make it quicker if you set mass to 2 and drag for 0.5 or slower if mass is 0.25 and drag is 4. Only rule is that drag * mass = 1.