Сложность с SKScene, делегирующей задачу Game Over на UIViewController

У меня есть два UIViewController. Пользователь начинает с UIViewController. Затем пользователь нажимает кнопку, чтобы начать игру. Таким образом, приложение последовательно переключается на другой контроллер представления, PlayViewController, который показывает игру с помощью SKView. А ActionScene — это подкласс SKScene, отвечающий за игровой процесс. Когда пользователь терпит неудачу, приложение отображает метку (SKLabelNode) и спрашивает, хочет ли он или она выйти из игры. Если пользователь коснется этой метки, игрок вернется к основному контроллеру представления (UIViewController) через PlayViewController. Поэтому я полагаю, что ActionScene должен делегировать эту задачу PlayViewController. Следующее исходит из ActionScene.

// ActionScene.h
#import <SpriteKit/SpriteKit.h>

@protocol actionDelegate;
@interface ActionScene : SKScene

@property (weak) id <actionDelegate> delegate;
@end

@protocol actionDelegate <NSObject>
@required

// Delegate
- (void)closeScene;
@end

// ActionScene.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    for (UITouch *touch in touches) {
    SKNode *n = [self nodeAtPoint:[touch locationInNode:self]];
        if (n != self && [n.name isEqual: @"doneLabel"]) { // It was else if before.  I've made a change.
            [[self childNodeWithName:@"doneLabel"] removeFromParent]; // The user chooses to end the game by tapping doneLabel (SKLabelNode)
            [self.delegate closeScene];
        }
    }
}

Что касается PlayViewController, он отвечает за представление ActionScene в SKView, а также за отправку пользователя обратно в UIViewController следующим образом.

// PlayViewController.h
#import "ActionScene.h"

@interface PlayViewController : UIViewController <actionDelegate>
@property (strong,nonatomic) ActionScene *actionScene;

@end

// PlayViewController.m
- (void)viewWillLayoutSubviews {
    SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:spriteView];

    SKScene *scene = [[ActionScene alloc] initWithSize:spriteView.frame.size];
    [self.actionScene setDelegate:self]; // Letting ActionScene delegate a task to itself
    [spriteView presentScene:scene];
}

- (void)closeScene {
    // It doesn't get a call from ActionScene
}

Поэтому, когда пользователь нажимает на метку «Готово», closeScene срабатывает. Но этот метод делегата никогда не вызывается. Я не разрабатывал приложение для iOS последние 9 месяцев. Но я думаю, что у меня есть правильная идея. Что я делаю неправильно? Пока что я прочитал эту тему, эта тема и другие.

Спасибо за помощь.

// Дополнительные пояснения //

  1. Все действия удаляются до того, как пользователь нажмет doneLabel.
  2. Игровое приложение войдет в touchBegan. Тем не менее, он пропустит строку [spriteView presentScene:scene].

person El Tomato    schedule 26.02.2014    source источник


Ответы (2)


Я реализовал ваш код, и все работает как шарм. Установите точку останова на строке:

[self.delegate closeScene];

чтобы увидеть, если он будет вызван.

person Rafa de King    schedule 26.02.2014
comment
Спасибо за уделенное время. Хм... Я установил точку останова внутри touchesBegan. Он пропустит эту строку. - person El Tomato; 27.02.2014
comment
Это означает, что что-то с вашим методом touchesBegan не так. Можете ли вы обновить свой вопрос с помощью полной реализации touchesBegan? - person Rafa de King; 27.02.2014
comment
Это все, что у меня есть в методе touchesBegain. - person El Tomato; 27.02.2014
comment
Ваш код вообще компилируется? В предоставленном вами коде есть оператор else if (сначала должен быть оператор if). Это не будет компилироваться. - person Rafa de King; 27.02.2014
comment
Спасибо. Я сделал изменение. - person El Tomato; 27.02.2014
comment
Что такое n в вашем методе touchesBegan? - person Rafa de King; 27.02.2014
comment
Упс. Извините... Я добавил строку для этого. - person El Tomato; 27.02.2014

Что касается этого поста, моя отчаянная мера сработала. Следующее изменение внесено в PlayViewController.m, чтобы вернуть пользователя в UIViewController.

- (void)viewWillLayoutSubviews {
    SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:spriteView];

    SKScene *scene = [[ActionScene alloc] initWithSize:spriteView.frame.size];
    [self.actionScene setDelegate:self]; // Letting ActionScene delegate a task to itself
    [spriteView presentScene:scene];
}

to

- (void)viewWillLayoutSubviews {        
    SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:spriteView];

    ActionScene *scene = [ActionScene sceneWithSize:spriteView.bounds.size];
    [scene setDelegate:self];
    [spriteView presentScene:scene];
}

Теперь я могу продолжать разработку игры в полном темпе, не беспокоясь ни о чем.

person El Tomato    schedule 27.02.2014