2016-07-15 7 views
1

이 질문을 단순화하라는 요청을 받았으므로 그게 내가하는 일입니다.SpriteKit joint : 본문 따르기

저는 SpriteKit의 물리 조인트 (및 아마도 신체 신체 속성)에 어려움을 겪고 있습니다. 모든 단일 하위 클래스와 많은 구성을 시도했지만 아무것도 작동하지 않는 솔기 또는 잘못된 것을하고 있습니다.

스네이크 게임을 개발 중입니다. 사용자는 앞으로 일정한 속도로 움직여야하는 뱀의 머리를 제어하고 사용자는 그것을 시계 방향 또는 반 시계 방향으로 돌릴 수 있습니다. 남은 뱀의 조각은 모두 머리를 따라야합니다. 머리가 몇 번이었던 것과 똑같은 경로를 따라야합니다.

저는이 게임에서 핀 조인트가 앵커 포인트가 정확히 요소 사이의 가운데에있는 대답이어야한다고 생각합니다.

결과는 완벽하지 않습니다. 구조가 완벽한 원을 만들어야하지만 그렇지 않습니다. 나는 코드를 붙이고, 현재의 효과를 보여주는 gif를 붙인다. 아무도 내 경험을 얻기에 충분한 경험이 있습니까? 신체 기관 및 관절의 어떤 특성이 원하는 효과를 위해 여기에 적용되어야합니까?

enter image description here

내 코드 :

class GameScene: SKScene { 
    private var elements = [SKNode]() 

    override func didMove(to view: SKView) { 
     physicsWorld.gravity = CGVector(dx: 0, dy: 0) 

     let dummyTurnNode = SKNode() 
     dummyTurnNode.position = CGPoint(x: size.width/2 - 50, y: size.height/2) 
     let dummyTurnBody = SKPhysicsBody(circleOfRadius: 1) 
     dummyTurnBody.isDynamic = false 
     dummyTurnNode.physicsBody = dummyTurnBody 
     addChild(dummyTurnNode) 

     for index in 0..<5 { 
      let element = SKShapeNode(circleOfRadius: 10) 
      let body = SKPhysicsBody(circleOfRadius: 10) 
      body.linearDamping = 0 
      // body.mass = 0 
      element.physicsBody = body 
      element.position = CGPoint(x: size.width/2, y: size.height/2 - 30 * CGFloat(index)) 
      elements.append(element) 
      addChild(element) 

      let label = SKLabelNode(text: "A") 
      label.fontSize = 10 
      label.fontName = "Helvetica-Bold" 
      element.addChild(label) 

      if index == 0 { 
       element.fillColor = UIColor.blue() 

       body.velocity = CGVector(dx: 0, dy: 30) 

       let dummyTurnJoint = SKPhysicsJointPin.joint(withBodyA: dummyTurnBody, bodyB: body, anchor: dummyTurnNode.position) 
       physicsWorld.add(dummyTurnJoint) 
      } else { 
       body.linearDamping = 1 

       element.fillColor = UIColor.red() 
       let previousElement = elements[index - 1] 
       let connectingJoint = SKPhysicsJointPin.joint(withBodyA: previousElement.physicsBody!, bodyB: body, anchor: CGPoint(x: size.width/2, y: size.height/2 - 30 * CGFloat(index) + CGFloat(15))) 
       physicsWorld.add(connectingJoint) 
      } 
     } 
    } 

    override func update(_ currentTime: TimeInterval) { 
     let head = elements.first!.physicsBody! 
     var velocity = head.velocity 
     velocity.normalize() 
     velocity.multiply(30) 
     head.velocity = velocity 
    } 
} 

extension CGVector { 
    var rwLength: CGFloat { 
     let xSq = pow(dx, 2) 
     let ySq = pow(dy, 2) 
     return sqrt(xSq + ySq) 
    } 

    mutating func normalize() { 
     dx /= rwLength 
     dy /= rwLength 
    } 

    mutating func multiply(_ factor: CGFloat) { 
     dx *= factor 
     dy *= factor 
    } 
} 
+0

사용하는 Swift 버전은 무엇입니까? –

+0

@AlessandroOrnano 3 –

답변

2

"모든 남아있는 뱀의 조각이 머리를 따라야합니다 - 그들은 머리를 몇 시간 전에이었다 정확히 같은 경로를 이동해야합니다."

Physics joint를 사용하면 자신이하는 일에 상관없이 차이가 발생할 수 있습니다. 완벽에 가깝더라도 정확한 경로를 지정하지 않고 후미에서 반올림 오류가 발생합니다.

모든 꼬리 부분이 동일하면 다른 접근법을 사용할 수도 있습니다. 이것은 혜성 꼬리에 대해 수행 한 작업입니다. 기본적으로 머리말 개체와 프레임 단위 이동 배열은 마지막 꼬리 개체를 항상 머리 개체와 같은 위치로 이동시키는 것입니다. head-object의 Z- 위치가 높으면 꼬리가 그 아래에 그려집니다.

테일을 유지해야하는 경우 헤드 위치 배열 (프레임 단위 경로)을 저장하여 접근 방식을 변경 한 다음 프레임 별 업데이트 호출에서 해당 경로를 따라 테일 개체를 배치하여 뱀.

아래에있는 내 코드 예를 들어, 참조 :이 당신이 머리 객체입니다 변수

: 당신의 머리의 init 함수에서

var tails = [SKEmitterNode]() 
var tailIndex = 0 

꼬리 객체 인스턴스화 : 아래

for _ in 0...MAX_TAIL_INDEX 
     { 
      if let remnant = SKEmitterNode(fileNamed: "FireTail.sks") 
      { 
       p.tails.append(remnant) 
      } 
     } 

전화 프레임 당 :

func drawTail() 
{ 
    if tails.count > tailIndex 
    { 
     tails[tailIndex].resetSimulation() 
     tails[tailIndex].particleSpeed = velocity()/4 
     tails[tailIndex].emissionAngle = zRotation - CGFloat(M_PI_2) // opposite direction 
     tails[tailIndex].position = position 
     tailIndex = tailIndex < MAX_TAIL_INDEX ? tailIndex + 1 : 0 
    } 
} 

장면 update() 함수에서 호출하면 결과 효과가 실제로 부드럽습니다.

+0

포인트와 헤드 회전으로 배열을 유지 한 다음 나중에 다른 노드에 적용하는 것도 가능하지만 가능하면 게임 프레임 워크의 이점을 최대한 활용하고 싶습니다. 이 솔루션은 또한 초기 위치에 대한 사전 계산을 필요로합니다. BTW : 반올림 오류가 정확하다고 생각합니다.나는 뱀 몸이 머리를 따라 가기를 원한다. 반올림 오류는 간신히 볼 수있다. –

관련 문제