Reputation: 145
I have a classic SKScene with some buttons (all made programmatically) and ViewController for that scene. Where should be touches events handled - in SKScene, or in ViewController. I need to switch to another scenes and another view controllers when touching different buttons via push segue. When I handle touches events in view controller, it returns me nil for SKNode touched. Here is my code in view controller (scene is its property):
-(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];
}
}
Thank you for explaining.
Upvotes: 1
Views: 642
Reputation: 20274
Implementing touch delegates in the ViewController cannot possibly get you the nodes, as it is the SKScene which manages them. Hence, to be able to use nodeAtPoint:
, you need to implement the touch delegates in the SKScene itself.
Now, you also need a way for the SKScene to communicate with the UIViewController, and pass messages which will trigger segues or other methods. For this, you can either use Delegation or NSNotificationCenter, the implementation of which is demonstrated in this answer.
After you have implemented either of the options from the answer, your code should look like the following:
//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];
}
}
In order to call the same method in the viewController using NSNotificationCenter, you will first have to add an observer:
//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];
}
}
Upvotes: 4