cocos2d sprite collision - iphone

I have an Array of CCSprites that being displayed all at once.
Every sprite has a movement path, a movement path is a random point on screen.
All the sprites are moving all at once to random points on screen.
What I want to do is to detect collision between the sprites and then change their movement path.
Is it possible?

Iterate through every CCSprite in your array (call it A), and for every iteration iterate again through every CCSprite in the array (excluding A itself of course) (call this one B). Now, use CGRectIntersectsRect along with boundingBox to find a collision between them. It goes something like this:
for (CCSprite *first in mySprites) {
for (CCSprite *second in mySprites) {
if (first != second) {
if (CGRectIntersectsRect([first boundingBox], [second boundingBox])) {
// COLLISION! Do something here.
}
}
}
}
Edit: But of course, it is possible that if two sprites collide, the "collision event" will occur twice (first from the point of view of sprite A, and then from the point of view of sprite B).
If you only want the collision event to trigger once every check, you will need to memorize the pairs so that you can ignore collisions that already did happen on that check.
There are countless ways you could check for that, but here's an example (updated code):
Edited again:
NSMutableArray *pairs = [[NSMutableArray alloc]init];
bool collision;
for (CCSprite *first in mySprites) {
for (CCSprite *second in mySprites) {
if (first != second) {
if (CGRectIntersectsRect([first boundingBox], [second boundingBox])) {
collision = NO;
// A collision has been found.
if ([pairs count] == 0) {
collision = YES;
}else{
for (NSArray *pair in pairs) {
if ([pair containsObject:first] && [pair containsObject:second]) {
// There is already a pair with those two objects! Ignore collision...
}else{
// There are no pairs with those two objects! Add to pairs...
[pairs addObject:[NSArray arrayWithObjects:first,second,nil]];
collision = YES;
}
}
}
if (collision) {
// PUT HERE YOUR COLLISION CODE.
}
}
}
}
}
[pairs release];

Have a look at this S.O. answers.
You can do simple collision detection using CGRectIntersectsRect and the node boundingBox. If you need more advanced features, have a look at a physics engine like chipmunk or Box2D.

Ray Wenderlich has written a good tutorial about using Box2D just for collision detection, if you're interested in going that way. http://www.raywenderlich.com/606/how-to-use-box2d-for-just-collision-detection-with-cocos2d-iphone
Check first that your sprites can be approximated by rectangles. If so then #Omega's answer was great. If they can't be, perhaps because they contain a lot of transparency or for some other reason, you might need to approximate your sprites with polys and work with those.

Related

BOOL method to detect if nodes have been removed from scene

