4

在这上面花了一整天。我在 iOS 文档或 SO 上找不到这个。

SKShapeNode*在我的应用程序中有一个类似于窗口的窗口,我添加了一个作为背景的背景SKSpriteNode,并且背景还有另外 10 个SKSpriteNode作为其子级。所以节点树是这样的:

SKScene -> window -> background -> (child1, ..., child10)

尺寸使得背景与窗口的大小相匹配,并且所有背景的孩子都适合背景。

我想在窗口内单击时进行缩放(让背景和 10 个孩子一起缩放)。我通过设置背景的 xScale 和 yScale 来实现这一点,并且孩子们继承了这个缩放比例。但我也不想溢出窗口的边界,所以我制作了一个 SKCropNode,并将背景添加为它的子节点。现在背景不会溢出:

SKScene -> window -> SKCropNode -> background -> (child1, ..., child10)

问题是,缩放时背景的孩子会溢出。这对我来说是违反直觉的。我尝试在线搜索并查看文档,“SKCropNode 是否裁剪其子代和所有后代”?由于答案似乎是否定的,我想将所有 10 个孩子的父母从背景更改为 SKCropNode:

SKScene -> window -> SKCropNode -> (background, child1, ..., child10)

现在我缩放 SKCropNode。这会缩放背景和所有孩子,但现在它再次溢出到窗外。(在游戏后期,孩子的数量可能会从 10 个增加到 300 个,我不想对 300 个项目做一个 for 循环。所以我希望能够只在一个父母身上设置比例。)

我终于决定尝试一些“hacky”的东西。这是我在网上找不到的任何地方,所以我想知道我是否处于“未定义行为”领域。

SKScene -> window -> SKCropNode1 -> SKCropNode2 -> (background, child1, ..., child10)

我在原来的 SKCropNode 之上添加了另一个 SKCropNode。现在,我只缩放 SKCropNode2。这行得通。但是,现在我的行​​为变得非常奇怪。我的 SKShapeNode 按钮(完全在窗口外)会一个一个消失,然后回来,像这样循环。此外,右下角的“nodes: 10, 60.0 fps”也会消失并在循环中返回。循环我的意思是我在窗口内单击缩放。看来我在 SpriteKit 中遇到了一个错误?我将按钮的 zPosition 设置为 20,比其他任何东西都高(5 及以下)。我还设置skview.ignoresSiblingOrder = false;了感谢有关如何完成此操作的任何帮助或建议!

编辑:在回复评论时,我没有使用模拟器。我在运行 iOS 9.2 的 iPad Pro 和 iPhone 6+ 上对此进行了测试。下面是我编译和重现行为的代码。我还取出了缩放代码,但它仍然可以重现。请尝试点击宇宙飞船(Apple 的示例图像)大约 30 次,然后您将开始看到它。

主场景.h

#import <UIKit/UIKit.h>
#import <SpriteKit/SpriteKit.h>
@interface MainScene : SKScene<NSStreamDelegate>
@property (strong, nonatomic) SKCropNode* skcrop;
@end

主场景.m

#import "MainScene.h"

@implementation MainScene
- (void)didMoveToView: (SKView*)view { }

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if ((int)[touches count] != 1) return;
    UITouch* touch = [touches anyObject];

    const CGPoint location = [touch locationInNode:self];

    { // without the 6 lines below, the disappearing-sprites behavior is gone
        SKShapeNode* newshape = [SKShapeNode shapeNodeWithRectOfSize:
            CGSizeMake(10.0, 10.0) cornerRadius:1.0];
        newshape.position = location;
        newshape.zPosition = 5;
        newshape.fillColor = [UIColor purpleColor];
        [self.skcrop addChild:newshape];
    }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { }

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { }

@end

游戏视图控制器.m:

#import "GameViewController.h"
#import "MainScene.h"
#import <CoreFoundation/CoreFoundation.h>

@implementation GameViewController

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeLeft
        | UIInterfaceOrientationMaskLandscapeRight;
}
- (void)viewDidLoad {
    [super viewDidLoad];

    // Configure SKView
    SKView* skview = (SKView*)self.view;
    skview.showsFPS = true;
    skview.showsNodeCount = true;
    skview.ignoresSiblingOrder = false;
    skview.multipleTouchEnabled = false;

    // Get Screen Size
    // IPad Pro  prints: screen size 768 1024
    // IPhone 6+ prints: screen size 375  667
    const int screenWidth = floor(0.5+skview.bounds.size.width);
    const int screenHeight = floor(0.5+skview.bounds.size.height);
    NSLog(@"screen size %d %d", screenWidth, screenHeight);
    const double width = (screenWidth < 375) ? 360 : 720;

    // Configure SKScene
    MainScene *skscene = [[MainScene alloc]
        initWithSize:CGSizeMake(screenWidth, screenHeight)];
    skscene.scaleMode = SKSceneScaleModeFill;
    skscene.backgroundColor = [UIColor whiteColor];
    [skview presentScene:skscene];

    // Set up window's crop mask
    const CGSize winSurface = CGSizeMake(width, width);
    const CGPoint winPosition = CGPointMake(
            CGRectGetMidX(skscene.frame), CGRectGetMidY(skscene.frame));
    NSLog(@"pos %f %f", winPosition.x, winPosition.y);

    SKSpriteNode* winMaskParent = [[SKSpriteNode alloc]
        initWithColor:[UIColor redColor] size:winSurface];
    [winMaskParent retain];
    winMaskParent.position = winPosition;
    SKCropNode* scnParent = [SKCropNode node];
    scnParent.zPosition = 1;
    scnParent.maskNode = winMaskParent;
    [skscene addChild:scnParent];

    SKSpriteNode* winMask = [[SKSpriteNode alloc]
        initWithColor:[UIColor blueColor] size:winSurface];
    [winMask retain];
    winMask.position = winPosition;
    SKCropNode* scn = [SKCropNode node];
    scn.zPosition = 1;
    scn.maskNode = winMask;
    [scnParent addChild:scn];

    // Add window sprite
    SKSpriteNode* win =
        [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship.png"];
    win.zPosition = 2;
    win.position = winPosition;
    [scn addChild:win];

    for (int i = 0; i < 5; ++i) {
        const double height = 30.0;
        const double width = 50.0;
        const double posY = screenHeight - (1+i)*100.0;
        const double posX = screenWidth - width - 10.0;

        SKShapeNode* button = [SKShapeNode shapeNodeWithRectOfSize:
            CGSizeMake(width, height) cornerRadius:1.0];
        button.position = CGPointMake(posX, posY);
        button.zPosition = 15;
        button.fillColor = [UIColor greenColor];
        button.lineWidth = 1.0;
        button.glowWidth = 0.0;
        [skscene addChild:button];
    }

    skscene.skcrop = scn;
    return;
}

@end

编辑 2:我删除了嵌套SKCropNode,因此只有 1 层 SKCropNode。在飞船上点击几下后,按钮精灵消失了。

4

0 回答 0