Loss of Contact - ios

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

Related

Code only working on iOS 7

Hi I've been making a game with the SpriteKit framework and I set a collision bit mask when 2 objects collide. One of those objects, let's say the object A, can have 2 states: black or normal so when the two objects collide and the A object is on normal state it adds a point but when the two objects collide and the A object is on black state the game is over. This code is working fine for me on iOS 7 but when I run it on iOS 8 and if the A object state is black it acts like if it's on normal state and adds a point. Why this is happening? Is different the code for iOS 7 and 8? Please can anyone help me, here's the 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;
}
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (firstBody.categoryBitMask == objectACategory && secondBody.categoryBitMask == objectBCategory) {
NSLog(#"OBJECT A CAUGHT");
[firstBody.node removeFromParent];
[GameState sharedInstance].score++;
_scoreLabel.text = [NSString stringWithFormat:#"%d", [GameState sharedInstance].score];
_scoreLabel_2.text = [NSString stringWithFormat:#"%d", [GameState sharedInstance].score];
gameUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"sound " ofType:#"wav"]];
_gameSound = [[AVAudioPlayer alloc] initWithContentsOfURL:gameUrl error:nil];
_gameSound.delegate = self;
[_gameSound play];
if ([[firstBody.node.userData valueForKey:#"Black"] boolValue]) {
[self removeActionForKey:origamiFallKey];
NSLog(#"YOU LOSE");
[self gameOver];
[self runAction:[SKAction sequence:#[
[SKAction waitForDuration:0.5],
[SKAction performSelector:#selector(removeWhenLose) onTarget:self]]]];
}
}
For setting the state I used this code in the method which adds a objectA:
// Black
if(arc4random_uniform(6) == 0) {
_objectA.texture = [SKTexture textureWithImageNamed:#"blackImage.png"];
_objectA.physicsBody.collisionBitMask = objectACategory;
_objectA.userData = [[NSMutableDictionary alloc] init];
[_objectA.userData setValue:#YES forKey:#"Black"];
blackObjectA = YES;
}
I finally solved this problem. First I had to create the collision variable:
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
And with write the collisions using this:
-(void)didBeginContact:(SKPhysicsContact *)contact {
if (collision == (objectACategory | objectBCategory)) {
if ([[firstBody.node.userData valueForKey:#"Black"] boolValue]){
[self removeActionForKey:fallKey];
NSLog(#"YOU LOSE");
[self gameOver];
[self runAction:[SKAction sequence:#[
[SKAction waitForDuration:0.5],
[SKAction performSelector:#selector(removeWhenLose) onTarget:self]]]];
} else {
[firstBody.node removeFromParent];
[GameState sharedInstance].score++;
_scoreLabel.text = [NSString stringWithFormat:#"%d", [GameState sharedInstance].score];
_scoreLabel_2.text = [NSString stringWithFormat:#"%d", [GameState sharedInstance].score];
gameUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"origami " ofType:#"wav"]];
_gameSound = [[AVAudioPlayer alloc] initWithContentsOfURL:gameUrl error:nil];
_gameSound.delegate = self;
[_gameSound play];
}
}

end game not working [closed]

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];
}

adding second to timer iOS game sprite kit

I am trying to add a few seconds to countdown timer each time when enemy and player node contacts.
Also when the player reach to some certain point I want player to pass to another level. I am sending part of the code . Could anybody help me to solve this problem. By the way because I am new to programming my code is a little hard to read . Sorry for that.
Thanks
-(void)update:(CFTimeInterval)currentTime{
if (startGamePlay){
startTime = currentTime;
startGamePlay = NO;
}
countDownInt = 10.0 - (int)(currentTime-startTime);
if(countDownInt > 0 ){ //if counting down to 0 show counter
countDown.text = [NSString stringWithFormat:#"%i", countDownInt];
}
else if (countDownInt == 0){
countDown.text =#"0";
Level2 *level2 = [Level2 sceneWithSize:self.frame.size];
SKTransition *transition = [SKTransition fadeWithDuration:0.5];
[self.view presentScene:level2 transition:transition];
}
}
- (void) didBeginContact:(SKPhysicsContact *)contact {
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA;
secondBody = contact.bodyB;
} else {
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if ( firstBody.categoryBitMask == CollisionCategoryBrick && secondBody.categoryBitMask == CollisionCategoryShark ) {
NSLog(#"BRICK");
[contact.bodyB.node removeFromParent];
} else if ( firstBody.categoryBitMask == CollisionCategoryWaterBall && secondBody.categoryBitMask == CollisionCategoryShark ) {
NSLog(#"BALL");
countDownInt = [countDown.text intValue];
[contact.bodyA.node removeFromParent];
[self addPoints:PointsPerHit];
if (![ self childNodeWithName:#"WATERBALLTL"]) {
[self addWaterBallTopLeft];
}
if (![ self childNodeWithName:#"WATERBALLTR"]) {
[self addWaterBallTopRight];
}
if (![ self childNodeWithName:#"WATERBALLBL"]) {
[self addWaterBallBottomLeft];
}
if (![ self childNodeWithName:#"WATERBALLBR"]) {
[self addWaterBallBottomRight];
}
}
NSLog(#"%lu", (unsigned long)[self.children count]);
}
#import "HudNode.h"
#implementation HudNode
{
SKLabelNode *countDown;
BOOL startGamePlay;
NSTimeInterval startTime;
}
+ (instancetype) hudAtPosition:(CGPoint)position inFrame:(CGRect)frame {
HudNode *hud = [self node];
hud.position = position;
hud.zPosition = 10;
hud.name = #"HUD";
SKLabelNode *scoreLabel = [SKLabelNode labelNodeWithFontNamed:#"Futura-CondensedExtraBold"];
scoreLabel.name = #"Score";
scoreLabel.text = #"0";
scoreLabel.fontSize = 24;
scoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
scoreLabel.position = CGPointMake(frame.size.width-20, -10);
scoreLabel.zPosition = 12;
[hud addChild:scoreLabel];
SKLabelNode *countDown = [SKLabelNode labelNodeWithFontNamed:#"Futura-Medium"];
countDown.fontSize = 50;
countDown.position = CGPointMake(30, -10);
countDown.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter; //good for positioning with other sprites
countDown.fontColor = [SKColor whiteColor ];
countDown.name = #"countDown";
countDown.zPosition = 100;
[hud addChild:countDown];
return hud;
}
- (void) addPoints:(NSInteger)points {
self.score += points;
SKLabelNode *scoreLabel = (SKLabelNode *) [self childNodeWithName:#"Score"];
scoreLabel.text = [NSString stringWithFormat:#"Score:%li", (long)self.score];
}
Create a boolean flag that the update method checks to see if it should add seconds.
Add the following variable and set self.addSeconds = NO; initially:
#property (nonatomic) BOOL addSeconds;
Set self.addSeconds =YES; in the method where your player hits your enemy:
Add the following to the very beginning of the Update:
if(self.addSeconds == YES)
{
CountDownInt+= 5 //Change this to add as many seconds as you want
self.addSeconds=NO;
}
This should do the trick.

I can't stop node on begin contact

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";
}
}

Multiple collisions spritekit

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];
}
}
}
}

Resources