Friction in SpriteKit
Here's an example of how to move a sprite based on touch. This approach uses the velocity
property of the physics body to move the sprite, so it will interact appropriately with other physics bodies in the scene and be affected by damping, friction, etc.
First, define the scale and damping properties. The scale
controls the rate at which the circle moves toward the location of the touch. A larger value will move the circle at a faster rate. The damping
property is used to slow the sprite when the touch ends. A smaller value will slow the sprite at a faster rate.
let scale:CGFloat = 2.0
let damping:CGFloat = 0.98
var point:CGPoint?
Save the location when a touch begins. The sprite will move toward this location.
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if let touch = touches.anyObject() as UITouch? {
let location = touch.locationInNode(self)
point = location
}
}
Update the location when the touch moves
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
if let touch = touches.anyObject() as UITouch? {
let location = touch.locationInNode(self)
point = location
}
}
Reset the touch location when the touch ends
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
point = nil
}
Move the sprite toward the specified location
func moveNodeToPoint(sprite:SKSpriteNode, point:CGPoint) {
var dx:CGFloat = (point.x - sprite.position.x) * scale
var dy:CGFloat = (point.y - sprite.position.y) * scale
sprite.physicsBody?.velocity = CGVectorMake(dx, dy)
}
This is called before each frame is rendered. It calls the function that updates the location of the sprite if a touch is active, else it slows the sprite over time
override func update(currentTime: CFTimeInterval) {
if (point != nil) {
moveNodeToPoint(firstCircle, point: point!)
}
else {
// This will slow the circle over time when after the touch ends
let dx = firstCircle.physicsBody!.velocity.dx * damping
let dy = firstCircle.physicsBody!.velocity.dy * damping
firstCircle.physicsBody!.velocity = CGVectorMake(dx, dy)
}
}
Sprite Kit (swift) node friction - screen jumping
Mass and damping can be problematic for characters. Here's how I would set up your player dynamics for jumping:
physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.size.width, self.size.height))
physicsBody?.dynamic = true
physicsBody?.allowsRotation = false
physicsBody?.restitution = 0.0
physicsBody?.friction = 0.0
physicsBody?.angularDamping = 0.0
physicsBody?.linearDamping = 0.0
physicsBody?.affectedByGravity = true
When the player jumps, apply an impulse to the physicsBody
:
physicsBody?.applyImpulse(CGVector(dx: 0.0, dy: 50.0))
SpriteKit linearDamping - maximum?
The Apple doco is simply wrong.
Just to answer my own question, in iOS:
The actual documentation:
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.
is simply wrong.
A value of about 10 to 15 is typical when you want typical "strong damping" like in many physics scenes.
I very often use values of 2 or 3. And "10" is our value for "very thick honey".
SpriteKit node going through wall
I think in general you're probably expecting too much. SpriteKit is a game engine, designed to give qualitatively reasonable behavior for scenarios involving normal-ish sorts of physics. It's not a high-precision physics simulation, and when you push it into a region where it's got to do something extreme, it's probably going to fail.
In this case, you're expecting it to simulate a huge number of perfectly elastic collisions within a small amount of time and distance (many collisions per animation frame of the simulation as the heavy block mashes the light one into a tiny gap). It's going to find the first collision in the frame, figure the impulses to apply to the blocks, and then advance to the next frame, with the effect that the big block happily mashes into the space where the small one resides. All the subsequent collisions that would prevent that are being missed in search of 60 fps.
Related Topics
Switching a @State Property to a @Binding Property Interferes with Animation
API Violation - Multiple Calls Made to -[Xctestexpectation Fulfill]
Set Custom Uiview Frame in Uiviewrepresentable Swiftui
Make a Grid of Buttons of Same Width and Height in Swiftui
Swift - How to Resize a Uiview Based on Its Uilabel Size (That Is Inside)
Swiftui Classes That Conforms Observableobject Should Be Singleton
Any or a Trouble with Sequence of Functions
Xcode 8 Swift 3 Pitch-Altering Sounds
Color Keying Video with Gpuimage on a Scnplane in Arkit
What Is Darwinboolean Type in Swift
How to Cast [Int8] to [Uint8] in Swift
How to Access a Custom Function from Any File in the Same Swift Project