Code only working on iOS 7 - ios

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

Related

iOS SpriteKit animation not working

I am new to the iOS native game development. I am trying to create animation using some frames for Ideal state for the character. I am following tutorial from the Ray's Website. Look like I am doing everything fine but I can't see animation in working. Only first frame (default) is visible all the time. I debug the code & it's indeed visiting blinking player method where all 3 frames are also present, but nothing happening on screen.
It will be great if someone can guide/help me identify the issue.
#implementation GameScene
{
NSArray *_playerBlinkFrames;
}
// Player
SKNode *_player;
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
[self createPlayer];
}
return self;
}
- (void) createPlayer
{
SKTextureAtlas *playerAnimatedAtlas = [SKTextureAtlas atlasNamed:#"Assets"];
_player = [SKNode node];
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:#"Idle"];
[_player addChild:sprite];
[sprite setName:#"Ball"];
NSMutableArray *blinkFrames = [NSMutableArray array];
SKTexture *temp = [playerAnimatedAtlas textureNamed:#"Idle.png"];
SKTexture *temp2 = [playerAnimatedAtlas textureNamed:#"Blink.png"];
SKTexture *temp3 = [playerAnimatedAtlas textureNamed:#"LookRight.png"];
[blinkFrames addObject:temp];
[blinkFrames addObject:temp2];
[blinkFrames addObject:temp3];
_playerBlinkFrames = blinkFrames;
_player.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:_player];
[self blinkingPlayer];
}
-(void)blinkingPlayer
{
[_player runAction:[SKAction repeatActionForever:
[SKAction animateWithTextures:_playerBlinkFrames
timePerFrame:0.3f
resize:NO
restore:YES]] withKey:#"blinkingInPlacePlayer"];
return;
}
Thanks.
Try this:
// Player
SKSpriteNode *_player;
//..//
SKTextureAtlas *playerAnimatedAtlas = [SKTextureAtlas atlasNamed:#"Assets"];
NSMutableArray *blinkFrames = [NSMutableArray array];
SKTexture *temp = [playerAnimatedAtlas textureNamed:#"Idle.png"];
SKTexture *temp2 = [playerAnimatedAtlas textureNamed:#"Blink.png"];
SKTexture *temp3 = [playerAnimatedAtlas textureNamed:#"LookRight.png"];
[blinkFrames addObject:temp];
[blinkFrames addObject:temp2];
[blinkFrames addObject:temp3];
_playerBlinkFrames = blinkFrames;
SKTexture *tempSprite = _playerBlinkFrames[0];
_player = [SKSpriteNode spriteNodeWithTexture:tempSprite];
I've not tested it, but i think you have create a SKNode player covered by a spritenode.
let me know

How to detect SKSpriteNode Contact but do not react?

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;

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.

Loss of Contact

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

Resources