Обнаружение и дифференцирование нескольких касаний - Cocos2D для iPhone

StackOverflow https://stackoverflow.com/questions/4061473

Вопрос

Я хотел бы узнать, как обнаружить и дифференцироваться между прикосновениями в мульти-прикосновении. Я прочитал о «хэш» коде, но я не понимаю, как его использовать. Я хочу знать, когда двое из моих спрайтов затронуты одновременно, как будто нажимая аккорд на двух ключах фортепиано.

Править] Вот пример того, что у меня для моего CCTOUSHESBEGAN:

- (void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {

  NSSet *allTouches = [event allTouches];
  int validTouchCount = 0;
  for (UITouch* touch in allTouches) {

    BOOL touchIsValid = FALSE;

    CGPoint location = [touch locationInView: [touch view]];
    CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];

    if (CGRectContainsPoint(_fourButtonsRect, convertedLocation)) {
        NSLog(@"Touch is within four buttons");
        touchIsValid = TRUE;
    }


    _playerDidAction = 0;
    NSLog(@"before the loop");
    if (touchIsValid) {

        validTouchCount++;
        NSLog(@"Within ValidTouches loop");
        CGPoint validLocation = [touch locationInView: [touch view]];
        CGPoint convertedValidLocation = [[CCDirector sharedDirector] convertToGL:validLocation];

        if (CGRectContainsPoint(_redButtonSprite.boundingBox, convertedValidLocation)) {
            _redButtonStatus = TRUE;
            [_redButtonSprite setTexture:_redButtonLit];
            if (validTouchCount == 1) {
                _playerDidAction = 1;
            }
        }
            else if (CGRectContainsPoint(_blueButtonSprite.boundingBox, convertedValidLocation)) {  
                _blueButtonStatus = TRUE;
                [_blueButtonSprite setTexture:_blueButtonLit];
                if (validTouchCount == 1) {
                    _playerDidAction = 2;
                }
            }
                else if (CGRectContainsPoint(_greenButtonSprite.boundingBox, convertedValidLocation)) { 
                    _greenButtonStatus = TRUE;
                    [_greenButtonSprite setTexture:_greenButtonLit];
                    if (validTouchCount == 1) {
                        _playerDidAction = 3;
                    }
                }
                    else if (CGRectContainsPoint(_yellowButtonSprite.boundingBox, convertedValidLocation)) {    
                        _yellowButtonStatus = TRUE;
                        [_yellowButtonSprite setTexture:_yellowButtonLit];
                        if (validTouchCount == 1) {
                            _playerDidAction = 4;
                        }
                    }

        if (validTouchCount > 1) {

            if (_redButtonStatus && _blueButtonStatus) {
                _comboRB = TRUE;
                _playerDidAction = 5;
            }
                else if (_redButtonStatus && _greenButtonStatus) {
                    _comboRG = TRUE;
                    _playerDidAction = 6;
                }
                    else if (_redButtonStatus && _yellowButtonStatus) {
                        _comboRY = TRUE;
                        _playerDidAction = 7;
                    }
                        else if (_blueButtonStatus && _greenButtonStatus) {
                            _comboBG = TRUE;
                            _playerDidAction = 8;
                        }
                            else if (_blueButtonStatus && _yellowButtonStatus) {
                                _comboBY = TRUE;
                                _playerDidAction = 9;
                            }
                                else if (_greenButtonStatus && _yellowButtonStatus) {
                                    _comboGY = TRUE;
                                    _playerDidAction = 10;
                                }

        }
    }
  }
}

И вот начало моего CCTouchEsed:

- (void)ccTouchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {

    for (UITouch *touch in touches) {


        CGPoint location = [touch locationInView: [touch view]];
        CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];     
        if (CGRectContainsPoint(_redButtonSprite.boundingBox, convertedLocation)) { 
            _redButtonStatus = FALSE;
            [_redButtonSprite setTexture:_redButtonNormal];
        }
        if (CGRectContainsPoint(_blueButtonSprite.boundingBox, convertedLocation)) {    
            _blueButtonStatus = FALSE;
            [_blueButtonSprite setTexture:_blueButtonNormal];
        }
        if (CGRectContainsPoint(_greenButtonSprite.boundingBox, convertedLocation)) {   
            _greenButtonStatus = FALSE;
            [_greenButtonSprite setTexture:_greenButtonNormal];
        }
        if (CGRectContainsPoint(_yellowButtonSprite.boundingBox, convertedLocation)) {  
            _yellowButtonStatus = FALSE;
            [_yellowButtonSprite setTexture:_yellowButtonNormal];
        }


    }
}

