2016-07-12 9 views
0

이미지에 구멍이있는 앱을 만들고 있습니다. 코드가 매우 커서 동일한 아이디어를 가진이 간단한 코드를 만들었습니다. 이 코드에는 이미 physicsBody가 설정된 이미지가 있습니다.SKNode에 구멍을 내고 PhysicsBody를 Swift에서 업데이트하십시오.

내가 원하는 것은 touchesBegan 함수에서 터치 된 위치에 투명 원형을 그리고 이미지 physicsBody (이미지에 구멍 만들기)를 업데이트하는 것입니다.

객관적인 C 및 UIImage에서 여러 코드를 발견했습니다. 누군가 Swift 및 SKSpriteNode를 도울 수 있습니까?

import SpriteKit 

class GameScene: SKScene { 
    override func didMoveToView(view: SKView) { 
     let texture = SKTexture(imageNamed: "Icon.png") 
     let node = SKSpriteNode(texture: texture) 
     node.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) 
     addChild(node) 

     node.physicsBody = SKPhysicsBody(rectangleOfSize: texture.size()) 
     node.physicsBody?.dynamic = false 

    } 

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 



    } 

} 
+0

피직스 바디는 노드의 시각적 모양에 영향을 미치지 않습니다. 노드의 시각적 구멍, 물리 구조의 물리적 구멍 또는 둘 다를 자르려고합니까? – andyvn22

+0

나는 작고 어쩌면 더 단순 할 것이라고 생각했지만 모두 –

답변

2

하나의 옵션은 마스크를 적용하고 이미지에 그 렌더링하고 SKSpriteNode's 질감을 업데이트하는 것입니다. 그런 다음 그 텍스처를 사용하여 물리 구조를 결정하십시오. 그러나이 과정은별로 효과가 없을 것입니다.

touchesBegan에서 예를 들어, 당신은 같은 것을 말할 수 : 우리가 노드를 얻을 첫 번째 터치 보면 여기

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     guard let touch = touches.first else { return } 
     if let node = self.nodeAtPoint(touch.locationInNode(self.scene!)) as? SKSpriteNode{ 

      let layer = self.layerFor(touch, node: node) // We'll use a helper function to create the layer 

      let image = self.snapShotLayer(layer) // Helper function to snapshot the layer 
      let texture = SKTexture(image:image) 
      node.texture = texture 

      // This will map the physical bounds of the body to alpha channel of texture. Hit in performance 
      node.physicsBody = SKPhysicsBody(texture: node.texture!, size: node.size) 
     } 
    } 

, 당신은 멀티 터치를 할 수 있도록 일반화 할 수 있지만, 우리는 다음과 레이어를 만들 투명도가있는 새 이미지를 만든 다음 텍스처를 만든 다음 노드의 물리 본문을 업데이트하십시오. 우리는 우리가 만들려는 마스크에 대한 CAShapeLayer을 만들

func layerFor(touch: UITouch, node: SKSpriteNode) -> CALayer 
    { 
     let touchDiameter:CGFloat = 20.0 

     let layer = CALayer() 
     layer.frame = CGRect(origin: CGPointZero, size: node.size) 
     layer.contents = node.texture?.CGImage() 

     let locationInNode = touch.locationInNode(node) 

     // Convert touch to layer coordinate system from node coordinates 
     let touchInLayerX = locationInNode.x + node.size.width * 0.5 - touchDiameter * 0.5 
     let touchInLayerY = node.size.height - (locationInNode.y + node.size.height * 0.5) - touchDiameter * 0.5 

     let circleRect = CGRect(x: touchInLayerX, y: touchInLayerY, width: touchDiameter, height: touchDiameter) 
     let circle = UIBezierPath(ovalInRect: circleRect) 

     let shapeLayer = CAShapeLayer() 
     shapeLayer.frame = CGRect(x: 0.0, y: 0.0, width: node.size.width, height: node.size.height) 
     let path = UIBezierPath(rect: shapeLayer.frame) 
     path.appendPath(circle) 
     shapeLayer.path = path.CGPath 
     shapeLayer.fillRule = kCAFillRuleEvenOdd 

     layer.mask = shapeLayer 
     return layer 
    } 

여기에 우리가 단지 CALayer의 내용을 현재 질감을 설정

레이어를 만드는 당신은 같은 것을 말할 수 있습니다. 대부분의 레이어에서 마스크가 불투명 해지기를 원하지만 투명한 원이 필요하므로 직사각형의 패스를 만든 다음 원을 추가합니다. fillRulekCAFillRuleEvenOdd으로 설정하여 서클 이외의 모든 것을 채 웁니다.

마지막으로 텍스처를 업데이트하는 데 사용할 수있는 UIImage로 레이어를 렌더링합니다.

func snapShotLayer(layer: CALayer) -> UIImage 
    { 
     UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, 0.0) 
     let context = UIGraphicsGetCurrentContext() 
     layer.renderInContext(context!) 
     let image = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return image 
    } 

어쩌면 누군가는이 달성의 더 성능이 좋은 방법을 제공 할 것입니다,하지만 난이 많은 경우 작동 것이라 생각합니다.

+0

beyowulf를 완벽하게 처리하려고 노력하고 있습니다. 그 일을 더 쉽게 할 수있는 방법이있을 것 같습니까? 그럼에도 불구하고 나는 다른 사람이든 심지어는 더 쉬운 길을 가는지 잠깐 동안 기다릴 것이다. 그렇지 않으면 나는 그 것을 정확하게 표시 할 것이다! 매우 감사! –