cocos2d iphone - game - Cocos2d: ¿Detect touch en el sprite girado?
cocos game creator (3)
¿Cómo se detectaría un toque en un CCSprite girado?
Estoy familiarizado con la técnica general de usar ccTouchesBegan y contentSize, anchorPoint, etc. para que un sprite detecte si un toque estaba dentro de sus límites ... pero no estoy seguro de cómo proceder una vez que el sprite ha sido girado en algún ángulo.
Quiero que el sprite detecte el tacto (encapsulación) e informe el evento a través de un delegado a otro objeto.
Si alguien tiene algún código para compartir ... sería genial.
Intente utilizar el método CCNode convertTouchToNodeSpaceAR: para convertir el punto a las coordenadas giradas y luego puede hacer la comparación de los límites de los sprites.
Hice esto una categoría en CCNode por lo que está disponible para cualquier CCNode o subclase.
@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
y la implementación:
@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
El código de @Pan transforma la bbox del nodo en mundo. Para un nodo rotado, esto amplía la bbox y puede devolver verdadero para toques que están fuera del nodo real pero dentro de la bbox mundial. Para evitar esto, transforma el punto del mundo en el espacio de coordenadas del nodo y prueba el punto local allí.
Como decía Absinthe , el código de poundev23 realmente comprueba solo BB alrededor del sprite girado. He escrito el código correcto (pero en Cocos2dx - c ++) - espero que ayude a alguien:
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);
tener un buen código!
Editar: ¡Buena solución! Lo convertí al Objetivo 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;
}