Может ли вы, возможно, приведу мне пример того, как вы будете захватывать прикосновения, которые начались на спрайт и закончились на спрайт? Я боролся и не могу получить код хеша на работу - просто не понимая, как хеш-код можно использовать для ссылки на прикосновение. Я думаю, что я пытаюсь сделать, будет называться хеш-трекером?

Я уверен, что есть гораздо менее запутанный способ сделать это, используя хэш-коды и меньшие переменные состояния. Я не сильно пробил CCTouchEsended метод с другими видами переменного состояния, потому что я надеялся найти более простой способ (я знаю, что мне все еще нужно сделать CCTouchesMeed и отменили методы).

Это было полезно?

Решение 2

Вот как я реализовал это в случае, если кто-то еще пытается сделать это (я ограничил его до 2 кнопочных комбо, но я мог легко расширить логику на 3 и 4-кнопочные комбо). Я решил обрабатывать каждое касание индивидуально с помощью CCTUSCBEGAN / ENDED / перемещенных вместо использования CCTOUSHESBEGAN / CONDED / MOVED, потому что я просто не мог заставить его работать с хэш-кодом. Любые альтернативные идеи будут приветствовать.

spubutton.h (подкласс CCSPRITE)

#import <Foundation/Foundation.h>
#import "cocos2d.h"

typedef enum tagButtonState {
    kButtonStatePressed,
    kButtonStateNotPressed
} ButtonState;

typedef enum tagButtonStatus {
    kButtonStatusEnabled,
    kButtonStatusDisabled
} ButtonStatus;

@interface spuButton : CCSprite <CCTargetedTouchDelegate> {
@private
    ButtonState buttonState;
    CCTexture2D *buttonNormal;
    CCTexture2D *buttonLit;
    ButtonStatus buttonStatus;  
}

@property(nonatomic, readonly) CGRect rect;

+ (id)spuButtonWithTexture:(CCTexture2D *)normalTexture;

- (void)setNormalTexture:(CCTexture2D *)normalTexture;
- (void)setLitTexture:(CCTexture2D *)litTexture;
- (BOOL)isPressed;
- (BOOL)isNotPressed;
- (void)makeDisabled;
- (void)makeEnabled;
- (BOOL)isEnabled;
- (BOOL)isDisabled;
- (void)makeLit;
- (void)makeNormal;
- (void)dealloc;

@end

spubutton.m.

#import "spuButton.h"
#import "cocos2d.h"

@implementation spuButton

- (CGRect)rect {
    CGSize s = [self.texture contentSize];
    return CGRectMake(-s.width / 2, -s.height / 2, s.width, s.height);
}

+ (id)spuButtonWithTexture:(CCTexture2D *)normalTexture {
    return [[[self alloc] initWithTexture:normalTexture] autorelease];
}

- (void)setNormalTexture:(CCTexture2D *)normalTexture {
    buttonNormal = normalTexture;
}
- (void)setLitTexture:(CCTexture2D *)litTexture {
    buttonLit = litTexture;
}

- (BOOL)isPressed {
    if (buttonState== kButtonStateNotPressed) return NO;
    if (buttonState== kButtonStatePressed) return YES;
    return NO;
}

- (BOOL)isNotPressed {
    if (buttonState== kButtonStateNotPressed) return YES;
    if (buttonState== kButtonStatePressed) return NO;
    return YES;
}

- (void)makeDisabled {
    buttonStatus = kButtonStatusDisabled;
    buttonState= kButtonStateNotPressed;
    [self makeNormal];
}
- (void)makeEnabled {
    buttonStatus = kButtonStatusEnabled;
    buttonState= kButtonStateNotPressed;
    [self makeNormal];
}

- (BOOL)isEnabled {
    if (buttonStatus== kButtonStatusDisabled) return NO;
    if (buttonStatus== kButtonStatusEnabled) return YES;
    return NO;
}

- (BOOL)isDisabled {
    if (buttonStatus== kButtonStatusEnabled) return NO;
    if (buttonStatus== kButtonStatusDisabled) return YES;
    return YES;
}

- (void)makeLit {
    [self setTexture:buttonLit];
}

- (void)makeNormal {
    [self setTexture:buttonNormal];
}

- (id)initWithTexture:(CCTexture2D *)aTexture {
    if ((self = [super initWithTexture:aTexture]) ) {       
        buttonState = kButtonStateNotPressed;
        buttonStatus = kButtonStatusEnabled;
    }
    return self;
}

- (void)onEnter {
    if (buttonStatus == kButtonStatusDisabled) return;
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO];
    [super onEnter];
}

- (void)onExit {
    if (buttonStatus == kButtonStatusDisabled) return;
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
    [super onExit];
}   

