9

在我目前使用 SpriteKit 的项目中,我有一堆需要在不同时间独立放大和缩小的精灵。问题是当我缩放节点时,物理体不会随它缩放,所以它搞砸了物理。这是我为了这个问题而放在一起的一个小例子:

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];

在此处输入图像描述

请注意蓝色精灵(按比例缩小)如何位于红色精灵的顶部,但您可以看出它的物理体仍然具有我告诉它的尺寸,并且它没有缩放。

所以很明显,缩小节点并不会缩小physicsBody。所以我的问题是,如果我必须手动完成,我该怎么做?

我尝试在缩放时将身体换成合适尺寸的身体,但是如果旧身体有关节等,事情就会变得非常复杂......如果我能以某种方式缩放现有身体会简单得多。

4

6 回答 6

7

使用 anSKAction或 Update 循环,您可以创建一个SKPhysicsBody具有适当比例的新循环并将其应用于对象。但是,这样做会失去速度。要解决此问题,您可以执行以下操作:

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

boxObject.physicsBody = newBody;
于 2014-01-09T20:46:17.857 回答
5

物理体形无法缩放。绝对不在 Sprite Kit 内部使用的 Box2D 中。

除了内部优化之外,缩放物理体还会产生深远的影响。例如,放大身体的形状可能会使身体陷入碰撞。它会影响关节如何相互作用。它肯定会改变身体的密度或质量,从而改变它的行为。

您可以使用一个 SKNode,向其中添加没有物理主体的精灵,然后添加具有给定大小的主体的附加 SKNode。然后,您可以在开始缩放精灵时启用或禁用身体。如果时间正确,玩家将不会注意到碰撞形状只是从全尺寸变为半尺寸,而精灵会为缩放过渡设置动画。

不过,您必须根据身体的大小计算身体的密度以及可能的其他属性。

于 2013-10-16T23:00:35.307 回答
5

对于其他阅读此答案的人,我相信现在物理体与 SKNode 一起扩展。我正在使用 Xcode 8.2.1 和 Swift 3.0.2。我新建一个Project,选择Game,填写详细信息。更改2个文件:

GameViewController.swift(添加一行)

view.showsFPS = true
view.showsNodeCount = true

// add this to turn on Physics Edges    
view.showsPhysics = true

Game 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)
    }

}

物理边界随着精灵节点缩放。

于 2017-03-26T03:30:05.507 回答
3

我有完全相同的问题,我认为它是精灵套件中的错误。

尝试使用动作来缩放,这适用于整个场景。

[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];
}

在此处输入图像描述

于 2013-10-10T20:33:55.467 回答
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 结合起来。

于 2013-12-09T06:34:23.617 回答
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 中重新定义你的物理属性。您可以使其中一些属性(例如恢复原状)等于一个变量,这样您就可以通过在其他地方更改变量来更改其属性。在其他任何地方重新定义它只在调用下一帧之前有效。

于 2017-06-06T21:36:55.887 回答