касается* событий — SKScene и ViewController

У меня есть классический SKScene с некоторыми кнопками (все сделано программно) и ViewController для этой сцены. Где должны обрабатываться события касаний - в SKScene или во ViewController. Мне нужно переключиться на другие сцены и другие контроллеры представления при нажатии на разные кнопки с помощью push segue. Когда я обрабатываю события касания в контроллере представления, он возвращает мне nil для касания SKNode. Вот мой код в контроллере представления (сцена является его свойством):

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   UITouch *touch = [touches anyObject];
   CGPoint location = [touch locationInNode:self.scene];
   SKNode *node = [self.scene nodeAtPoint:location];
   if ([node.name  isEqual: @"campaign"]) {
       CampaignViewController *levelViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"CampaignScene"];
       [self.navigationController pushViewController:levelViewController animated:NO];
   }
}

Спасибо за объяснение.


person Baerdon    schedule 28.08.2014    source источник


Ответы (1)


Реализация сенсорных делегатов в ViewController не может дать вам узлы, поскольку ими управляет SKScene. Следовательно, чтобы иметь возможность использовать nodeAtPoint:, вам необходимо реализовать сенсорные делегаты в самом SKScene.

Теперь вам также нужен способ связи SKScene с UIViewController и передачи сообщений, которые будут запускать переходы или другие методы. Для этого вы можете использовать делегирование или NSNotificationCenter, реализация которых демонстрируется в этом ответе.

После того, как вы реализовали любой из вариантов ответа, ваш код должен выглядеть следующим образом:

//In ViewController.m

-(void) presentCampaignVieController
{
     CampaignViewController *levelViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"CampaignScene"];
     [self.navigationController pushViewController:levelViewController animated:NO];
}

//In SKScene.m (Using Delegation)

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   UITouch *touch = [touches anyObject];
   CGPoint location = [touch locationInNode:self.scene];
   SKNode *node = [self.scene nodeAtPoint:location];
   if ([node.name  isEqual: @"campaign"]) {
       [self.delegate presentCampaignVieController];
   }
}

Чтобы вызвать тот же метод в viewController с помощью NSNotificationCenter, вам сначала нужно добавить наблюдателя:

//ViewController.m, under viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(presentCampaignVieController) name:@"gotoCampaign" object:nil];

//In SKScene.m (Using NSNotificationCenter)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   UITouch *touch = [touches anyObject];
   CGPoint location = [touch locationInNode:self.scene];
   SKNode *node = [self.scene nodeAtPoint:location];
   if ([node.name  isEqual: @"campaign"])
   {
       [[NSNotificationCenter defaultCenter] postNotificationName:@"gotoCampaign" object:nil];
   }
}
person ZeMoon    schedule 28.08.2014