在SpriteKit中,是否可以围绕任意点旋转节点?

20

有没有一种方法可以在SpriteKit中以任意点为中心旋转节点? 我知道我可以操纵节点的anchorPoint,但是如果我想使用的旋转点位于节点之外,那么这并不足够。

enter image description here

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


无法将锚点设置为大于(1,1)的某个值以围绕该外部点旋转吗? - rizzes
4个回答

29

既然你要求“最好”的方法,这里有一个效果很好的(当然,“最好”是主观的):

创建一个SKNode并将其位置设置为旋转中心。将应该围绕此中心旋转的节点添加为中心节点的子节点。将子节点的位置设置为所需的偏移量(例如半径,如x+100)。更改中心节点的旋转属性,使子节点围绕中心点旋转。cocos2d同样适用于此。


谢谢!完成得不错。如果我忽视了一个现有的API功能,正好适用于这个用例,我会称之为“最佳方式”。除了这个用例的API使用之外的一切,我同意,都是主观的。然而,我喜欢这个解决方案,它有效地运行着 ;) - Ben-G

0

代码本身没有经过

第二点计算选项

+(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;
}

0

我几周前也在尝试解决这个问题,但没有实现锚点解决方案,因为我不想担心当物体与另一个节点碰撞并应该离开其轨道并弹开时,需要删除锚点。

相反,我想出了两种解决方案,只要进行微调就可以工作。第一种花费了很长时间才完善,仍然不完美。它涉及计算以一定半径偏移的中心位置周围的某些点,然后如果某个对象到达中心点的一定距离,它将继续使用物理学将对象沿着圆形“周长”上的轨迹路径发送,这些路径是它计算出来的(见上文)。

有两种计算半径的方法

第一种使用勾股定理,第二种最终使用三角函数。在第一种方法中,您通过一定量递增for循环,而它小于361度,并且对于循环的每次迭代,使用正弦和余弦计算从中心点开始的具有该角度的点,距离中心点一定半径。

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

在计算完点数之后,您应该创建一个定时器选择器[<object> scheduled selector...];或者在didMoveToView中使用一个定时器,或者使用一个固定的更新方法,另外还需要一个实例变量int来保存下一个位置的索引,以便您的对象移动到下一个点。每次调用定时器方法时,它将使用您自己的物理运动代码或下面标记为physicsMovement的代码将对象移动到计算点数组中的下一个点;您可以尝试不同的物理值和定时器频率以获得不同的运动效果,但一定要确保索引正确。
此外,为了更加真实,我使用了一个方法来计算计算点数组中距离对象最近的点,在碰撞开始时仅调用一次。它也在下面标记为nearestPointGoTo。
如果您需要更多帮助,请在评论中提出。
继续Hack吧!
我使用了第二个,这是它的源代码:

0

我认为使这个工作的最佳方式是通过两个SKNode并使用SKPhysicsJointPin将它们连接起来(请参考下面的pin示例)

enter image description here

我试图在我的门(SkScene)上挂一个门牌(SKSpriteNode),并希望当有人触摸它时能够旋转

我所做的是创建一个质量巨大且禁用重力效果的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)旋转。

参考:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接