Im making a brick breaker type game and need to know if all the bricks have been broken in order to transition to the win screen.
The way I've been thinking of solving this is to create a BOOL method that is ran each time a brick is removed to calculate how many bricks are left. If there are no bricks left... move to the win scene.
Im struggling with the logic on how to do this.
So far I have:
-(BOOL)isGameWon{
for (SKNode* node in self.children){
if ([node.name isEqual:brickCategoryName]){
//some logic
}
}
return YES;
}
didBeginContactMethod:
if (notTheBall.categoryBitMask == brickCategory) {
[self runAction:_smashSound];
[notTheBall.node removeFromParent];
if ([self isGameWon]) {
NSLog(#"YOU WIN!");
}
}

How to refer to sprites when using Cocos2d collision detection?

Using the method below, how can one refer to specific sprites when checking to see if they intersect?
- (void)update:(ccTime)dt {
for (CCSprite *sprite in movableSprites) {
if (CGRectIntersectsRect(sprite.boundingBox, sprite.boundingBox)) {
break;
}
}
}
It appears that all sprites are available in the moveableSprites object, but I don't know how to check if specific sprites are colliding... I don't know how to refer to them. If there is an easier way to perform collision detection I'm interested.
It appears your code above will always return TRUE because you are checking if the boundingbox of sprite collides with sprite, and since they are the same it always will.
if (CGRectIntersectsRect(sprite.boundingBox, sprite.boundingBox)) {//
break;
}
Should be comparing to a different sprite not the same sprite.
if (CGRectIntersectsRect(sprite.boundingBox, otherSprite.boundingBox)) {//
break;
}
If that does not answer your question maybe you are looking to avoid enumerating through the array? If that is the case try using tags. Someting like below.
CCSprite *aSprite = [CCSprite spriteWithFile:#"hurdle1.png"];
[self addChild:aSprite tag:2];
Now [self getChildByTag:2] can take the place of sprite
and you can just add boundingBox to check collisions, as below.
if (CGRectIntersectsRect([self getChildByTag:2].boundingBox, checkSprite.boundingBox)) {//
break;
}

Removing sprite from layer not removing rect with it (Cocos2d)?

I am making a game in Cocos2d. Everything is okay, so far. I used Ray Wenderlich's tutorial to get collision detection to work. It works, but whenever an 'enemy' spawns where a bullet was deleted (because the bullet that was deleted hit a target, therefore, was deleted), the enemy is automatically deleted, too. I think it's because it doesn't remove the rect that was declared for the sprite. Note, it also can go through more than one enemy, even though the bullet is deleted. Any help is appreciated. Thanks!
EDIT:
I found out what the problem was. I had the shoot method set in a schedule:#selector method, with no set interval. That meant that it would fire bullets 60fps fast. So I was getting TWO bullets with ONE click. They were so close together, that it took me a while to notice it. I won't make that mistake again!!!
Are you using the following code? (from How To Make A Simple iPhone Game with Cocos2D Tutorial)
- (void)update:(ccTime)dt {
NSMutableArray *projectilesToDelete = [[NSMutableArray alloc] init];
for (CCSprite *projectile in _projectiles) {
CGRect projectileRect = CGRectMake(
projectile.position.x - (projectile.contentSize.width/2),
projectile.position.y - (projectile.contentSize.height/2),
projectile.contentSize.width,
projectile.contentSize.height);
NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
for (CCSprite *target in _targets) {
CGRect targetRect = CGRectMake(
target.position.x - (target.contentSize.width/2),
target.position.y - (target.contentSize.height/2),
target.contentSize.width,
target.contentSize.height);
if (CGRectIntersectsRect(projectileRect, targetRect)) {
[targetsToDelete addObject:target];
}
}
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
}
if (targetsToDelete.count > 0) {
[projectilesToDelete addObject:projectile];
}
[targetsToDelete release];
}
for (CCSprite *projectile in projectilesToDelete) {
[_projectiles removeObject:projectile];
[self removeChild:projectile cleanup:YES];
}
[projectilesToDelete release];
}
whenever an 'enemy' spawns where a bullet was deleted, the enemy is automatically deleted, too.
It sounds that the bullet is removed from the layer, but it is not removed from _projectiles array.
[_projectiles removeObject:projectile];
Are you sure that this code works?
Rect is not a seperate entity from your bullet. Rect is the property associated with the bullet. As soon as your "bullet is deleted" the rect will no longer be valid.
What you should be looking at is your collision checking code.
You probably want to surround your bullet collision check code with a condition like:
if(bullet exists)
{
check for collision
}
Since you haven't posted code I could only post pseudo code here. Maybe if you post your collision checking code I could show you in more detail.

count the number of time of touches

I have a game and I want that every time an image(image1) touchs another image(image2) a counter count one, if it touches a second time it becomes two. So it's something that counts. How can I do this?
Is this a collision detection? This link may help... collision detection
So you may have to write a collision detection method. Then each time it collide, you increment the count.
- (BOOL)collisionCheck:(UIImage *)image1 withImage:(UIImage *)image2 {
return CGRectIntersectsRect(image1.frame, image2.frame);
}
// then in game loop
// code that move the image here
if ([self collisionCheck:image1 withImage:image2] == YES) {
// code that bounce the image here
count++;
}

Stalling in a game loop and removing sprites naturally

I'm making a game with cocos2d and I have a bunch of sprites that I would like to delete. For example I might have a bunch of characters on the screen but when my game is over I would like to clean them up. Right now I have created a special effect (particle system) as a distraction, but because it is transparent and does not cover all of the screen you can see through and watch the sprites disappear as I remove them from the layer.
Also because the instructions execute so fast to the user it appears as if the sprites disappear before the particle effect begins!
Any suggestions on my 2 problems? Thanks.
NSMutableArray *toRemove = [[NSMutableArray alloc] init]; // array of sprites that I collect to remove
spriteCount = 0;
if([self findAllSprites:parent forRemoval:toRemove] > 0){ // is there is at least one sprite to delete. If not then don't do anything
[self specialEffect]; // runs for maybe 3 seconds.
// how can I stall here so that the sprites aren't removed "instantaneously"?
for (Character* aCharacter in toRemove) {
[aCharacter.parent remove:aCharacter];
}
}
You can delay the removal action using performSelector:withObject:afterDelay:. For example:
NSMutableArray *toRemove = [[NSMutableArray alloc] init]; // array of sprites that I collect to remove
spriteCount = 0;
if([self findAllSprites:parent forRemoval:toRemove] > 0){ // is there is at least one sprite to delete. If not then don't do anything
[self specialEffect]; // runs for maybe 3 seconds.
[self performSelector:#selector(removeSprites:) withObject: toRemove afterDelay:1.0];
}
[toRemove release];
- (void) removeSprites: (NSArray*) toRemove
{
for (Character* aCharacter in toRemove) {
[aCharacter.parent remove:aCharacter];
}
}
Note that performSelector:withObject:afterDelay: will retain the toRemove object and keep it alive until after it calls removeSprites, so you don't have to do anything special with toRemove (except that you still need to release it as shown since you own it as well).
You need to do your 'special effect' in a thread, so that it runs alongside your sprite remove. Lookup NSThread for more information, but this will enable you to synchronize the two processes.