Пользовательский SKSpriteNode не обнаружен во время касания

В процессе обучения SpriteKit я пытаюсь создать небольшую приключенческую игру. Я создаю героя и добавляю его на сцену, а затем, во время touchesBegan:, я обнаруживаю, что прикосновение возникло у героя и соответственно предпримет действия.

Если я добавлю героя в качестве SKSpriteNode, сенсорный сигнал обнаружит его. Если я добавлю его в качестве подкласса SKSpriteNode, это не коснется! Разница в добавлении:

_heroNode = [SKSpriteNode spriteNodeWithImageNamed:@"hero.png"];

против

_heroNode = [[ADVHeroNode alloc] init];

Инициализация выглядит так:

- (id) init {
    if (self = [super init]) {

        self.name = @"heroNode";
        SKSpriteNode *image = [SKSpriteNode spriteNodeWithImageNamed:@"hero.png"];
        [self addChild:image];
    }
    return self;
}

Добавление героя в качестве подкласса SKSpriteNode работает в том смысле, что оно добавлено к сцене, но прикосновение его не обнаруживает. Мой touchesBegan: выглядит следующим образом:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */

    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:location];
    if (YES) NSLog(@"Node name where touch began: %@", node.name);

    //if hero touched set BOOL
    if ([node.name isEqualToString:@"heroNode"]) {
        if (YES) NSLog(@"touch in hero");
        touchedHero = YES;
    }
}

Удивительно, что этот код отлично работает при добавлении прямой вверх SKSpriteNode, а не в моем собственном подклассе. Любые предложения?

Ответ 1

Вот несколько примеров подкласса вашего героя

SKNode

Подкласс an SKNode этот метод требует, чтобы ваш node отслеживал касания, следовательно, свойство self.userInteractionEnabled.

@implementation HeroSprite

- (id) init {
    if (self = [super init]) {
        [self setUpHeroDetails];
        self.userInteractionEnabled = YES;
    }
    return self;
}

-(void) setUpHeroDetails
{
    self.name = @"heroNode";
    SKSpriteNode *heroImage = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
    [self addChild:heroImage];
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint locationA = [touch locationInNode:self];
    CGPoint locationB = [touch locationInNode:self.parent];
    NSLog(@"Hit at, %@ %@", NSStringFromCGPoint(locationA), NSStringFromCGPoint(locationB));
}

@end

SKSpriteNode

Другой "более простой" способ, если вы просто хотите подклассифицировать SKSpriteNode. Это будет работать по существу так же, как и вы (до того, как вы захотите подклассировать своего героя). Итак, ваши прикосновенияBegan, как установлено в вашем вопросе, будут работать.

@implementation HeroSprite

- (id) init {
    if (self = [super init]) {
        self = [HeroSprite spriteNodeWithImageNamed:@"Spaceship"];
        [self setUpHeroDetails];

    }
    return self;
}

-(void) setUpHeroDetails {
    self.name = @"heroNode";
}

@end

Ответ 2

Просто добавьте это в свой метод init.

self.userInteractionEnabled = YES;

По некоторым причинам это не включено по умолчанию при подклассе. По крайней мере, для меня это работало только при ручном включении.

Ответ 3

Обычно я проверяю затронутого родителя node, пока не найду класс, который я хочу контролировать. Вот фрагмент кода.

while (touchedNode.parent)
    {
        if ([touchedNode isKindOfClass:[GameObject class]])
            break;
        else
            touchedNode = (SKSpriteNode*)self.touchedNode.parent;
    }

Ответ 4

Он только что обнаружил касание только этого спрайта.

При создании объекта SKSpriteNode он будет управлять собой. Это означает, что когда на нем наступает прикосновение, это означает, что этот объект получает это касание, а не SKView.

Итак, если вы хотите обнаружить это прикосновение, вы должны написать этот код на этом объекте, а не на SKView. Если вы хотите что-то сделать в SKView, когда на SKSpriteNode появляется прикосновение, вы можете использовать делегат для этого.

Не стесняйтесь спрашивать больше, если вы не можете понять, что я отвечаю.

Ответ 5

Ваш ADVHeroNode является либо SkNode, либо SkSpriteNode без изображения. Ни один из них не будет иметь экстентов, они могут так сказать. Они не будут найдены nodeAtPoint: но это будет дочерний объект SKSpriteNode. Поскольку вы явно проверяете имя node, проверка не выполняется.

Вы можете присвоить изображению имя и проверить его, а затем обратиться к его родительскому элементу, чтобы получить экземпляр ADVHeronode. Или просто проверьте node.parent name.