2010-07-18 4 views
4

회전 된 CCSprite에서 터치를 어떻게 감지합니까?Cocos2d : 회전 된 스프라이트에 터치가 감지 되었습니까?

나는 ccTouchesBegan과 contentSize, anchorPoint 등을 사용하는 일반적인 기술에 익숙하여 터치가 경계 내에 있는지를 스프라이트로 감지하지만 스프라이트가 회전되면 어떻게 진행해야할지 모르겠습니다. 어떤 각도.

스프라이트 자체가 터치 (캡슐화)를 감지하고 대리자를 통해 다른 객체에 이벤트를보고하기를 원합니다.

누군가 공유 할 코드가 있다면 ... 좋을 것입니다.

답변

6

CCNode convertTouchToNodeSpaceAR : 메서드를 사용하여 포인트를 회전 좌표로 변환 한 다음 스프라이트 경계 비교를 수행 할 수 있습니다.

CCNode에서이 카테고리를 만들었으므로 모든 CCNode 또는 하위 클래스에서 사용할 수 있습니다.

@interface CCNode (gndUtils) 

// Lets a node test to see if a touch is in it. 
// Takes into account the scaling/rotation/transforms of all 
// the parents in the parent chain. 
// Note that rotation of a rectangle doesn't produce a rectangle 
// (and we are using a simple rectangle test) 
// so this is testing the smallest rectangle that encloses the rotated node. 
// This does the converstion to view and then world coordinates 
// so if you are testing lots of nodes, do that converstion manually 
// 
// CGPoint touchLoc = [touch locationInView: [touch view]]; // convert to "View" 
// touchLoc = [[CCDirector sharedDirector] convertToGL: touchLoc]; // move to "World" 
// and then use worldPointInNode: method instead for efficiency. 

- (BOOL) touchInNode: (UITouch *) touch; 

// allows a node to test if a world point is in it. 
- (BOOL) worldPointInNode: (CGPoint) worldPoint; 

@end 

및 구현 :

아빠의 코드는 세계로 노드의 BBOX 변환 @
@implementation CCNode (gndUtils) 

- (BOOL) touchInNode: (UITouch *) touch 
{ 
    CGPoint touchLoc = [touch locationInView: [touch view]];   // convert to "View coordinates" from "window" presumably 
    touchLoc = [[CCDirector sharedDirector] convertToGL: touchLoc];  // move to "cocos2d World coordinates" 

    return [self worldPointInNode: touchLoc]; 
} 

- (BOOL) worldPointInNode: (CGPoint) worldPoint 
{ 
    // scale the bounding rect of the node to world coordinates so we can see if the worldPoint is in the node. 
    CGRect bbox = CGRectMake(0.0f, 0.0f, self.contentSize.width, self.contentSize.height); // get bounding box in local 
    bbox = CGRectApplyAffineTransform(bbox, [self nodeToWorldTransform]);  // convert box to world coordinates, scaling etc. 
    return CGRectContainsPoint(bbox, worldPoint); 
} 
@end 
+0

고마워요! 매력처럼 작동 ... – poundev23

+0

어쨌든 이걸 cocos2d 2에서 할 수 있을까요? 약간의 오류가 발생했습니다. 나는 이것이 쓰여진 이후로 몇몇 것들이 사용되지 않을 것이라고 생각한다. 감사! – Corey

+0

나를 위해 작동합니다. 이것은 cocos2d에 내장되어야합니다. :-) –

5

. 회전 된 노드의 경우, 이는 bbox를 확장하고 실제 노드 외부이지만 world bbox 내부의 접촉에 대해서는 true를 반환 할 수 있습니다. 이것을 피하려면, 월드 포인트를 노드의 좌표 공간으로 변환하고, 로컬 포인트를 테스트하십시오.

+1

나는 당신이 여기에서 설명하는 문제를 가지고 있다고 믿지만 당신이 솔루션으로 제안하는 것을 이해하지 못하고있다. 당신은 정교 할 수 있습니까? – mwright

+0

좋은 지적과 좋은 제안 – Dad

2

압생트 으로 말했다 - poundev23 정말 회전 스프라이트 주위에만 BB를 확인하는 코드입니다. 나는 올바른 코드를 작성했습니다 (그러나 Cocos2dx에 - C++) - 희망은 누군가 도움 :

CCSize size = this->getContentSize(); 
CCRect rect = CCRect(0, 0, size.width, size.height); 
CCPoint pt = touch->locationInView(); 
pt = CCDirector::sharedDirector()->convertToGL(pt); 
pt = CCPointApplyAffineTransform(pt, this->worldToNodeTransform()); 
bool b = CCRect::CCRectContainsPoint(rect, pt); 

가 좋은 코드를!

편집 : 좋은 해결책! Objective C로 변환했습니다.

- (BOOL) containsTouchLocation:(UITouch *) touch 
{ 
    CGSize size = self.contentSize; 
    CGRect rect = CGRectMake(0, 0, size.width, size.height); 
    CGPoint touchLocation = [touch locationInView: [touch view]]; 
    touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation]; 
    touchLocation = CGPointApplyAffineTransform(touchLocation, self.worldToNodeTransform); 
    bool containsPoint = CGRectContainsPoint(rect, touchLocation); 

    return containsPoint; 
} 
+1

Obj-C로 변환하여 편집으로 추가했습니다. 감사합니다. – jarryd

관련 문제