我试图让玩家将我游戏中的对象从屏幕的一个部分拖到另一个部分。问题是,要拖动的对象下面也有需要接收触摸的层。通常我只会吞下触摸,但据我所知,这只能在ccTouchBegan
. 在调用after 之前,我无法判断用户是否正在尝试拖动对象ccTouchMoved
,所以我需要一种方法来明确地吞下(或以其他方式防止下层)在我确定它是触摸后接收触摸我'我对(内ccTouchMoved
)感兴趣。
1 回答
我遇到了几乎同样的问题,但我不知道我的解决方案是否适合这里。主要思想是应该被拖动的对象是同一个 CCNode 层次结构中的子对象,下面的项目。解决方案在于父母禁用孩子的触摸事件,然后拦截这些事件。如果某个对象被拖动,则父级将所有事件发送给它,在另一种情况下,父级将处理事件本身。
让我试着表明我的意思。为可以吞下触摸的项目创建协议 ccTouchMoved:
@protocol SwallowingOnTouchMovedNode
{
-(BOOL) ccTouchMoved:(UITouch*)touch; // not full signature for simpleness (UIEvent should be also here)
}
然后创建图层,它将手动处理其子级的触摸:
@interface TouchHandler : CCLayer
{
NSMutableArray *draggableChildren_, nonDraggableChildren_, *claimedChildren_;
BOOL isDragging_;
}
@implementation TouchHandler
-(id) init
{
...
self.isTouchEnabled = YES;
draggableChildren_ = [[NSMutableArray alloc] init];
nonDraggableChildren_ = [[NSMutableArray alloc] init];
claimedChildren = [[NSMutableArray alloc] init];
...
}
创建两种方法来TouchHandler
添加两种类型的孩子 - 可以拖动的孩子和其他孩子。该方法将禁用对子级的触摸,因此父级将手动处理它们。
-(void) addChild:(CCNode*)child shouldBeDragged:(BOOL)shouldBeDragged
{
NSMutableArray *arrayToAddChild = shouldBeDragged ? draggableChildren_ : nonDraggableChildren_;
[arrayToAddChild addObject:child];
// note, that if the child has its own children, you will need to
// set isTouchEnabled on all of them, as adding all children to array recursively
if ([child respondsToSelector:@selector(setIsTouchEnabled:)]) ((CCLayer*)child).isTouchEnabled = NO;
[self addChild:child]; // maybe you need to call -addChild:zOrder:tag: here
}
然后像这样覆盖触摸句柄:
-(BOOL) ccTouchBegan:(UITouch*)touch
{
for (CCNode *child in draggableChildren)
{
if ([child ccTouchBegin:touch])
{
// this behavior looks like the one in CCTouchDispatcher -
// we claim children which return YES for touchBegin
[claimedChildren addObject:child];
}
}
}
-(void) ccTouchMoved:(UITouch*)touch
{
for (CCNode *child in claimedChildren)
{
if ([(id<SwallowingOnTouchMovedNode>)child ccTouchMoved:touch])
{
isDragging_ = YES;
}
}
// if no one swallowed touches
if (!isDragging_)
{
for (CCNode *child in nonDraggableChildren)
{
// we did not called ccTouchBegan earlier for these items,
// so for consistency we need to call it now
if ([child ccTouchBegin:touch])
{
[child ccTouchMoved:touch];
[claimedChildren addObject:child];
}
}
}
}
-(void) ccTouchEnded:(UITouch*)touch
{
isDragging_ = NO;
for (CCNode *child in claimedChildren)
{
[child ccTouchEnded];
}
}
不要忘记执行-ccTouchCancelled
。这段代码非常具体,因此您可能需要进行一些更改,但我希望我已经解释了我的想法。一般来说,它TouchHandler
甚至可能不是这样CCLayer
工作的,只需将其添加为接收触摸的目标委托即可。
还有另一种方式,从 OOP 的角度来看,这似乎更一致和正确,但我不确定。中的行为ccTouchBegin
,几乎与 中ccTouchMoved
的行为相同。您可以将其子类化并覆盖一些用于接收触摸事件和实现的方法,就像我所做的那样。另外,我不知道我们是否可以替换 default 。希望这会有所帮助!ccTouchEnded
CCTouchDispatcher
-(BOOL)ccTouchMoved
CCTouchDispatcher