- (BOOL)containsTouchLocation:(UITouch *)touch {
    return CGRectContainsPoint(self.rect, [self convertTouchToNodeSpaceAR:touch]);
}

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    if (buttonStatus == kButtonStatusDisabled) return NO;
    if (buttonState== kButtonStatePressed) return NO;
    if ( ![self containsTouchLocation:touch] ) return NO;

    buttonState= kButtonStatePressed;
    [self makeLit];

    return YES;
}

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
    // If it weren't for the TouchDispatcher, you would need to keep a reference
    // to the touch from touchBegan and check that the current touch is the same
    // as that one.
    // Actually, it would be even more complicated since in the Cocos dispatcher
    // you get NSSets instead of 1 UITouch, so you'd need to loop through the set
    // in each touchXXX method.

    if (buttonStatus == kButtonStatusDisabled) return;
    if ([self containsTouchLocation:touch]) return;

    buttonState= kButtonStateNotPressed;
    [self makeNormal];
}

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
    if (buttonStatus == kButtonStatusDisabled) return;

    buttonState= kButtonStateNotPressed;
    [self makeNormal];
}

- (void)dealloc {
    [buttonNormal release];
    [buttonLit release];
    [super dealloc];
}

@end

Helloworldscene.m (только моя галочка: метод, чтобы сохранить мои другие функции с толку с толку пример)

