问题描述
我想知道如何在多点触摸视图中检测和区分触摸。我已经阅读了一个哈希代码,但我不明白如何使用它。我想知道我的两个精灵在同一时间被触摸,就像在钢琴的两个琴键上按下和弦一样。
I would like to know how to detect and differentiate between touches in a multi-touch view. I have read about a "hash" code, but I don't understand how to use it. I want to know when two of my Sprites are touched at the same time, like as if pressing a chord on two keys of a piano.
下面是我为ccTouchesBegan所做的例子:
Here is an example of what I have for my ccTouchesBegan:
- (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;
}
}
}
}
}
这里是我的ccTouchesEnded的开始:
And here is the beginning of my ccTouchesEnded:
- (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];
}
}
}
你能给我一个例子,如何捕获从sprite开始,结束在sprite上的触摸?我一直在努力,不能让哈希码工作 - 只是不明白如何哈希码可以用来引用一个触摸以后。我猜我想要做什么将被称为哈希跟踪器?
Could you maybe give me an example of how you would capture touches that began on a sprite and ended on a sprite? I have been struggling and can't get the hash code to work - just not understanding how the hash code can be used to reference a touch later. I guess what I'm trying to make would be called a hash tracker?
我相信有一个更少的复杂的方式来做它使用哈希码和更少状态变量。我没有充分利用ccTouchesEnded方法与其他状态变量效果,因为我希望找到一个更简单的方法(我知道我仍然需要使ccTouchesMoved和Cancelled方法)。
I am sure there is a much less convoluted way to do it using the hash codes and less state variables. I haven't fleshed out the ccTouchesEnded method with the other state variable effects because I was hoping to find a simpler way (I know I still need to make the ccTouchesMoved and Canceled methods too).
推荐答案
这里是我实现这一点,如果其他人试图这样做(我限制为2按钮组合,但我可以很容易地将逻辑扩展到3& ; 4按钮组合)。我选择使用ccTouchBegan / Ended / Moved单独处理每个触摸,而不是使用ccTouchesBegan / Ended / Moved,因为我根本无法使用哈希码。欢迎任何其他想法。
Here is how I implemented this in case anyone else is trying to do this (I have limited it to 2-button combos but I could easily extend the logic to 3 & 4-button combos as well). I chose to handle each touch individually using the ccTouchBegan/Ended/Moved instead of using the ccTouchesBegan/Ended/Moved because I just couldn't get it to work with the hash code. Any alternative ideas would be welcome.
spuButton.h(CCSprite子类)
spuButton.h (a CCSprite Subclass)
#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
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 tick:方法来保持我的其他函数不混淆的例子)
HelloWorldScene.m (Just my tick: method to keep my other functions from confusing the example)
-(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;
}
}
这篇关于多点触摸检测& iPhone下载Cocos2d的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!