2013-10-10 5 views
8

내 현재 프로젝트에서 SpriteKit을 사용하여 다양한 시간에 독립적으로 크기를 조정할 필요가있는 여러 스프라이트가 있습니다. 문제는 노드의 크기를 조절할 때 물리 구조가 물리 구조에 맞지 않아 물리 구조가 엉망이된다는 것입니다.SKPhysicsBody 및 [SKNode setScale :]

CGSize objectSize = CGSizeMake(100, 100); 
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)]; 

SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:objectSize]; 
n1.position = CGPointMake(self.size.width/2, 2*self.size.height/3); 
n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectSize]; 
n1.physicsBody.affectedByGravity = YES; 
[self addChild:n1]; 

SKSpriteNode *n2 = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:objectSize]; 
n2.position = CGPointMake(self.size.width/2, self.size.height/3); 
n2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectSize]; 
n2.physicsBody.affectedByGravity = YES; 
[self addChild:n2]; 

[n1 setScale:0.5]; 

enter image description here

공지 사항 (축소) 파란색 스프라이트가 빨간 하나의 꼭대기에 앉아 어떻게하지만 당신은 여전히 ​​물리학 본문을 알 수 있습니다 : 여기이 질문의 목적을 위해 함께 넣어 작은 예입니다 내가 말한 차원이 있으며, 규모가 조정되지 않았습니다.

분명히 노드를 축소해도 physicsBody가 축소되지는 않습니다. 그래서 내 질문은 수동으로해야한다면, 어떻게해야합니까?

스케일링 할 때 몸체를 올바른 크기로 바꾸려고 시도했지만, 오래된 몸체에 관절 등이 있으면 정말 복잡해졌습니다. 기존 몸체를 확장 할 수 있다면 훨씬 간단 할 것입니다. 어쩐지.

+1

Box2D (SK에서 사용)의 몸체 크기 조정이 없습니다. – LearnCocos2D

답변

3

나는 똑같은 문제가 있었는데, 나는 그 스프라이트 키트에 버그가 있다고 생각한다.

조치를 사용하여 시도해보십시오. 전체 장면에서 작동합니다. 내 원래 question

[self runAction:[SKAction scaleTo:0.5 duration:0]]; 

는 물리학의 체형을 확장 할 수 없습니다

- (void) anthoertest 
{ 
    CGSize objectSize = CGSizeMake(100, 100); 
    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)]; 

    SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:objectSize]; 
    n1.position = CGPointMake(self.size.width/2, 2*self.size.height/3); 
    n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:n1.size]; 
    n1.physicsBody.affectedByGravity = YES; 
    [self addChild:n1]; 

    SKSpriteNode *n2 = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:objectSize]; 
    n2.position = CGPointMake(self.size.width/2, self.size.height/3); 
    n2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:n2.size]; 
    n2.physicsBody.affectedByGravity = YES; 
    [self addChild:n2]; 

    [self shrinkMe:n1]; 
} 

- (void) shrinkMe:(SKSpriteNode *) s 
{ 
    [s setScale:0.5]; 
    s.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:s.size]; 
} 

enter image description here

+0

실은 이전에 실을 실제로 읽었습니다. 그런 식으로 전체 장면을 스케일링하면 작동하지만, 스프라이트에서 같은 액션을 실행하면 동일한 버그가 발생합니다. 나는 그 노드들을 독립적으로 확장하려고 노력하고있다. – mprivat

+0

몸을 작은 것으로 바꾸면 잘됩니다. 그러나 그것은 시체 사이의 기존 관절에 영향을 미칩니다. 노드가 움직이면 조인트를 다시 만들면 제대로 작동하지 않습니다. 프레임 워크를 조정하기 전까지는 불가능한 문제 중 하나가 될 수 있습니다. – mprivat

+0

댓글에 동의합니다. SK 수정 – DogCoffee

5

발생하는 것이 이것이다. Sprite Kit이 내부적으로 사용하는 Box2D에는 절대 존재하지 않습니다.

내부 최적화 외에도 물리 물리층을 확장하면 광범위한 영향을 미칩니다. 예를 들어 신체의 모양을 위로 올리면 신체가 충돌로 붙을 수 있습니다. 관절이 어떻게 상호 작용하는지에 영향을 미칩니다. 그것은 신체의 밀도 또는 질량과 그에 따른 행동을 확실히 바꿀 것입니다.

물리 본문없이 스프라이트를 추가 한 SKNode를 사용할 수 있으며 지정된 크기의 본문이있는 추가 SKNode를 추가 할 수 있습니다. 그러면 스프라이트의 크기를 조절할 때 본문을 활성화 또는 비활성화 할 수 있습니다. 이 권한을 갖기 위해 플레이어는 충돌 셰이프가 전체 크기에서 절반 크기로 변하는 것을 스프라이트가 스케일링 전환을 움직이는 동안 통지하지 않습니다.

신체의 밀도와 크기에 따라 다른 속성을 계산해야합니다.

+0

좋은 아이디어지만, 유감스럽게도 내 유스 케이스에는 적용 할 수 없습니다. 다른 물체를 때릴 때 다른 방향으로 튀어 나와 작아지는 공 (SKShapeNode 몸체)이 있습니다. 단순히 몸을 비활성화하고 다른 몸체를 만들면 공은 속도와 다른 속성을 잃게됩니다. 작성 : > 주어진 크기의 몸체가있는 SKNode 추가 AFAIK 하나의 SKNode에 여러 개의 바디를 추가 할 수는 없습니까? – cocoapriest