-(void)tick:(ccTime)dt {
    if ([[_otherControlsArray objectAtIndex:0] wasPressed]) {
        [[_otherControlsArray objectAtIndex:0] setWasPressed:NO];
        [self removeChild:[_otherControlsArray objectAtIndex:0] cleanup:YES];
        [self addChild:[_otherControlsArray objectAtIndex:1]];
        NSLog(@"Play");

        _gameHasNotBeenPlayedYet = NO;
        Snarfle_s_PowerUPAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
        [delegate makeNotPaused];
        [self gameLogic];
    }

    if (_gameHasNotBeenPlayedYet) {
        return;
    }

    if (_buttonsPressedAndReleased > 0) {  //respond to button(s) released and reset
        NSLog(@"Buttons Pressed and Released-->%d",_buttonsPressedAndReleased);
        if ([self checkButtons:_buttonsPressedAndReleased]);
        _buttonsPressed = 0;
        _buttonsPressedAndReleased = 0;

        return;
    }
    if (_buttonsPressed <= 4) { // two buttons have not already been pressed
        for (spuButton *aButton in _fourButtonsArray) {
            if ([aButton isNotPressed]) continue; //this button is not pressed
            if (_buttonsPressed == 0) { //this button is pressed and no other buttons have been pressed
                _buttonsPressed = aButton.tag;
                continue;
            }
            //this button is pressed while another has been pressed
            //figure out which two buttons have been pressed
            if (_buttonsPressed == 1) {  //red plus another
                switch (aButton.tag) {
                    case 2:   //blue
                        _buttonsPressed = 5;
                        [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                        break;
                    case 3:  //green
                        _buttonsPressed = 6;
                        [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                        break;
                    case 4:  //yellow
                        _buttonsPressed = 7;
                        [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                        break;
                    default:
                        _buttonsPressed = 1;
                        break;
                }
            }
            if (_buttonsPressed == 2) {  //blue plus another
                switch (aButton.tag) {
                    case 1:   //red
                        _buttonsPressed = 5;
                        [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                        break;
                    case 3:  //green
                        _buttonsPressed = 8;
                        [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                        break;
                    case 4:  //yellow
                        _buttonsPressed = 9;
                        [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                        break;
                    default:
                        _buttonsPressed = 2;
                        break;
                }
            }
            if (_buttonsPressed == 3) {  //green plus another
                switch (aButton.tag) {
                    case 1:   //red
                        _buttonsPressed = 6;
                        [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                        break;
                    case 2:  //blue
                        _buttonsPressed = 8;
                        [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                        break;
                    case 4:  //yellow
                        _buttonsPressed = 10;
                        [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                        break;
                    default:
                        _buttonsPressed = 3;
                        break;
                }
            }
            if (_buttonsPressed == 4) {  //yellow plus another
                switch (aButton.tag) {
                    case 1:   //red
                        _buttonsPressed = 7;
                        [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                        break;
                    case 2:  //blue
                        _buttonsPressed = 9;
                        [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                        break;
                    case 3:  //green
                        _buttonsPressed = 10;
                        [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                        [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                        break;
                    default:
                        _buttonsPressed = 4;
                        break;
                }
            }
            if (_buttonsPressed > 4) break;  //more than one has been pressed and identified
        }
    }
    //now we know what buttons have been pressed now check to see if they have been released
    //if more than one has been pressed disable the other two
    //also if more than one has been pressed and one of them gets released disable the released one but keep it lit
    switch (_buttonsPressed) {
        case 1:  //red
            if ([[_fourButtonsArray objectAtIndex:0] isNotPressed]) _buttonsPressedAndReleased = 1;
            break;
        case 2:  //blue
            if ([[_fourButtonsArray objectAtIndex:1] isNotPressed]) _buttonsPressedAndReleased = 2;
            break;
        case 3:  //green
            if ([[_fourButtonsArray objectAtIndex:2] isNotPressed]) _buttonsPressedAndReleased = 3;
            break;
        case 4:  //yellow
            if ([[_fourButtonsArray objectAtIndex:3] isNotPressed]) _buttonsPressedAndReleased = 4;
            break;
        case 5:  //red & blue
            if (([[_fourButtonsArray objectAtIndex:0] isNotPressed]) && ([[_fourButtonsArray objectAtIndex:1] isNotPressed])) _buttonsPressedAndReleased = 5;
            else {
                if ([[_fourButtonsArray objectAtIndex:0] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:0] makeLit];
                }
                if ([[_fourButtonsArray objectAtIndex:1] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:1] makeLit];
                }
            }
            break;
        case 6:  //red & green
            if (([[_fourButtonsArray objectAtIndex:0] isNotPressed]) && ([[_fourButtonsArray objectAtIndex:2] isNotPressed])) _buttonsPressedAndReleased = 6;
            else {
                if ([[_fourButtonsArray objectAtIndex:0] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:0] makeLit];
                }
                if ([[_fourButtonsArray objectAtIndex:2] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:2] makeLit];
                }
            }
            break;
        case 7:  //red & yellow
            if (([[_fourButtonsArray objectAtIndex:0] isNotPressed]) && ([[_fourButtonsArray objectAtIndex:3] isNotPressed])) _buttonsPressedAndReleased = 7;
            else {
                if ([[_fourButtonsArray objectAtIndex:0] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:0] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:0] makeLit];
                }
                if ([[_fourButtonsArray objectAtIndex:3] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:3] makeLit];
                }
            }
            break;
        case 8:  //blue & green
            if (([[_fourButtonsArray objectAtIndex:1] isNotPressed]) && ([[_fourButtonsArray objectAtIndex:2] isNotPressed])) _buttonsPressedAndReleased = 8;
            else {
                if ([[_fourButtonsArray objectAtIndex:1] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:1] makeLit];
                }
                if ([[_fourButtonsArray objectAtIndex:2] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:2] makeLit];
                }
            }
            break;
        case 9:  //blue & yellow
            if (([[_fourButtonsArray objectAtIndex:1] isNotPressed]) && ([[_fourButtonsArray objectAtIndex:3] isNotPressed])) _buttonsPressedAndReleased = 9;
            else {
                if ([[_fourButtonsArray objectAtIndex:1] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:1] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:1] makeLit];
                }
                if ([[_fourButtonsArray objectAtIndex:3] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:3] makeLit];
                }
            }
            break;
        case 10:  //green & yellow
            if (([[_fourButtonsArray objectAtIndex:2] isNotPressed]) && ([[_fourButtonsArray objectAtIndex:3] isNotPressed])) _buttonsPressedAndReleased = 10;
            else {
                if ([[_fourButtonsArray objectAtIndex:2] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:2] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:2] makeLit];
                }
                if ([[_fourButtonsArray objectAtIndex:3] isNotPressed]) {
                    [[_fourButtonsArray objectAtIndex:3] makeDisabled];
                    [[_fourButtonsArray objectAtIndex:3] makeLit];
                }
            }
            break;
        default:
            _buttonsPressedAndReleased = 0;
            break;
    }
}

Другие советы

Предположим, у вас есть два прикосновения. Вы получаете прикосновение события для двух, скажем, на (1,1) и (2,2). Допустим, пользователю стороны оба пальца, вы тогда получаете другое событие, но на этот раз, возможно, на (3,3) и (4,4).

Вопрос в том, сделал (1,1) перейти к (3,3) и (2,2) переместить в (4,4) - или произошел обратное - где (1,1) переместился в (4,4) и (2,2) переместился в (3,3).

Это то, для этого используется «хэш-код» для - дать каждому прикосновению к «имени» - так что вы можете сказать, что происходит с этим особый Прикосновение как последующие события генерируются для него.

Таким образом, для вашего случая вы получите сенсорные события - посмотрите на координаты и определите, какой ключ нажимается для каждого. Вы тогда отслеживаете хэш Для каждого прикосновения, чтобы определить, когда они касаются (то есть конкретная клавиша фортепиано) выделяется.

Вы не можете использовать координаты для этого, потому что координаты могут изменять Как пальцы скользны.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top