【问题标题】:Is it possible to rotate a Node around an arbitrary point in SpriteKit?是否可以围绕 SpriteKit 中的任意点旋转节点?
【发布时间】:2013-09-27 07:26:17
【问题描述】:

有没有办法让 SpriteKit 中的节点围绕一个任意点旋转? 我现在可以操作节点的anchorPoint,但如果我要使用的旋转点位于节点之外,这还不够。

在 SpriteKit 中实现这种旋转的最佳方式是什么?

【问题讨论】:

  • 是否不能将锚点设置为大于 (1, 1) 的某个值以围绕该外点旋转?

标签: ios ios7 sprite-kit


【解决方案1】:

由于您要求最佳方式,这里有一个效果很好(最佳是主观的):

创建一个 SKNode 并将其位置设置为旋转中心。将应该围绕该中心旋转的节点作为子节点添加到中心节点。将子节点的位置设置为所需的偏移量(即半径,例如 x + 100)。更改中心节点的旋转属性以使子节点围绕中心点旋转。顺便说一句,cocos2d 也是如此。

【讨论】:

  • 谢谢!完成了这项工作。如果我忽略了针对该用例的现有 API 功能,我会称之为“最佳方式”。我同意,对于确切的用例,API 使用之外的所有内容都是主观的。但是,我喜欢这个解决方案并且它有效;)
【解决方案2】:

几周前我也试图解决这个问题,并没有实施锚点解决方案,因为我不想担心在说对象时移除锚点与另一个节点碰撞,应该离开它的轨道并弹开。

相反,我想出了两个解决方案,如果经过调整,这两个解决方案都可以工作。第一个花了很长时间来完善,但仍然不完美。它涉及计算围绕中心位置偏移设定半径的一定数量的点,然后如果某个物体在中心点的一定距离内进入,它将不断使用物理学将物体沿着“圆周”,它计算的点(见上文)。

用半径计算点有两种方法

第一个使用勾股定理,第二个最终使用三角学。 首先,您将 for 循环增加一定量,而它小于 361(度),并且对于循环的每次迭代,使用正弦和余弦计算一个点,该点在距中心点一定半径处具有该角度.

第二个使用勾股定理,其代码如下:

计算点数后,你应该在你的 didMoveToView 中创建一个预定的选择器[<object> scheduled selector...]; 或一个计时器,或者使用一个固定的更新方法,除了一个名为 int 的实例变量,它将保存您的对象将移动到的下一个位置的索引。每次调用计时器方法时,它都会使用您自己的或以下标有physicsMovement的代码将对象移动到计算点数组中的下一个点;您可以使用物理值,甚至 ttimer 的频率来获得不同的运动效果。只要确保你得到正确的索引。 另外,为了更真实,我使用了一种方法,该方法计算计算点数组中与对象最近的点,该方法仅在碰撞开始时调用。它也在下面标记为nearestPointGoTo。 如果您需要更多帮助,请在 cmets 中说出来。 继续黑客攻击!

我使用了第二个,这里是它的源代码:

【讨论】:

    【解决方案3】:

    代码本身没有通过

    第二点计算选项

    +(NSArray *)calculatePoints:(CGPoint)point withRadius:(CGFloat)radius numberOfPoints:    (int)numberOfPoints{ //or sprite kit equivalent thereof 
    //                [drawNode clear];
    
    
    NSMutableArray *points = [[NSMutableArray alloc]init];
    for (int j = 1; j < 5; j++) {
        float currentDistance;
        float myRadius = radius;
        float xAdd;
        float yAdd;
        int xMultiplier;
        int yMultiplier;
        CCColor *color = [[CCColor alloc]init]; //Will be used later to draw the position of the node, for debugging only 
        for (int i = 0; i < numberOfPoints; i += 1){ 
            //You also have to change the if (indextogoto == <value>) in the moveGumliMethod;
        float opposite = sqrtf( powf(myRadius, 2) - powf(currentDistance, 2) );
        currentDistance = i;
    
        switch (j) {
            case 1:
                xMultiplier = 1;
                yMultiplier = 1;
                xAdd = currentDistance;
                yAdd = opposite;
                color = [CCColor blueColor];
                break;
            case 2:
               xMultiplier = 1;
                yMultiplier = -1;
                xAdd = opposite;
                yAdd = currentDistance;
                color = [CCColor orangeColor];
                break;
            case 3:
                xMultiplier = -1;
                yMultiplier = -1;
                xAdd = currentDistance;
                yAdd = opposite;
                color = [CCColor redColor];
                break;
            case 4:
                xMultiplier = -1;
                yMultiplier = 1;
                xAdd = opposite;
                yAdd = currentDistance;
                color = [CCColor purpleColor];
                break;
            default:
                break;
        }
       int x = (CGFloat)(point.x + xAdd * xMultiplier); //or sprite kit equivalent thereof 
       int y = (CGFloat)(point.y + yAdd * yMultiplier); //or sprite kit equivalent thereof 
       CGPoint newPoint = CGPointMake((CGFloat)x,(CGFloat)y); //or sprite kit equivalent thereof 
    
    
       NSValue *pointWrapper = [NSValue valueWithCGPoint:newPoint]; //or sprite kit equivalent thereof 
       NSLog(@"Point is %@",pointWrapper);
      [points addObject:pointWrapper];
        }
    }
    return points;
    }
    

    计算到对象的最近点

    -(CGPoint)calculateNearestGumliPoint:(CGPoint)search point { // MY Character is named    Gumli
        float closestDist = 2000;
        CGPoint closestPt = ccp(0,0);
        for (NSValue *point in points) {
            CGPoint cgPoint = [point CGPointValue];
            float dist = sqrt(pow( (cgPoint.x - searchpoint.x), 2) + pow( (cgPoint.y - searchpoint.y), 2));
        if (dist < closestDist) {
            closestDist = dist;
            closestPt = cgPoint;
    
            }
        }
    
        return closestPt;
    }
    

    【讨论】:

      【解决方案4】:

      我认为完成这项工作的最佳方法是通过两个 SKNode 并将它们与 SKPhysicsJointPin 连接起来(请看下面的 pin 示例)

      我试图在我的门 (`SkScene) 上挂一个门牌 (SKSpriteNode),并且想在有人触摸它时在悬挂点上旋转

      我所做的是制作一个具有 HUGH 质量的 1x1 SKNode 并禁用它的重力效果。

      var doorSignAnchor = SKSpriteNode(color: myUIColor, size: CGSize(width: 1, height: 1))
      doorSignAnchor.physicsBody = SKPhysicsBody(rectangleOf: doorSignAnchor.frame.size)
      doorSignAnchor.physicsBody!.affectedByGravity = false // MAGIC PART
      doorSignAnchor.physicsBody!.mass = 9999999999 // MAGIC PART
      
      var doorSignNode = SKSpriteNode(imageNamed:"doorSign")
      doorSignNode.physicsBody = SKPhysicsBody(rectangleOf: doorSignNode.frame.size)
      

      并创建了一个SKPhysicsJointPin 来连接它们

      let joint = SKPhysicsJointPin.joint(
            withBodyA:  doorSignAnchor.physicsBody!,
            bodyB: doorSignNode.physicsBody!,
            anchor: doorSignAnchor.position)
      mySkScene.physicsWorld.add(joint)
      

      所以它会像实际的门牌一样移动,围绕任意点(doorSignAnchor)旋转

      参考:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多