I'm working with Swift, SpriteKit and Xcode 6, I have a circle node on my screen and I can change the node's position with my finger, but I would like to implement a friction effect to this node, but I don't now how to do so, here's my code :
class PlayScene: SKScene
{
let firstCircle = SKSpriteNode(imageNamed: "Circle")
// theses 3 variables allows me to move the node according to my finger, but my finger don't have to touch the node
var departCircleLocation = CGPoint()
var departTouchLocation = CGPoint()
var currentTouchLocation = CGPoint()
override func didMoveToView(view: SKView)
{
addChild(firstCircle)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
{
for touch: AnyObject in touches
{
departTouchLocation = touch.locationInNode(self)
}
departCircleLocation = firstCircle.position
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent)
{
for touch: AnyObject in touches
{
currentTouchLocation = touch.locationInNode(self)
}
moveCircle()
}
func moveCircle()
{
firstCircle.position.x = departCircleLocation.x - departTouchLocation.x + currentTouchLocation.x
firstCircle.position.y = departCircleLocation.y - departTouchLocation.y + currentTouchLocation.y
}
}
I tried to put this into my code but it doesn't worked :
firstCircle.physicsBody = SKPhysicsBody(circleOfRadius: 7)
firstCircle.physicsBody?.affectedByGravity = false
firstCircle.physicsBody?.friction = 0.4
I don't want gravity because the game is viewed from above
Can someone explain to me how I could implement friction to this node ? I want for example that when I slide up with a certain speed and when I release my finger, the node continue to go up a little amount of time, but if I put my finger on the screen again, the friction stop immediately, for example:
If I put my finger 50pixels under the node, it will do nothing, but if I move my finger (which is 50pixels under the node) to 80pixels under the node, the node will move from 30 pixels down, and this works in any x and y directions, I can move the node without touching it, but it will follow the path if my finger, now if for example I move my finger from 30 pixels down really quickly and the I release my finger, the node will continue to go down due to the friction force, but my finger is no longer on the screen (the effect looks like when we scroll a website on an iphone, there is a little bit of friction when you release your finger due to the speed of your swipe) but I can't use UISwipeGesture because it only detects up, right, down and left directions, not every directions like I want. I hope that you can understand what I'm saying
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)
}
}