Вопрос SKCropNode

Потратил на это целый день. Я не нахожу это в 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, и я не хочу делать цикл for для 300 элементов. Поэтому я хочу иметь возможность устанавливать масштаб только для одного родителя.)

Я наконец решил попробовать что-то немного "хакерское". Этого я нигде не нашел в Интернете, поэтому мне интересно, не нахожусь ли я на территории "неопределенного поведения".

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

Я добавил еще один SKCropNode поверх моего оригинального SKCropNode. Теперь я только масштабирую SKCropNode2. Это работает. Однако сейчас у меня очень странное поведение. Мои кнопки SKShapeNode (полностью за окном) исчезают одна за другой, затем возвращаются и циклически повторяются. Кроме того, "узлы: 10, 60,0 кадр / с" в правом нижнем углу тоже исчезнут и вернутся в цикле. Под циклом я подразумеваю, что я щелкаю внутри окна масштабирования. Кажется, я столкнулся с ошибкой в ​​SpriteKit? Я установил zPosition кнопок на 20, намного выше, чем что-либо еще (5 и ниже). Я тоже поставил skview.ignoresSiblingOrder = false; Ценю любую помощь или совет о том, как этого добиться!

Изменить: В ответ на комментарии я не использовал симулятор. Я проверил это на своем iPad Pro и iPhone 6+, оба работают под управлением iOS 9.2. Ниже мой код, который компилирует и воспроизводит поведение. Я также вынул код масштабирования, но он все еще воспроизводим. Пожалуйста, попробуйте нажать на космический корабль (образец изображения Apple) примерно 30 раз, тогда вы начнете его видеть.

MainScene.h

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

MainScene.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

GameViewController.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. Спрайты кнопок исчезают после нескольких нажатий на космический корабль.

0 ответов

Другие вопросы по тегам