+0

그는 당신이 스프라이트 노드에 자식으로 여러 SKNode를 추가 할 수 있고 각 자식 노드가 자체 물리 본문을 가질 수 있음을 의미한다고 생각합니다. 바디를 활성화/비활성화 할 수있는 한 가지 방법은 충돌 비트 마스크를 변경하는 것입니다. – peacetype

1

물리 본문은 SKNode의 CGPath에 따라 달라집니다. 당신은 어떻게 든 그것을 바꿔야 할 것입니다. 다음과 같은으로 CGPath을 확장하려고 할 수 있습니다

//scale up 

CGFloat scaleFactor = 1.1; 
CGAffineTransform scaleTransform = CGAffineTransformIdentity; 
scaleTransform = CGAffineTransformScale(scaleTransform, scaleFactor, scaleFactor); 
CGPathRef scaledPathRef = CGPathCreateCopyByTransformingPath(exampleNode.path, &scaleTransform); 
exampleNode.path = scaledPathRef; 

그러나이 SKScene 이미 노드의 모양을 업데이트하지 않습니다 점에 유의하십시오. CGPath 크기를 노드 크기를 조정하는 SKAction과 결합해야 할 수도 있습니다.

+0

그러나 PhysicsBody 현재 경로에 액세스 할 수 없습니다. – Martin

+0

신체가 의존하는 것은 당신이 그것을 어떻게 만들 었는지에 달렸지 만, CGPath는 반드시 (직접적으로) 만들 필요는 없으며, 그것이 생성 될 때 그 경로 (또는 다른 기하학)에 의존합니다. – bshirley

7

SKAction 또는 업데이트 루프 중 하나를 사용하면 적절한 축척으로 SKPhysicsBody을 새로 작성하여 개체에 적용 할 수 있습니다. 그러나 이렇게하면 속도가 떨어집니다.이 문제를 해결하려면 다음을 수행하십시오.

SKPhysicsBody *newBody = [SKPhysicsBody bodyWithRectangleOfSize:boxObject.size]; 
newBody.velocity = boxObject.physicsBody.velocity; 

boxObject.physicsBody = newBody; 
+0

충분하지 않습니다. angularVelocity와 다른 매개 변수가 관련되어 있습니다. 직접 사용할 수 없으므로 동일한 속성을 새로운 physicsBody에 전파 할 수 없습니다. –

2

이 답변을 읽는 다른 사용자의 경우 물리 물리학자가 SKNode로 확장 될 수 있다고 생각합니다. Xcode 8.2.1과 Swift 3.0.2를 사용하고 있습니다. 나는 새로운 프로젝트를 시작하고, 게임을 선택하고, 세부 사항을 채운다. 이 개 파일을 변경합니다

GameViewController.swift이

게임 Scene.swift이와 기능을합니다 (sceneDidLoad() 대체)을 (한 줄을 추가) : 물리학의 경계가 확장되고

override func sceneDidLoad() { 

    var found = false 
    self.enumerateChildNodes(withName: "testSprite") { 
     node, stop in 
      found = true 
    } 
    if !found { 
     let testSprite = SKSpriteNode(color: UIColor.white, size: CGSize(width: 200.0, height: 200.0)) 
     testSprite.physicsBody = SKPhysicsBody(polygonFrom: CGPath(rect: CGRect(x: -100.0, y: -100.0, width: 200.0, height: 200.0), transform: nil)) 
     testSprite.physicsBody?.affectedByGravity = false 
     testSprite.name = "testSprite" 
     let scaleAction = SKAction.repeatForever(SKAction.sequence([ 
      SKAction.scale(to: 2.0, duration: 2.0), 
      SKAction.scale(to: 0.5, duration: 2.0) 
      ])) 
     testSprite.run(scaleAction) 
     self.addChild(testSprite) 
    } 

} 

스프라이트 노드.

+2

나는 이것을 잘 알고 있습니다 : http://stackoverflow.com/a/33572073/3402095 – Whirlwind

+0

@Whirlwind는이 게시물보다 먼저 내 소식을 보았 더라면 좋겠다. –

0

나는이 동일한 문제를 겪었는데, 내가 한 모든 것은 현재의 내 업데이트 기능에서 내 물리 구조를 정의하는 것이 었습니다. 이 같은

당신을 위해 그것을 볼 수있는 작품은 :

override func sceneDidLoad() { 

SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:objectSize]; 
n1.position = CGPointMake(self.size.width/2, 2*self.size.height/3); 

} 
override func update(_ currentTime: TimeInterval) { 

n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectSize]; 
n1.physicsBody.affectedByGravity = YES; 

} 

유일한 문제는 당신이 당신의 물리 특성 updateCurrentTime의 모든 시간을 다시 정의해야한다는 것입니다. 변수를 같게 만드는 것처럼 이러한 속성 중 일부를 만들 수 있으므로 다른 곳에서 변수를 변경하여 속성을 변경할 수 있습니다. 다른 프레임을 재정의하면 다음 프레임이 호출 될 때까지만 작동합니다.

관련 문제