touches* 事件 - SKScene 与 ViewController

Posted

技术标签:

【中文标题】touches* 事件 - SKScene 与 ViewController【英文标题】:touches* events - SKScene vs. ViewController 【发布时间】:2014-08-28 09:45:32 【问题描述】:

我有一个经典的 SKScene,带有一些按钮(全部以编程方式制作)和用于该场景的 ViewController。应该在哪里处理触摸事件 - 在 SKScene 或 ViewController 中。通过 push segue 触摸不同的按钮时,我需要切换到另一个场景和另一个视图控制器。当我在视图控制器中处理触摸事件时,它会为触摸的 SKNode 返回 nil。这是我在视图控制器中的代码(场景是它的属性):

-(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];
   

感谢您的解释。

【问题讨论】:

【参考方案1】:

在 ViewController 中实现触摸代理不可能让您获得节点,因为管理它们的是 SKScene。因此,为了能够使用nodeAtPoint:,您需要在 SKScene 本身中实现触摸代理。

现在,您还需要一种方法让 SKScene 与 UIViewController 通信,并传递将触发 segue 或其他方法的消息。为此,您可以使用委托或 NSNotificationCenter,其实现在此 answer 中进行了演示。

实现答案中的任一选项后,您的代码应如下所示:

//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];
   

为了使用 NSNotificationCenter 在 vi​​ewController 中调用相同的方法,您首先必须添加一个观察者:

//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];
   

【讨论】:

以上是关于touches* 事件 - SKScene 与 ViewController的主要内容,如果未能解决你的问题,请参考以下文章

Touchend 事件无法与 touches 数组一起正常工作

swift2 SKScene 类的对象如何将大小作为参数?

什么是 touches cancelled 事件,它与 touches end 有什么不同

如何避免 Touches 取消事件?

UIWindow 子类:Touches 事件不会被触发

如何在 SKSpriteNode 中正确封装触摸事件处理并将数据传回 SKScene