Cocos2d: Detect touch on rotated sprite?

How can I detect the touch of a rotated CCSprite?

I am familiar with the general technique of using ccTouchesBegan and contentSize, anchorPoint, etc., to determine the sprite if the touch was within its borders ... but I'm not sure how to act once the sprite has been rotated by some angle.

I want the sprite itself to detect a touch (encapsulation) and pass the event through the delegate to another object.

If someone has a code for sharing ... that would be great.

+4
source share
3 answers

Try using the CCNode convertTouchToNodeSpaceAR: method to convert the point to rotated coordinates, and then you can compare the borders of the sprites.

I made this category on CCNode so that it is available to any CCNode or subclass.

@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 

and implementation:

 @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 
+6
source

@ Dad code converts node bbox to the world. For a rotating node, this extends bbox and can return true for touches that are outside the actual node, but inside the bbox world. To avoid this, convert the world point to the coordinate space of the node and check the local point there.

+5
source

As Absinthe said, poundev23 code really only checks BB around a rotated sprite. I wrote the correct code (but in Cocos2dx - C ++) - I hope that it helps someone:

 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); 

have a good code!

Edit: Good solution! I converted it to 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; } 
+2
source

Source: https://habr.com/ru/post/1316051/


All Articles