How to Detect the CCSprite Touchevent getBoundingbox equals of CCTouches - cocos2d-android

I am new to COCOS2d. I am using ccsprite with animation as a button. Now i am struggle to detect the CCTouches and CCsprite getbounding box are equals for click event.

From this way you can achieve what you need and write this code in CCtouches___() :
ArrayList<CCSprite> animation= new ArrayList<CCSprite>();
CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(event.getX(), event.getY()));
for (CCSprite target : animation){
if(CGRect.containsPoint((target.getBoundingBox()), location)){
//here what you want
}

Related

Fixed sprite on the tile map cocos2d?

I can't figure out how to handle with tile map layer and other node. I want to make another one layer(CCNode) for such things as menu button, score, joystick that must always stay fixed(not scrolled), when the whole map is scrolled.
self.theMap=[CCTiledMap tiledMapWithFile:#"map.tmx"];
self.bgLayer=[theMap layerNamed:#"bg"];
[self addChild:theMap z:-1];
CCNode *joystickNode;
joystickNode=[CCNode node];
[bgLayer.parent addChild:joystickNode z:2];
upArrowFrame=[CCSpriteFrame frameWithImageNamed:#"uparrow.png"];
upArrow=[CCButton buttonWithTitle:#"" spriteFrame:upArrowFrame];
[upArrow setTarget:self selector:#selector(upArrowPressed)];
upArrow.position= ccp(190,190);
[joystickNode addChild:upArrow z:2];
Now upArrow is not visible on the screen at all. If I add to self instead of joystickNode, it will appear.
I can't even understand, what parent should new CCNode have. Can anyone explain it to me? I also tried to add new CCNode as a child of self and theMap.
EDIT: Oops, it's actually moving the camera. How to implement it in this case?
-(void)setCenterOfScreen :(CGPoint) position {
CGSize screenSize=[[CCDirector sharedDirector]viewSize];
int x=MAX(position.x, screenSize.width/2);
int y=MAX(position.y, screenSize.height/2);
x= MIN(x, theMap.mapSize.width * theMap.tileSize.width - screenSize.width/2);
y= MIN(y, theMap.mapSize.height * theMap.tileSize.height - screenSize.height/2);
CGPoint goodPoint =ccp(x,y);
CGPoint centerOfScreen = ccp(screenSize.width/2, screenSize.height/2);
CGPoint difference = ccpSub(centerOfScreen, goodPoint);
self.position=difference;
}
- (void)update:(CCTime)dt{
[self setCenterOfScreen:hero.position];
}

CGRectContainsPoints and bounding box check is off by several pixels

I've been studying this for hours (2 days, actually) and just cannot figure out what is wrong. The touches are accepted and processing, but the isTouchHandled test is triggering TRUE prematurely; as if a different bounding box was touched than the one that is touched. I have several non-overlapping CCSprite buttons, with each pointed to in the levelButtons array. Iterate through to see which one is touched; but it's always the wrong one.
Does the CGRectContainsPoints method get thrown off if these sprites are in their own layer, which is then in another layer? In other words, is CGRectContainsPoints using raw equality of pixel locations as reported by position? If so, a sprite's position relative to the entire screen is different than its reported position if it is a child, which is relative to the parent. Maybe this has something to do with it? My array and the tags of its contents are correctly lining up, I've logged and checked that many times; it appears to be the bounding box check.
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CCLOG (#"levelButtons size:%i",[self.levelButtons count]);
BOOL isTouchHandled = NO;
for (int i=0;i<25;i++){
CCSprite*temp=(CCSprite*)[self.levelButtons objectAtIndex:i];
CCLOG(#"iteration temp.tag: %i for object: %i",temp.tag,i);
isTouchHandled= CGRectContainsPoint([temp boundingBox], [[CCDirector sharedDirector] convertToGL:[touch locationInView: [touch view]]]);
if (isTouchHandled) {
CCLOG(#"level touched: %i",temp.tag);
break;
}
}
return isTouchHandled;
}
UPDATE: Incidentally, I also just subclassed CCSprite and add the touche methods to the individual sprites in this fashion ,taking my array of sprites out of the picture. The results were the same, so I suspect the CGRectContainsPoints is not properly working when your rect is a child of other children, the coordinates are not being reported correctly, I suspect.
I think it may be problem with an array that you are getting sprites. Any way , this is how i am using the code for getting the sprite tag.
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for(int i1=0;i1<=25;i1++)
{
CCSprite *sprite1 = (CCSprite *)[self getChildByTag:i1];
if(CGRectContainsPoint([sprite1 boundingBox], location))
{
//Your Code
break;
}
}
I solved this by creating a new CGRect for the CGRectContainsPoint test, and translating the bounding box into the actual onscreen rectangle; the bounding box test will not work on its own if it is located on a child sprite (or layer). It returns its local position only, relative to the parent.

Cocos2d - Orbiting/spinning one sprite around another

I've got to sprites, essentially a nucleus (parent) and an electron (child). I'm trying to find a way to have the electron orbit the nucleus. I've found a few posts here and there on moving anchor points, but that is apparently related to the texture of the sprite, not the sprite itself.
This is my current init method for my parent sprite:
self = [super init];
if (self) {
CCSprite *orbitAnchor = [CCSprite new];
[self addChild:orbitAnchor];
orbitAnchor.position = ccp(32,32);
CCSprite *orbiter = [CCSprite spriteWithFile:#"line.png" rect:CGRectMake(0, 0, 8, 8)];
[orbitAnchor addChild:orbiter];
orbiter.position = ccp(40,40);
CCAction *orbitAction = [CCRepeatForever actionWithAction:[CCRotateTo actionWithDuration:1 angle:720]];
[orbitAnchor runAction:orbitAction];
[self initAnimations];
}
return self;
Those numbers are all totally arbitrary though - I just stuck them in there and got what looked best. I'm sure there's a more programatic way to do what I want.
Basically, I'm looking for a way to set the child's axis point at the center of the parent, and then have it rotate around that point. It seems like a relatively simple thing to do using CCRotate and such, but I think I'm missing what to search for in order to move the anchor point of the child. Any suggestions/other posts?
Thanks
You have [CCSprite new] which is an unusual use, probably not supported. Unless the orbit anchor node should display a texture, you can just use a CCNode as anchor.
Technically you're doing everything correct from what I can see. You might want to try without the rotate actions and instead change the direction manually in a scheduled update method.
CCNode *orbitAnchor = [CCNode node];
[self addChild:orbitAnchor z:0 tag:1];
orbitAnchor.position = ccp(32,32);
CCSprite *orbiter = [CCSprite spriteWithFile:#"line.png" rect:CGRectMake(0, 0, 8, 8)];
[orbitAnchor addChild:orbiter z:0 tag:2];
orbiter.position = ccp(40,40);
[self scheduleUpdate];
Update method:
-(void) update:(ccTime)delta
{
CCNode* orbitAnchor = [self getChildByTag:1];
orbitAnchor.direction += 5;
}
From the image filename it looks like you're trying to draw a line from the orbitAnchor to the orbiter. You can do that with ccDrawLine:
-(void) draw
{
CCNode* orbitAnchor = [self getChildByTag:1];
CCNode* orbiter = [self getChildByTag:2];
ccDrawLine(orbitAnchor.position, orbiter.position);
}
Anchor points. Automatically, objects are placed based on the center of an object right? with anchor points you can move that around, so if you rotate the object it will rotate around the anchorpoint. http://www.qcmat.com/understanding-anchorpoint-in-cocos2d/

a SPECIFIC sprite- touch detection

since i havnt got an answer in my previos post, and no one solve that problem , i am asking this again. there is no 1 explanation regarding this.
i need to detect a sprite touch, a SPECIFIC one. in cocos2d+box2d.
lets say i have sprite CCSprite *ran that has a body, BUT , i have many of it .
if i detect a touch with the ccTouchesBegan , and use the if(CGRectContainsPoint(particularSpriteRect, currentPosition))
i will detect the touch in ran but i dont know who ran is this from all, and i need to destroy than specific ran , which i cant know who it was .
i find the best way to do that, as i do with contact listener that gives me the specific sprite user data :
CCSprite *actora = (CCSprite*)bodyA->GetUserData();
CCSprite *actorb = (CCSprite*)bodyB->GetUserData();
and then i know that actora is what needs to be destroy cause i have his user data.
[self removeChild:actora cleanup:YES];
so , again , i need to detect a sprite touch and KNOW who it was,cause i have many ran's.
i guess its something needs to involve the userData .
any direction please ?
thanks alot.
ok, i have got it :
this is what i do, to destroy the specific body, different from what was said here :
put the next code in the touch method :
CGPoint currentPosition = [touch locationInView: [touch view]];
currentPosition = [[CCDirector sharedDirector] convertToGL: currentPosition];
b2Vec2 locationWorld = b2Vec2(currentPosition.x/PTM_RATIO, currentPosition.y/PTM_RATIO);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
b2Fixture *bf1 = b->GetFixtureList();
if (bf1->TestPoint(locationWorld))
{
CCSprite *tempSprite = (CCSprite *) b->GetUserData();
if (tempSprite .tag==2 || tempSprite .tag==3)
{
[self removeChild:tempSprite cleanup:YES];
world->DestroyBody(b);
}
}
}
here if you touch the right sprite(tagged) , it get destroyed .

not working - Box2D

I am using tilemap in my box2D game in which I have created powers. When the player hits the power, a score label is displayed on the screen. Along with this I want to remove that power from the tilemap when player hits it. I have displayed label but I am unable to remove the power. Here is some code :
In ContactListener I am calling the method which removes the power from tilemap :
void ContactListener::BeginContact(b2Contact *contact) {
else if(actorA.tag==obj.gamePower.tag) //obj is a DataClass object.
{
[GameScene addPointLabel]; // For displaying score label
[GameScene removePower:actorA];
}
+(void)removePower:(id)sender
{
GameScene *obj=[[GameScene alloc]init];
CCSprite *sprite = (CCSprite *)sender;
[obj removePowerFromScene:sprite];
[obj release];
}
-(void)removePowerFromScene:(id)sender
{
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
}
I have created an object layer on tilemap to display power. But somehow, I am unable to remove it. Can someone help me?
If power is a CCNode why don't you remove it with [power removeFromParentAndCleanup:YES] ?
The (removePower:) does remove nothing because it creates a new scene and remove the sprite from that scene where the sprite does not belong to.
Another notice, be careful with contact listener. Removing o node in BeginContact is potential of crash. Let imagine the case that powerA contacts with both actor1 and actor2. The first call to BeginContact with powerA and actor1 removes powerA, so subsequent call to BeginContact with powerA envolved will crash !