我正在尝试制作一个动画角色,可以移动屏幕上的东西,而不会移动他的躯干。

如果他无法伸手,则他的手应朝该方向最大移动,然后通过其静态躯干的物理限制来抵消。

因此,在我的代码中,绿色矩形()移动到了我单击的位置,躯干也随之移动。
我希望能够使红色矩形( body )固定,并使绿色矩形“point”位于接触点位置。

我试图在场景和红色主体矩形之间应用固定的关节,但这似乎不起作用。

- (void) createSceneContent
{
    SKSpriteNode *body = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(100, 100)];
    body.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    [self addChild:body];

    body.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:body.size];
    body.physicsBody.affectedByGravity = NO;
    body.physicsBody.dynamic = YES;

    self.hand = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(150, 20)];
    self.hand.position = CGPointMake(body.position.x + body.size.width / 2 + self.hand.size.width / 2, body.position.y);
    [self addChild:self.hand];
    self.hand.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.hand.size];
    self.hand.physicsBody.dynamic = NO;

    self.scene.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];

    [self.physicsWorld addJoint:[SKPhysicsJointPin jointWithBodyA:body.physicsBody bodyB:self.hand.physicsBody anchor:CGPointMake(body.position.x + body.size.width / 2, body.position.y)]];

    [self.hand runAction:[SKAction moveByX:100 y:10 duration:0.1]];
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];

    CGPoint location = [touch locationInNode:self];
    [self.hand runAction:[SKAction moveTo:location duration:0.1]];
}

最佳答案

首先,如果您只希望手臂指向被触摸的位置,那么您实际上并不需要使用物理学。
只需将手臂节点的anchorPoint更改为肩部(将销钉放置在关节上)并围绕该点旋转(该点被保存在辅助肩膀节点中,以便以后轻松转换为其坐标)。您可以使用atan2f计算旋转角度。这是代码:

- (void) createSceneContent
{
    SKSpriteNode *body = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(100, 100)];
    body.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    [self addChild:body];

    self.hand = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(150, 20)];
    self.hand.position = CGPointMake(body.position.x + body.size.width*0.5, body.position.y);
    self.hand.anchorPoint = CGPointMake(0, 0.5);
    [self addChild:self.hand];

    SKNode *shoulderNode = [SKNode node];
    shoulderNode.position = self.hand.position;
    shoulderNode.name = @"shoulderNode";
    [self addChild:shoulderNode];

}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];

    CGPoint location = [touch locationInNode:self];
    CGPoint locationConv = [self convertPoint:location toNode:[self childNodeWithName:@"shoulderNode"]];

    self.hand.zRotation = (atan2f(locationConv.y, locationConv.x));
}

另一方面,如果您需要在此处使用物理物体,则使用SKAction来移动手臂可能不是一个好主意,并且您可能还希望设置body.physicsBody.dynamic = NO以使躯干保持静止。然后,确保正确添加销接头,并将其摩擦摩擦属性设置为较高的值,以减少悬空。使手指指向正确位置的方法之一是在更新方法中设置的速度矢量-只需使用转换后的位置坐标即可(此处它们相对于身体节点的中心)。完整的示例代码:
- (void) createSceneContent {
    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];

    body = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(100, 100)];
    body.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    [self addChild:body];

    body.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:body.size];
    body.physicsBody.dynamic = NO;
    body.physicsBody.affectedByGravity = YES;

    self.hand = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(20, 150)];
    // experiment with the anchorPoint for different results
    self.hand.anchorPoint = CGPointMake(0.5, 0);
    self.hand.position = CGPointMake(body.position.x, body.position.y);
    [self addChild:self.hand];

    self.hand.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.hand.size];
    self.hand.physicsBody.dynamic = YES;
    self.hand.physicsBody.affectedByGravity = NO;

    SKPhysicsJointPin *pinHand = [SKPhysicsJointPin jointWithBodyA:body.physicsBody bodyB:self.hand.physicsBody anchor:CGPointMake(body.position.x, body.position.y-5)];
    [self.physicsWorld addJoint:pinHand];
    // experiment with the friction torque value to achieve desired results
    pinHand.frictionTorque = 1.0;
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    location = [touch locationInNode:self];
}

-(void)update:(CFTimeInterval)currentTime {
    CGPoint locationConv = [self convertPoint:location toNode:body];
    // experiment with the multiplier (here: 10) for faster/slower movement
    self.hand.physicsBody.velocity = CGVectorMake(locationConv.x*10, locationConv.y*10);
}

希望有帮助!

关于ios - SpriteKit 关节,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21124203/

10-12 01:32