检测节点是不是被任何手指触摸
Posted
技术标签:
【中文标题】检测节点是不是被任何手指触摸【英文标题】:Detect if node is being touched by any finger检测节点是否被任何手指触摸 【发布时间】:2015-02-19 23:17:32 【问题描述】:所以我想在我的应用程序中调用一个方法,只要有一个 touchesEnd 并且节点 buttonX 没有被触摸。本来我只是打算用这段代码:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
NSArray *touchesArray = [touches allObjects];
UITouch *touch = (UITouch *)[touchesArray objectAtIndex:0];
CGPoint pointTouched = [touch locationInNode:self];
SKNode *nodeAtTouchPoint = [self nodeAtPoint:pointTouched];
if ([nodeAtPointTouched.name isEqualToString:buttonX.name])
// Call the method I want to call
问题在于,仅检测“当前手指”的touchesEnded
和“当前手指”是否未接触buttonX
。如果fingerA 触摸按钮,然后fingerB touchesStarted
和touchesEnded
(屏幕上的任何其他位置),即使fingerA 仍在触摸buttonX
,我想调用的方法也会被调用。
我真正的问题:如何在 touchesEnded
上为最初按下 buttonX
的手指调用我的方法,但在其他地方为手指调用 touchesEnded
时不调用该方法?
编辑:如果我可以创建一个 BOOL
方法来返回节点是否被触摸,并且它在对象中的“任何地方”都可以工作(不需要来自 touchesBegan
或 touchesEnd
的数据),我想这将帮助我解决问题。
【问题讨论】:
你的问题让我想起了数学课。如果所有 Gimp 都是 Gomp,但只有一些 Gomp 是 Gimp……您已经检查了节点的名称以进行触摸,因此您拥有正确的代码。你到底遇到了什么问题? 现在我已经设置为在 buttonX 上启动操作touchesBegin
,然后在 buttonX 上 touchesEnd
时停止操作。任何触摸都会调用touchesEnd
。问题是,如果 buttonX 上的 fingerA touchesBegin
,然后是其他地方的 fingerB touchesEnd
(有或没有第一个 touchesBegin
),即使在 buttonX 上的 fingerA 没有 touchesEnd
,它也会调用停止动作。我希望在 fingerA 按下 buttonX 时开始动作,并且仅在 fingerA 不再触摸 buttonX 时停止动作(通过touchesMoved
或 touchesEnd
),而不管其他手指同时做什么。
【参考方案1】:
不要使用 -nodeAtPoint:,而是尝试使用 -containsPoint:
if ([buttonX containtsPoint:pointTouched])
// Code here
【讨论】:
这不是问题的答案,这只是一种更有效的方法来检测是否点击了节点。 @Johny973 它应该可以解决代码存在的问题。 if 语句的内部在 touchesEnded 被调用时发生,但前提是所讨论的触摸在 buttonX 的框架内 - 它会忽略其他触摸。【参考方案2】:您需要跟踪按钮内的手指。每次从touchesBegan
到touchesEnded
都会为每个手指返回一个唯一的对象。所以跟踪它非常简单。
首先初始化buttonX
的userData
。
buttonX.userData = [[NSMutableDictionary alloc] init];
然后使用以下touchesBegan and touchesMoved
函数。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
NSArray *touchesArray = [touches allObjects];
for (UITouch *touch in touchesArray)
CGPoint pointTouched = [touch locationInNode:self];
SKNode *nodeAtTouchPoint = [self nodeAtPoint:pointTouched];
if ([nodeAtTouchPoint.name isEqualToString:buttonX.name])
buttonX.userData[@"touchPoint"] = touch;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
NSArray *touchesArray = [touches allObjects];
for (UITouch *touch in touchesArray)
CGPoint pointTouched = [touch locationInNode:self];
SKNode *nodeAtTouchPoint = [self nodeAtPoint:pointTouched];
if (buttonX.userData[@"touchPoint"] == touch)
if ([buttonX.name isEqualToString:nodeAtTouchPoint.name])
NSLog(@"clicked");
[buttonX.userData removeObjectForKey:@"touchPoint"];
【讨论】:
【参考方案3】:我可以通过两种方式了解您的情况。
第一个无需对代码进行太多更改的方法是在您的类中创建一个属性。
@property (nonatomic, strong)UITouch *buttonTouch;
并在您像示例一样遍历所有触摸时跟踪它
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
for (UITouch *touch in [touches allObjects])
CGPoint pointTouched = [touch locationInNode:self];
SKNode *nodeAtTouchPoint = [self nodeAtPoint:pointTouched];
if ([nodeAtTouchPoint.name isEqualToString:buttonX.name] && !self.buttonTouch)
self.buttonTouch = touch;
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
for (UITouch *touch in [touches allObjects])
CGPoint pointTouched = [touch locationInNode:self];
SKNode *nodeAtTouchPoint = [self nodeAtPoint:pointTouched];
if ([nodeAtTouchPoint.name isEqualToString:buttonX.name] && touch == self.buttonTouch)
self.buttonTouch = nil;
// Call the method I want to call
另一个选项更复杂一点是为您的按钮子类化 SKSpriteNode 并在其中处理触摸并使用委托。这就是我在项目中处理按钮的方式。
编辑
我将我的 ButtonSprite 类添加到 GitHub,以防您发现它有用。
https://github.com/Urthstripe29/ButtonSprite
【讨论】:
以上是关于检测节点是不是被任何手指触摸的主要内容,如果未能解决你的问题,请参考以下文章