设置永久性SKSpritenode图像方向

时间:2014-11-07 20:08:18

标签: ios sprite-kit skspritenode skphysicsbody

嗨我有一堆圆形SKSpriteNodes带有圆形物理身体。现在,当这些球滚下路径时,我希望这些SKSpritenodes图像中的一些即使在滚动时也能保持直立。所以想想一个向上的箭头。当球开始滚动时,箭头旋转成圆形。但是对于一些球来说,即使球滚动,箭头仍然指向上方。这是最好的方法吗?

修改

所以给出了答案但是从测试结果证明它不是正确的答案。不允许球旋转会影响它沿着路径滚动的方式。所以我想我想要的是旋转,但是图像总是向用户显示,就像它不旋转一样。感谢。

3 个答案:

答案 0 :(得分:5)

这看起来像是 Superm SKConstraint的工作。在物理模拟在每个帧上运行之后,对约束进行评估和应用,因此您可以将它们用于使节点指向某个方向的任务,而不管物理学对它做什么。为此,您需要zRotation约束。

但是还有更多的东西。如果你在球上设置了零旋转约束:

// Swift
let constraint = SKConstraint.zRotation(SKRange(constantValue: 0))
ball.constraints = [constraint]

你会发现SpriteKit会因为约束而重置物理体对每一帧的变换,所以它只会像它的滚动一样。可能不是你想要的。 (为了更好地了解这里发生的事情,尝试在没有重力的世界中为矩形物理体添加零旋转约束,对其施加角度冲动,并观察它在视图中旋转showsPhysics打开了。你会看到精灵和它的物理体失去同步并摇晃一下 - 可能是由于物理引擎和约束引擎对抗累积的舍入错误。)< / p>

相反,您可以在0x141E的答案中做一些事情,但是使用约束来减少代码(并且更有效地运行):

  1. 给球节点一个圆形的物理体。 (并且可能没有纹理,如果你想要球的唯一艺术是非旋转精灵。)
  2. 将箭头节点添加为球节点的子节点。 (它不需要自己的物理机构。)
  3. 对箭头设置零旋转约束。
  4. 等等,这不起作用 - 我告诉箭头不要旋转,但它还在旋转?!请记住,子节点相对于其父节点定位(并旋转和缩放)。所以箭头不是相对于球旋转,而是球旋转。别担心,您仍然可以通过约束来解决这个问题:

    1. 告诉约束相对于包含球的节点(可能是场景)进行操作。
    2. 现在约束将保持箭头到位,同时允许球旋转,但物理模拟需要它。

      这里有一些测试代码来说明:

      // Step 1: A rectangular spinner so we can see the rotation 
      //         more easily than with a ball
      let spinner = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 300, height: 20))
      spinner.position.x = scene.frame.midX
      spinner.position.y = scene.frame.midY
      spinner.physicsBody = SKPhysicsBody(rectangleOfSize: spinner.size)
      scene.addChild(spinner)
      spinner.physicsBody?.applyAngularImpulse(0.1) // wheeeeee
      
      // Step 2: Make the arrow a child of the spinner
      let arrow = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 20, height: 50))
      spinner.addChild(arrow)
      
      // Step 3: Constrain the arrow's rotation...
      let constraint = SKConstraint.zRotation(SKRange(constantValue: 0))
      arrow.constraints = [constraint]
      
      // Step 4: ...relative to the scene, instead of to its parent
      constraint.referenceNode = scene
      

答案 1 :(得分:1)

以下是使用物理主体和箭头创建球的两种方法:

  1. 添加箭头作为球的孩子
  2. 将球和箭头直接添加到场景中
  3. 以下是将上述内容添加到SpriteKit模拟时会发生的情况:

    1. 球旋转时箭头将旋转
    2. 箭头和球都将独立移动/旋转
    3. 如果您希望箭头随球一起旋转,请选择选项1.如果您希望箭头保持固定,请选择选项2.如果选择选项2,则需要调整箭头的旋转以确保它指向上方。这是一个如何做到这一点的例子。

      -(void)didMoveToView:(SKView *)view {
          self.scaleMode = SKSceneScaleModeResizeFill;
      
          /* Create an edge around the scene */
          self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:view.frame];
      
          // Show outline of all physics bodies
          self.view.showsPhysics = YES;
      
          CGFloat radius = 16;
      
          SKNode *balls = [SKNode node];
          balls.name = @"balls";
          [self addChild:balls];
      
          // Create 5 balls with stationary arrows
          for (int i = 0;i<5;i++) {
              // Create a shape node with a circular physics body. If you are targeting iOS 8,
              // you have other options to create circular node. You can also create an SKSpriteNode
              // with a texture
              SKShapeNode *ball = [SKShapeNode node];
              // Create a CGPath that is centered
              ball.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-radius,-radius,radius*2,radius*2)].CGPath;
              ball.fillColor = [SKColor whiteColor];
              ball.position = CGPointMake(100, 100+i*radius*2);
              ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:radius];
      
              [balls addChild:ball];
      
              // Create an arrow node
              CGSize size = CGSizeMake(2, radius*2);
              SKSpriteNode *arrow = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:size];
              arrow.name = @"arrow";
              arrow.position = CGPointZero;
      
              [ball addChild:arrow];
              // Apply angular impulse to the ball so it spins when it hits the floor
              [ball.physicsBody applyAngularImpulse:-1];
          }
      }
      
      - (void) didSimulatePhysics
      {
          SKNode *balls = [self childNodeWithName:@"balls"];
          for (SKNode *ball in balls.children) {
              SKNode *arrow = [ball childNodeWithName:@"arrow"];
              arrow.zRotation = -ball.zRotation;
          }
      }
      

答案 2 :(得分:0)

sprite.physicsBody.allowsRotation = NO;

allowRotation属性应该准确控制您的要求。