I have been unsuccesfully trying to implement the following in my iOS application for the last few days
(Source)
WHAT I WANT
When any of these circles are dragged by the user (whether red or grey), the circles that come in contact with the moving one should move . So if all the circles were in a line and the first was moved to the right , it would push the rest of the circles to the right.
WHAT I'VE TRIED SO FAR
1) intersects(_ rect2: CGRect)
method. I couldn't think of anything else other than creating a huge number of nested for loops with the intersects
method for every circle. Firstly , it looks very cluttery and Secondly the method is inefficient i.e. the method doesn't respond when the user drags too quickly .
2) UICollisionBehaviour
. After reading in another question , I discoverd that this somehow only works when UIDynamicAnimator
is responsible for moving Views on screen , NOT the user.(as with drag)
Finally I think , Sprite Kit is what I need , but I am not sure how or why to use it for such a tiny component of my app.
Any suggestion would be aspirin. Thanks!
I was able to perform the move against collision effect using Sprite kit
. It wasn't hard , as I had imagined.
This is however simply a proof of concept and doesn't address issues like being receptive to super fast movement.
If you are new to SpriteKit , go through this article from RayWenderlich.com . Ofcourse Apple's Programming guide to Sprite Kit is another amazing resource.
CODE
class GameScene : SKScene
var orangeBall : SKShapeNode!
var greenBall : SKShapeNode!
// Description : - Create two circular shapes here
// - Give them physics bodies
// - Add them
override func didMove(to view: SKView) {
orangeBall = SKShapeNode(circleOfRadius: 50 ) // Size of Circle
orangeBall.position = CGPoint(x: frame.midX, y: frame.midY) // Middle of Screen
orangeBall.glowWidth = 1.0
orangeBall.fillColor = SKColor.orange
orangeBall.physicsBody = SKPhysicsBody(circleOfRadius: 50 )
orangeBall.physicsBody?.affectedByGravity = false
orangeBall.physicsBody?.isDynamic = true
orangeBall.physicsBody?.allowsRotation = false
orangeBall.physicsBody?.restitution = 1
self.addChild(orangeBall)
greenBall = SKShapeNode(circleOfRadius: 50 ) // Size of Circle
greenBall.position = CGPoint(x: frame.midX + 70, y: frame.midY + 55.0 ) // Middle of Screen
greenBall.glowWidth = 1.0
greenBall.fillColor = SKColor.green
greenBall.physicsBody = SKPhysicsBody(circleOfRadius: 50)
greenBall.physicsBody?.affectedByGravity = false
greenBall.physicsBody?.isDynamic = true
greenBall.physicsBody?.density = greenBall.physicsBody!.density * 0.000001
greenBall.physicsBody?.allowsRotation = false
greenBall.physicsBody?.restitution = 1
self.addChild(greenBall)
}
Configuring touch
var fingerOnOrangeBall = false
var fingerOnGreenBall = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if orangeBall.contains(touches.first!.location(in: self)){ fingerOnOrangeBall = true }
if greenBall.contains( touches.first!.location(in: self)){ fingerOnGreenBall = true }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if fingerOnOrangeBall{
let touch = touches.first
var position = touch!.location(in: self.view)
position = self.convertPoint(fromView: position)
orangeBall.position = position
}
if fingerOnGreenBall{
let touch = touches.first
var position = touch!.location(in: self.view)
position = self.convertPoint(fromView: position)
greenBall.position = position
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if fingerOnOrangeBall { fingerOnOrangeBall = false }
if fingerOnGreenBall { fingerOnGreenBall = false }
}
}