I am still new to Sprite Kit but I think you can solve your problem with this function. It's easy and simple.
I would split your unfilled image in 3. unfilled_left_wing, unfilled_right_wing, unfilled_head.
Then I would move the image to the desired position. If the filled image intersects with the unfilled one, check how far it's from it's center, if it's smaller than 30 px apply it.
func touchDown(atPoint pos: CGPoint, atTime t: TimeInterval) {
// have to start inside the left_wing
guard left_wing.contains(pos) else {
return
}
}
func touchMoved(atPoint pos: CGPoint, atTime t: TimeInterval) {
// move wing to cursor position
left_wing.position = pos
}
func touchUp(atPoint pos : CGPoint, atTime t: TimeInterval) {
left_wing.position = pos
// check if it intersects with unfilled image
if (left_wing.frame.intersects(unfilled_left_wing.frame)
{
//check if it's close to center
if (fabs(left_wing.frame.origin.x - unfilled_left_wing.origin.x) < 30 && fabs(left_wing.frame.origin.y - unfilled_left_wing.origin.y) < 30)
{
left_wing.position = unfilled_left_wing.position
}
}
}
// overridden touch method to call our touch method for each touch
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { touchMoved(atPoint: t.location(in: self), atTime: t.timestamp) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { touchUp(atPoint: t.location(in: self), atTime: t.timestamp) }
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { touchDown(atPoint: t.location(in: self), atTime: t.timestamp) }
}
Based on this method, you can further optimise your code and save the images on NSArray for a dynamic check.