私が書いている cocos2D プログラムでタッチ イベントを処理する際に興味深い問題があります。CCScene に 3 つの CCLayer サブレンズ レイヤーがあります。
backgroundLayer – z:0 – 背景画像を表示するために使用される単純な静的レイヤー。
PlanetLayer - z:3 – 表示レイヤー – データ変更の視覚化がここに表示されます。
gameControlsLayer – z:5 – スライダーやボタンなどのデータ コントローラーを表示するために使用されるレイヤー。
コントロールが影響を受けることを心配せずに惑星レイヤーをパンおよびズームしたいので、惑星レイヤーとコントロール レイヤーを分離しました。
これらのレイヤーを設定するシーンの初期化コードは次のとおりです。
- (id) init
{
self = [super init];
if (self != nil)
{
// background layer
BackgroundLayer *backgroundLayer = [BackgroundLayer node];
[self addChild:backgroundLayer z:0];
// planet layer
PlanetLayer *planetLayer = [PlanetLayer node];
[self addChild:planetLayer z:3];
// gameplay layer
GameControlsLayer *gameControlsLayer = [GameControlsLayer node];
[self addChild:gameControlsLayer z:5];
}
return self;
}
惑星レイヤーとコントロールレイヤーの両方でタッチ処理が必要です。コントロール レイヤーでは、タッチ処理はレイヤーの子であるコントロール オブジェクト内にあります。最初にこのコードをすべて書きましたが、問題なく動作します。
その後、惑星レイヤーのレイヤー全体のタッチ処理を記述して、タッチ スクロールとズームを実行できるようにしました。スクロールはできましたが(まだズームはできていません)、問題なく動作しています。私の問題は次のとおりです。コントロールレイヤーのコントロールをタッチして操作すると、正常に動作しますが、たとえば、スライダーの親指を上下に動かすと、コントロールレイヤーの背後にある惑星レイヤーが、タッチが意図されているかのようにパンしますそれ。
コードを含めるのは冗長かもしれませんが、関連するスニペットは次のとおりです。
スライダー コントロールの場合、コントロール レイヤーの子:
- (void) onEnterTransitionDidFinish
{
[[CCTouchDispatcher sharedDispatcher]
addTargetedDelegate:self priority:1 swallowsTouches:YES];
}
- (void) onExit
{
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
}
#pragma mark Touch Delegate
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint location = [[CCDirector sharedDirector]
convertToGL:[touch locationInView:[touch view]]];
float distance = [self distanceBetweenPointOne:thumbPosition
andPointTwo:location];
if (distance > thumbRadius*2)
{
return NO;
}
// touch is on the thumb. store the location so we
// can calculate changes on ccTouchMoved events
touched = YES;
return YES;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
if (!touched)
{
return;
}
CGPoint location = [[CCDirector sharedDirector]
convertToGL:[touch locationInView:[touch view]]];
location = [self convertToNodeSpace:location];
// if we're too far off the thumb, abandon it
float distance = [self distanceBetweenPointOne:thumbPosition
andPointTwo:location];
if (distance > thumbRadius*3)
{
//touched = NO;
return;
}
// this call adjusts some ivars – not relevant
[self updateValueAndPosition:location];
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
if (touched)
{
touched = NO;
}
}
- (void)ccTouchCancelled:(UITouch *)touch
withEvent:(UIEvent *)event
{
[self ccTouchEnded:touch withEvent:event];
}
惑星レイヤーからの関連コードは次のとおりです。
// Yes, we want touch notifications please
//
- (void) onEnterTransitionDidFinish
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:0 swallowsTouches:NO];
}
#pragma mark Touch Delegate
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector]
convertToGL:touchLocation];
// ****NOTE – the following is a kludge I used it to break
// ********** the behavior; the controls are all grouped
// ********** at the bottom of the screen. But this is not
// ********** an acceptable fix. I shouldn’t need to mask
// ********** off certain areas of the screen. This strategy
// ********** will not hold once I add other controls to the
// ********** control layer.
//
if (touchLocation.y > 250.0f)
{
self.touched = YES;
touchHash = [touch hash];
return YES;
}
return YES;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
if (!touched)
{
return;
}
if ([touch hash] == touchHash)
{
CGSize screenSize = [[CCDirector sharedDirector] winSize];
CGPoint touchLocation =
[touch locationInView:[touch view]];
CGPoint prevLocation =
[touch previousLocationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector]
convertToGL:touchLocation];
prevLocation = [[CCDirector sharedDirector]
convertToGL:prevLocation];
CGPoint diff = ccpSub(touchLocation, prevLocation);
CGPoint currentPosition = [self position];
CGPoint newPosition = ccpAdd(currentPosition, diff);
if (newPosition.x < lowestX)
newPosition.x = lowestX;
else if (newPosition.x > highestX-screenSize.width)
newPosition.x = highestX-screenSize.width;
if (newPosition.y < lowestY)
newPosition.y = lowestY;
else if (newPosition.y > highestY-screenSize.height)
newPosition.y = highestY-screenSize.height;
[self setPosition:newPosition];
}
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
if ([touch hash] == touchHash)
{
if (touched)
{
touched = NO;
}
}
}
- (void)ccTouchCancelled:(UITouch *)touch
withEvent:(UIEvent *)event
{
[self ccTouchEnded:touch withEvent:event];
}
ピンチ ズーム機能を追加したいのですが、その前にこの問題を解決する必要があります。誰かがここで答えを持っていますか? 明らかな何かが欠けているように感じます…</p>
ありがとう!