So unterscheiden Sie ein Tippen von einem Ziehen

7

Ich erstelle eine App und versuche, sie so zu gestalten, dass ich ein Sprite (mit einem zweiten Sprite oben) über den Bildschirm ziehen kann. Wenn ich jedoch nur auf das Sprite tippe, sollte eine andere Methode aufgerufen werden.

Das Ziehen funktioniert einwandfrei, wenn ich die Kante meines Sprites berühre, aber wenn ich versuche, aus der Mitte des Sprites (wo sich das zweite Sprite oben befindet) zu ziehen, funktioniert das Ziehen überhaupt nicht, aber das Tippen wird aufgerufen .

Ich weiß, warum das nicht so ist, aber es gibt widersprüchliche Berührungen von beiden Geistern, weil der eine oben die Berührung verschluckt, bevor er den zweiten darunter trifft.

Wie kann ich dies implementieren, wenn das Sprite gezogen werden soll, wenn sich der Finger bewegt, aber das Tippen registriert werden soll, wenn nur ein Tippen erfolgt (dh der Finger hat sich nicht auf dem Bildschirm bewegt)?

Ein Bild der Sprites, mit denen ich arbeite (wenn es hilft): Geben Sie hier die Bildbeschreibung ein

Die gelbe Rune ist ein vom Stein darunter getrenntes Sprite (da es sich um Animationen handelt).

--------Touch for the top sprite----------
-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event{
    lastTouchLocation = [RuneScene locationFromTouch:touch];
    BOOL isTouchHandled = CGRectContainsPoint([charSprite boundingBox], lastTouchLocation);

    return isTouchHandled;
}
-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event{
    NSLog(@"Tap received!");

}

------Touch for the bottom sprite--------

-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event{
    lastTouchLocation = [RuneScene locationFromTouch:touch];
    BOOL isTouchHandled = NO;

    // Check if this touch is on the Spider's sprite.
    if (CGRectContainsPoint([current.runeSprite boundingBox], lastTouchLocation)){
        mover = current;
        isTouchHandled = YES;
    }
    else if(CGRectContainsPoint([rune1.runeSprite boundingBox], lastTouchLocation)){
        mover = rune1;
        isTouchHandled = YES;
    }
    else if(CGRectContainsPoint([rune2.runeSprite boundingBox], lastTouchLocation)){
        mover = rune2;
        isTouchHandled = YES;
    }else if(CGRectContainsPoint([rune3.runeSprite boundingBox], lastTouchLocation)){
        mover = rune3;
        isTouchHandled = YES;
    }else if(CGRectContainsPoint([rune4.runeSprite boundingBox], lastTouchLocation)){
        mover = rune4;
        isTouchHandled = YES;
    }else if(CGRectContainsPoint([rune5.runeSprite boundingBox], lastTouchLocation)){
        mover = rune5;
        isTouchHandled = YES;
    }else if(CGRectContainsPoint([rune6.runeSprite boundingBox], lastTouchLocation)){
        mover = rune6;
        isTouchHandled = YES;
    }else if(CGRectContainsPoint([rune7.runeSprite boundingBox], lastTouchLocation)){
        mover = rune7;
        isTouchHandled = YES;
    }else if(CGRectContainsPoint([rune0.runeSprite boundingBox], lastTouchLocation)){
        mover = rune0;
        isTouchHandled = YES;
    }

    // Stop the move action so it doesn't interfere with the user's scrolling.
    //[self stopActionByTag:ActionTagCastingLayerMovesBack];

    // Always swallow touches, GameLayer is the last layer to receive touches.
    return isTouchHandled;

}

-(void) ccTouchMoved:(UITouch*)touch withEvent:(UIEvent *)event{
    CGPoint currentTouchLocation = [RuneScene locationFromTouch:touch]; 

    // Take the difference of the current to the last touch location.
    CGPoint moveTo = ccpSub(lastTouchLocation, currentTouchLocation);

    // Then reverse it since the goal is not to give the impression of moving the camera over the background, 
    // but to touch and move the background.
    moveTo = ccpMult(moveTo, -1);

    lastTouchLocation = currentTouchLocation;

    [self moveActionWithLocation: moveTo];
}

