I tried so much methods but i didn't stop the cats when begin contacts.Here is node moving method:
[self enumerateChildNodesWithName:#"cat" usingBlock:^(SKNode *node, BOOL *stop){
SKSpriteNode *tempCat = (SKSpriteNode *) node;
float actionDuration = 0.1;
CGPoint offset = CGPointSubtract(_zombie.position, tempCat.position);
CGPoint direction = CGPointNormalize(offset);
CGPoint amountToMovePerSec = CGPointMultiplyScalar(direction, CAT_MOVE_POINTS_PER_SEC);
CGPoint amountToMove = CGPointMultiplyScalar(amountToMovePerSec, actionDuration);
node.position = CGPointMake(node.position.x+amountToMove.x, node.position.y+amountToMove.y);
_velocityCat = CGPointMultiplyScalar(direction, CAT_MOVE_POINTS_PER_SEC);
[self rotateNode:tempCat toFace:_velocityCat rotateRadiansPerSec:CAT_ROTATE_RADIANS_PER_SEC];
How can I stop cat when begin contact?
-(void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (enemyCategory | catsCategory)) {
[self enumerateChildNodesWithName:#"cat" usingBlock:^(SKNode *node, BOOL *stop) {
if ([contact.bodyA.node isEqual:node] || [contact.bodyB.node isEqual:node])
{
node.physicsBody = NO;
SKAction *wait = [SKAction waitForDuration:2];
SKAction *catDie = [SKAction runBlock:^{
[node removeFromParent];
}];
SKAction *animation = [SKAction sequence:#[wait, catDie]];
[self runAction:animation];
}
}]; NSLog(#"test 1");
}
Enumerating over all cat nodes is not necessary since you can get the node involved in the contact from the SKPhysicsContact object. The following shows how to do that...
EDIT: you can change the cat node's name to prevent it from chasing the zombie
-(void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (enemyCategory | catsCategory)) {
SKNode *node = contact.bodyA.node;
if (contact.bodyB.categoryBitMask == catsCategory) {
node = contact.bodyB.node;
}
// One way to stop the cat from chasing zombie is by changing its name
node.name = #"not cat";
}
}
Related
I have two SKSpriteNode first Hero
+(id)hero
{
NSMutableArray *walkFrames = [NSMutableArray array];
SKTextureAtlas *heroAnimatedAtlas = [SKTextureAtlas atlasNamed:#"HeroImages"];
int numImages = (int)heroAnimatedAtlas.textureNames.count;
for (int i=1; i <= numImages; i++) {
NSString *textureName = [NSString stringWithFormat:#"hero%d", i];
SKTexture *temp = [heroAnimatedAtlas textureNamed:textureName];
[walkFrames addObject:temp];
}
Hero *hero = [Hero spriteNodeWithTexture:walkFrames[0]];
hero.heroWalkingFrames = walkFrames;
hero.name =#"Hero";
hero.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:hero.size];
hero.physicsBody.categoryBitMask = heroCategory;
hero.physicsBody.categoryBitMask = obstacleCategory | groundCategory | homeCategory | ~goodiesCategory;
return hero;
}
and second is Coin
SKSpriteNode *coin = [SKSpriteNode spriteNodeWithImageNamed:#"coin"];
coin.size = CGSizeMake(10,10);
coin.position = CGPointMake(100,100);
coin.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:coin.size];
coin.physicsBody.contactTestBitMask = coinCategory;
coin.physicsBody.dynamic=NO;
coin.name = #"coin";
[self.world addChild:coin];
And I am able to get collision detection by
if([contact.bodyA.node.name isEqual: #"coin"] || [contact.bodyB.node.name isEqual: #"coin"])
{
//[self LevelComplete];
SKNode* coinNode ;
if ([contact.bodyA.node.name isEqual: #"coin"]) {
coinNode=contact.bodyA.node;
}
else{
coinNode=contact.bodyB.node;
}
[coinNode removeFromParent];
NSLog(#"Coin touched");
}
Now my problem is every time hero jump and touch the coin it will go down to ground instead to continue jump and reach the height that it should, I know I am missing something here but don't know what it is, So anyone can please show me the right direction to correct this effect .
Create an extra "nilCategory" and set the collisionBitMask of your coin..
coin.physicsBody.collisionBitMask = nilCategory;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm using a tutorial to create a game where if the rocketship is hit by an asteroid, the ship will show an image using SKEmitterNode and will blink then play a sound. This part of the game is working, however the game will not end. How do I fix this error?
Here's my code where I believe the error is
- (void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (asteroidCategory | shipCategory)) {
SKNode *asteroid, *spaceship;
if (contact.bodyA.categoryBitMask == shipCategory) {
spaceship = contact.bodyA.node;
asteroid = contact.bodyB.node;
[self runAction:[SKAction playSoundFileNamed:#"explosion_large.caf" waitForCompletion:NO]];
SKAction *blink = [SKAction sequence:#[[SKAction fadeOutWithDuration:0.1],
[SKAction fadeInWithDuration:0.1]]];
SKAction *blinkForTime = [SKAction repeatAction:blink count:6];
[self.spaceship runAction:blinkForTime];
NSString *explosionPath = [[NSBundle mainBundle] pathForResource:#"RocketFlame" ofType:#"sks"];
SKEmitterNode *explosion = [NSKeyedUnarchiver unarchiveObjectWithFile:explosionPath];
CGVector emitterVector = CGVectorMake(spaceship.frame.size.width * 2.0, 0);
explosion.particlePositionRange = emitterVector;
[self.spaceship addChild:explosion];
}
else {
spaceship = contact.bodyB.node;
asteroid = contact.bodyA.node;
[self runAction:[SKAction playSoundFileNamed:#"explosion_large.caf" waitForCompletion:NO]];
SKAction *blink = [SKAction sequence:#[[SKAction fadeOutWithDuration:0.1],
[SKAction fadeInWithDuration:0.1]]];
// SKAction *blinkForTime = [SKAction repeatAction:blink count:6];
[self.spaceship runAction:blink];
NSString *explosionPath = [[NSBundle mainBundle] pathForResource:#"RocketFlame" ofType:#"sks"];
SKEmitterNode *explosion = [NSKeyedUnarchiver unarchiveObjectWithFile:explosionPath];
CGVector emitterVector = CGVectorMake(spaceship.frame.size.width * 2.0, 0);
explosion.particlePositionRange = emitterVector;
[self.spaceship addChild:explosion];
}
[self asteroid:(SKSpriteNode *) asteroid didCollideWithasteroid:(SKSpriteNode *) spaceship];
}
else if (collision == (projectileCategory| asteroidCategory)) {
SKNode *Projectile, *asteroid;
if (contact.bodyA.categoryBitMask == asteroidCategory) {
Projectile= contact.bodyA.node;
asteroid = contact.bodyB.node;
}
else {
Projectile = contact.bodyB.node;
asteroid = contact.bodyA.node;
}
[self projectile:(SKSpriteNode *) Projectile didCollideWithasteroid:(SKSpriteNode *) asteroid];
self.asteroidsDestroyed++;
if (self.asteroidsDestroyed > 30) {
SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size won:NO];
[self.view presentScene:gameOverScene transition: reveal];
}
}
}
The game is not ending because you are not calling the end-game transition in case of the collsion between the spaceship and asteroid as you do in the case where the collision is between the projectile and the asteroid.
- (void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (asteroidCategory | shipCategory)) {
SKNode *asteroid, *spaceship;
if (contact.bodyA.categoryBitMask == shipCategory) {
spaceship = contact.bodyA.node;
asteroid = contact.bodyB.node;
}
else {
spaceship = contact.bodyB.node;
asteroid = contact.bodyA.node;
}
[self runAction:[SKAction playSoundFileNamed:#"explosion_large.caf" waitForCompletion:NO]];
SKAction *blink = [SKAction sequence:#[[SKAction fadeOutWithDuration:0.1],
[SKAction fadeInWithDuration:0.1]]];
SKAction *blinkForTime = [SKAction repeatAction:blink count:6];
[self.spaceship runAction:blinkForTime];
NSString *explosionPath = [[NSBundle mainBundle] pathForResource:#"RocketFlame" ofType:#"sks"];
SKEmitterNode *explosion = [NSKeyedUnarchiver unarchiveObjectWithFile:explosionPath];
CGVector emitterVector = CGVectorMake(spaceship.frame.size.width * 2.0, 0);
explosion.particlePositionRange = emitterVector;
[self.spaceship addChild:explosion];
[self asteroid:(SKSpriteNode *) asteroid didCollideWithasteroid:(SKSpriteNode *) spaceship]; //What does this do?
[self runAction:[SKAction sequence:#[[SKAction waitForDuration:3.0], [SKAction runBlock:^{
[self gameEndedWithSuccess:NO];
}]]]];
}
else if (collision == (projectileCategory| asteroidCategory)) {
SKNode *Projectile, *asteroid;
if (contact.bodyA.categoryBitMask == asteroidCategory) {
Projectile= contact.bodyA.node;
asteroid = contact.bodyB.node;
}
else {
Projectile = contact.bodyB.node;
asteroid = contact.bodyA.node;
}
[self projectile:(SKSpriteNode *) Projectile didCollideWithasteroid:(SKSpriteNode *) asteroid];
self.asteroidsDestroyed++;
if (self.asteroidsDestroyed > 30) {
[self gameEndedWithSuccess:YES];
}
}
}
-(void) gameEndedWithSuccess:(BOOL)success
{
SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size won:success];
[self.view presentScene:gameOverScene transition: reveal];
}
I'm sorry to post this, I know it has been asked before but I have tried the previous solutions and nothing has seemed to work.
The problem that I'm having is that I use both didBeginContact and didEndContact to establish whether or not my sprite is touching the ground.
The sprite has a BOOL named grounded that determines this state. Basically I want to know if its on the ground when its touching a platform. The results that I am getting are a constant battle between establishing contact with the platform and then losing contact immediately, its very frustrating. Here's what I have so far:
-(Player *)createPlayer
{
...
sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:player.size];
sprite.physicsBody.mass = 0.02;
sprite.physicsBody.restitution = 0;
sprite.physicsBody.categoryBitMask = playerCategory;
sprite.physicsBody.collisionBitMask = platformCategory;
sprite.physicsBody.contactTestBitMask = platformCategory;
sprite.physicsBody.usesPreciseCollisionDetection = YES;
return sprite;
}
-(SKSpriteNode *)createPlatform
{
SKSpriteNode *platform = [[SKSpriteNode alloc] initWithColor:[SKColor grayColor] size:CGSizeMake(100,25)];
platform.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:player.size];
platform.dynamic = NO;
platform.physicsBody.categoryBitMask = platformCategory;
platform.physicsBody.collisionBitMask = playerCategory;
platform.physicsBody.contactTestBitMask = playerCategory;
return platform;
}
-(void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody;
if(contact.bodyA.categoryBitMask < contact.B.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if((firstBody.categoryBitMask & playerCategory) != 0)
{
Player *player = firstBody.node;
if((secondBody.categoyBitMask & platformCategoy) != 0)
{
NSLog(#"Connection Established");
player.grounded = YES;
}
}
}
-(void)didEndContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody;
if(contact.bodyA.categoryBitMask < contact.B.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if((firstBody.categoryBitMask & playerCategory) != 0)
{
Player *player = firstBody.node;
if((secondBody.categoyBitMask & platformCategoy) != 0)
{
NSLog(#"Connection Lost");
player.grounded = NO;
}
}
}
Basically the end result of this looks like this when I examine the log:
Contact Established
Contact Lost
Contact Established
Contact Lost
Thank you in advance for any help you offer, I am completely stumped.
-(void)didEndContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision != (playerCategory | platformCategory)) {
SKNode *node = contact.bodyA.node;
if (contact.bodyB.categoryBitMask == platformCategory) {
node = contact.bodyB.node;
}
NSLog(#"Connection Lost");
player.grounded = NO;
}
I am trying to make a SpriteKit game but I cannot figure out or find a good example of multiple collision detection.
My code:
-(void)didBeginContact:(SKPhysicsContact *)contact{
SKPhysicsBody *firstBody;
SKPhysicsBody *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if ((firstBody.categoryBitMask & bulletCategory) != 0) {
[self updateScore];
SKNode *applenode = [self childNodeWithName:(#"Apple")];
applenode.removeFromParent;
[self updateScore];
SKScene *sampleScene = [[Level2 alloc] initWithSize:self.size];
SKTransition *transition = [SKTransition flipVerticalWithDuration:0.5];
[self.view presentScene:sampleScene transition:transition];
}
Worked great for one collision but I cannot seem to get it to work for multiple.
//for multiple collision you can add code like something that
(void)didBeginContact:(SKPhysicsContact *)contact
{
CGPoint contactPoint=CGPointMake(0, 0);
//multiple collision
if (contact.bodyA.categoryBitMask || contact.bodyB.categoryBitMask)
{
//first collision
if(([contact.bodyA.node.name isEqualToString:#"hero"] && [contact.bodyB.node.name isEqualToString:#"coin"] ) || ([contact.bodyA.node.name isEqualToString:#"coin"] && [contact.bodyB.node.name isEqualToString:#"hero"]) )
{
if([contact.bodyA.node.name isEqualToString:#"coin"] )
{
[contact.bodyA.node removeFromParent];
}
else
{
[contact.bodyB.node removeFromParent];
}
}
//second collision
else if(([contact.bodyA.node.name isEqualToString:#"hero"] && [contact.bodyB.node.name isEqualToString:#"enemy"] ) || ([contact.bodyA.node.name isEqualToString:#"enemy"] && [contact.bodyB.node.name isEqualToString:#"hero"]) )
{
if([contact.bodyA.node.name isEqualToString:#"hero"] )
{
[contact.bodyA.node removeFromParent];
}
else
{
[contact.bodyB.node removeFromParent];
}
}
}
}
I have to remove one when contact with enemy target.I tried this,but this removes all cats.I have remove only contact cat.
-(void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (enemyCategory | catsCategory)) {
[self enumerateChildNodesWithName:#"cats" usingBlock:^(SKNode *node, BOOL *stop) {
[node removeFromParent];
}];
NSLog(#"test 1");
}
The code:
[self enumerateChildNodesWithName:#"cats" usingBlock:^(SKNode *node, BOOL *stop) {
[node removeFromParent];
}];
Will remove all nodes whose name property is #"cats". Hence it is removing all the cats on screen.
You need to check whether the contact cat is the same as the one being enumerated, and then remove it.
[self enumerateChildNodesWithName:#"cats" usingBlock:^(SKNode *node, BOOL *stop) {
if ([contact.bodyA.node isEqual:node] || [contact.bodyB.node isEqual:node])
{
[node removeFromParent];
stop = YES;
}
}];
You can read more about the enumerateChildNodesWithName:usingBlock: method here.