-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event{
    if (!current.isPlaced && mover == current && currentR < Rune6) {
        // Move the game layer back to its designated position.
        CCMoveTo* move = [CCMoveTo actionWithDuration:1 position:curPt];
        CCEaseIn* ease = [CCEaseIn actionWithAction:move rate:0.5f];
        //ease.tag = ActionTagCastingLayerMovesBack;
        [current.runeSprite runAction:ease];

        [current setIsPlaced:YES];
        current.charSprite = [characters objectAtIndex:currentR];
        current.charSprite.position = curPt;
        //charSprite.visible = YES;
        [current performSelector:@selector(fade:) withObject:current.charSprite afterDelay:1];
        [current reorderChild:current.charSprite z:10];

        [self updateCurrentRune:currentR];
        [self updateCurrentCastNum:currentP];
        [self reorderChild:current z:10];
    }
}

Ich habe versucht, in den UITapGestureRecognizer zu schauen, aber alles, was ich tue, um zu implementieren, funktioniert nie. Mit meinen Ebenen / Sprites kann ich sie nicht als Gesten hinzufügen. Ich habe auch etwas über CCGrstureRecognizer oder etwas in den cocos2d-Foren gelesen, aber ich kann keine Dokumentation zu dieser Klasse finden und auch nicht herausfinden, wie man sie tatsächlich verwendet ...

Kennt hier jemand einen Weg, um mir bei meinem Problem zu helfen?

OghmaOsiris
quelle

Antworten:

5

Ich kann Ihnen nicht speziell über cocos2d erzählen, aber im Allgemeinen ist Tippen gegen Ziehen das gleiche Problem bei der Eingabeerkennung wie Mausklick gegen Ziehen.

Die Standardmethode, um damit umzugehen, besteht darin, zu notieren, wann ein Mousedown (oder eine Berührung) auftritt, und zu speichern, wo es passiert ist, um später darauf zurückgreifen zu können. Achten Sie auf Ereignisse mit Mausbewegungen (oder Berührungsbewegungen), um festzustellen, ob sie sich bewegen. Wenn es sich zu einer Position bewegt, die mehr als eine bestimmte Entfernung vom ursprünglichen Klicken / Berühren entfernt ist (normalerweise 3 Pixel für Mausoperationen - ich stelle mir vor, dass dieser Schwellenwert für Berührungssteuerelemente etwas höher wäre), klassifizieren Sie das Klicken / Berühren als Ziehen. und fangen Sie an, es so zu behandeln (bewegte Objekte usw.). Wenn das Mousedown / Touch losgelassen wird, ohne jemals in ein Drag-In umgewandelt zu werden, handelt es sich bei der gespeicherten Click / Touch-Position um ein einfaches Click / Touch-Ereignis.

Sie sollten in der Lage sein, dieses einfache Erkennungssystem vollständig in den bereits vorhandenen TouchBegan-, TouchMoved- und TouchEnded-Ziel-C-Nachrichten zu implementieren, indem Sie für jede Berührung einen kleinen zusätzlichen Status speichern.

Trevor Powell
quelle
Nicht zu einfach, Sie sollten auch über das Delta zwischen Presse und Veröffentlichung nachdenken. Dies soll Ihnen helfen zu verstehen, ob es sich um eine Langpresse oder einen Hahn handelt. Wenn Sie beispielsweise den Bildschirm berühren, 1 Sekunde vergehen und ein Release-Ereignis aufgetreten ist, behandeln Sie es als Longpress und ignorieren Sie das nächste Release-Ereignis. Wenn Sie ein Release vor Ablauf von 1 Sekunde erhalten, behandeln Sie das Release als Tippen.
Gustavo Maciel
0

Das iOS implementiert bereits die Erkennung von Tippen / Ziehen.

ccTouchMoved wird nur aufgerufen, wenn sich der Finger bewegt hat (mit einer Toleranz). Implementieren Sie also einfach ccTouchMoved in topSprite. Wenn es aufgerufen wird, können Sie es als Drag betrachten.

-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event{
    lastTouchLocation = [RuneScene locationFromTouch:touch];
    BOOL isTouchHandled = CGRectContainsPoint([charSprite boundingBox], lastTouchLocation);
    dragged=NO;

    return isTouchHandled;
}
-(void) ccTouchMoved:(UITouch*)touch withEvent:(UIEvent *)event{
    NSLog(@"Drag !");

    dragged=YES;
}
-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event{
    NSLog(@"Tap received!");
    if (!dragged) {
        //Follow tap event to the mainSprite
        //...TODO
    }
    dragged=NO;
}
jptsetung
quelle