Removing specific nodes in SpriteKit - ios

Need some help as a beginner: I've got different nodes: 4 squares (sprite1) and 1 counter (counterLabel, counts the nodes, which have been removed). I want to remove the 4 squares by touching them. With the code below the squares can be removed, but also the counter. Strangely enough, because I tried to address the square nodes (sprite1) exclusively. Is there any possibility to remove the square nodes (sprite 1) exclusively?
#implementation GameScene {
BOOL updateLabel;
SKLabelNode *counterLabel;
}
int x;
int y;
int counter;
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]){
self.backgroundColor = [SKColor /*colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0*/ whiteColor];
counter = 0;
updateLabel = false;
counterLabel = [SKLabelNode labelNodeWithFontNamed:#"Chalkduster"];
counterLabel.name = #"myCounterLabel";
counterLabel.text = #"0";
counterLabel.fontSize = 48;
counterLabel.fontColor = [SKColor greenColor];
//counterLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
//counterLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeBottom;
counterLabel.position = CGPointMake(50,50); // change x,y to location you want
//counterLabel.zPosition = 900;
[self addChild: counterLabel];
}
return self;
}
-(void) didMoveToView:(SKView *)view {
SKTexture *texture1 = [SKTexture textureWithImageNamed:#"square"];
for (int i = 0; i < 4; i++) {
x = arc4random()%668;
y = arc4random()%924;
SKSpriteNode *sprite1 = [SKSpriteNode spriteNodeWithTexture:texture1];
sprite1.position = CGPointMake(x, y);
sprite1.name = #"square";
[self addChild:sprite1];
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
NSArray *nodes = [self nodesAtPoint: [touch locationInNode: self]];
for (SKNode *sprite1 in nodes) {
[sprite1 removeFromParent];
counter ++;
updateLabel = true;
}
}
-(void)update:(CFTimeInterval)currentTime {
if(updateLabel == true){
counterLabel.text = [NSString stringWithFormat:#"%i",counter];
updateLabel = false;
}
}
#end

you should use the property name of SKSpriteNode
in this case you can do:
for (SKNode *sprite1 in nodes) {
if(![sprite1.name isEqualToString:#"myCounterLabel"]) {
[sprite1 removeFromParent];
}
counter ++;
updateLabel = true;
}
So if the SKNode name is different to the name of counterLabel, then removeFromParent.

Related

Objective C - SpriteKit - Unable to detect contact between ball and paddle node

I am trying to detect the collision between the ball node and either one of the paddle nodes but the message to confirm the collision is not being fired.
Could somebody help me understand where I am going wrong?
//categories for detecting contacts between nodes
static const uint32_t ballCategory = 0x1 << 0;
static const uint32_t paddleCategory = 0x1 << 1;
#interface GameScene ()
#property BOOL contentCreated;
#property(nonatomic) UITouch *playerOnePaddleControlTouch;
#property(nonatomic, weak) UITouch *paddleTouch;
#property(nonatomic) SKSpriteNode *paddleOneNode;
#property(nonatomic) SKSpriteNode *paddleTwoNode;
#property(nonatomic) SKSpriteNode *ballNode;
#property(nonatomic) SKLabelNode *playerOneScoreNode;
#property(nonatomic) SKLabelNode *playerTwoScoreNode;
#property(nonatomic) NSInteger playerOneScore;
#property(nonatomic) NSInteger playerTwoScore;
#end
#implementation GameScene
- (void)didMoveToView:(SKView *)view
{
if (!self.contentCreated)
{
[self createSceneContents];
self.contentCreated = YES;
}
}
- (void) createSceneContents
{
self.backgroundColor = [SKColor blackColor];
self.scaleMode = SKSceneScaleModeAspectFit;
[self addChild: [self newGameNode]];
self.physicsWorld.gravity = CGVectorMake(0, 0);
self.physicsWorld.contactDelegate = self;
// Create border around screen
SKPhysicsBody* borderBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
self.physicsBody = borderBody;
self.physicsBody.friction = 0;
// Create Paddle One
SKSpriteNode *paddleOne = [self newPaddle];
paddleOne.position = CGPointMake(CGRectGetMidX(self.frame)/8, CGRectGetMidY(self.frame));
paddleOne.name = #"paddleOne";
paddleOne.physicsBody.categoryBitMask = paddleCategory;
paddleOne.physicsBody.contactTestBitMask = ballCategory;
[self addChild:paddleOne];
// Create Paddle Two
SKSpriteNode *paddleTwo = [self newPaddle];
paddleTwo.position = CGPointMake((CGRectGetMaxX(self.frame) - CGRectGetMidX(self.frame) / 8), CGRectGetMidY(self.frame));
paddleTwo.name = #"paddleTwo";
paddleTwo.physicsBody.categoryBitMask = paddleCategory;
paddleTwo.physicsBody.contactTestBitMask = ballCategory;
[self addChild:paddleTwo];
// Create ball
SKSpriteNode *ball = [self newBall];
ball.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:ball];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.frame.size.width/2];
ball.physicsBody.friction = 1.0f; //normally 1.0f
ball.physicsBody.restitution = 1.0f; //normally 1.0f
ball.physicsBody.linearDamping = 0.0f; //normally 0.0f
ball.physicsBody.allowsRotation = NO;
ball.physicsBody.categoryBitMask = ballCategory;
ball.physicsBody.contactTestBitMask = paddleCategory;
[ball.physicsBody applyImpulse:CGVectorMake(1.0f, -1.0f)];
// Create score labels
self.playerOneScoreNode = [SKLabelNode labelNodeWithFontNamed:#"Helvetica"];
self.playerTwoScoreNode = [SKLabelNode labelNodeWithFontNamed:#"Helvetica"];
self.playerOneScoreNode.fontColor = self.playerOneScoreNode.fontColor = [SKColor whiteColor];
self.playerOneScoreNode.fontSize = self.playerTwoScoreNode.fontSize = 90;
self.playerOneScoreNode.position = CGPointMake((CGRectGetWidth(self.frame))* 0.25, (CGRectGetHeight(self.frame)) - 80);
self.playerTwoScoreNode.position = CGPointMake((CGRectGetWidth(self.frame)) * 0.75, (CGRectGetHeight(self.frame)) - 80);
[self addChild:self.playerOneScoreNode];
[self addChild:self.playerTwoScoreNode];
// Set Scores to 0
self.playerOneScore = 7;
self.playerTwoScore = 0;
self.playerOneScoreNode.text = [NSString stringWithFormat:#"%ld",self.playerOneScore];
self.playerTwoScoreNode.text = [NSString stringWithFormat:#"%ld",self.playerTwoScore];
}
- (SKSpriteNode *)newPaddle
{
SKSpriteNode *paddle = [[SKSpriteNode alloc]initWithColor:[SKColor whiteColor] size:CGSizeMake(16,64)];
return paddle;
}
- (SKSpriteNode *)newBall
{
SKSpriteNode *ball = [[SKSpriteNode alloc]initWithColor:[SKColor redColor] size:CGSizeMake(16, 16)];
return ball;
}
- (SKLabelNode *) newGameNode
{
SKLabelNode *gameNode = [SKLabelNode labelNodeWithFontNamed:#"Chalkduster"];
gameNode.text = #" Pong";
gameNode.fontSize = 50;
gameNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
gameNode.fontColor = [SKColor blueColor];
return gameNode;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.paddleTouch = [touches anyObject];
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInNode:self];
SKNode *paddleOne = [self childNodeWithName:#"paddleOne"];
SKNode *paddleTwo = [self childNodeWithName:#"paddleTwo"];
if (touchPoint.x < CGRectGetMidX(self.frame)) {
paddleOne.position = CGPointMake(paddleOne.position.x, touchPoint.y);
}
else
{
paddleTwo.position = CGPointMake(paddleTwo.position.x, touchPoint.y);
}
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if (self.paddleTouch) {
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInNode:self];
CGPoint previousPoint = [touch previousLocationInNode:self];
SKSpriteNode *paddleOne = (SKSpriteNode*)[self childNodeWithName:#"paddleOne"];
SKSpriteNode *paddleTwo = (SKSpriteNode*)[self childNodeWithName:#"paddleTwo"];
int paddleOneY = paddleOne.position.y + (touchPoint.y - previousPoint.y);
int paddleTwoY = paddleTwo.position.y + (touchPoint.y - previousPoint.y);
if (touchPoint.x < CGRectGetMidX(self.frame)) {
paddleOne.position = CGPointMake(paddleOne.position.x, paddleOneY);
}
else
{
paddleTwo.position = CGPointMake(paddleTwo.position.x, paddleTwoY);
}
}
}
// React to collision's between nodes/bodies
// Currently not working....need to understand this set of 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 == ballCategory && secondBody.categoryBitMask == paddleCategory)
{
NSLog(#"Ball has touched Paddle");
}
}
#end
Your paddleOne and paddleTwo does not have SKPhysicsBody.
Add these (change size of physics body if needed)
paddleOne.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: paddleOne.size];
paddleTwo.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: paddleTwo.size];

Sprite not keeping track of count

The following code I'm using is to end the game when I my number of balls in the scene reaches zero. Now I'm not getting any error when I put the code in but it doesn't do any thing as of counting the balls and reacting to that count. I am fairly new to sprite kit so I understand that this is a problem that comes so easy to others but this is the first time of worked with reacting to the count of a certain sprite in a scene so please help.
SKSpriteNode *ball;
int numberOfBalls = 3;
#implementation EasyScene
-(void)didBeginContact:(SKPhysicsContact *)contact {
if ([self isGameWon]) {
EasyEndGameScene *end = [EasyEndGameScene sceneWithSize:self.size];
[self.view presentScene:end transition:[SKTransition doorsCloseHorizontalWithDuration:1]];
}
}
-(BOOL)isGameWon {
int numberOfBalls = 3;
for (SKNode* node in self.children) {
if ([node.name isEqual: ball]) {
numberOfBalls = 0;
}
}
return numberOfBalls =0;
}
- (void) addBalls:(CGSize)size {
for (int i = 0; i < 3; i++) {
//create brick sprite from image
SKSpriteNode *ball = [SKSpriteNode spriteNodeWithImageNamed:#"ball-image"];
ball.name = #"ball";
//resize balls
ball.size = CGSizeMake(self.size.width/5.5, self.size.width/5.5);
//position and space out balls
int xPos = size.width/3 * (i+.5);
int yPos = self.size.height - (self.size.width/7);
ball.position = CGPointMake(xPos, yPos);
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width/2];
ball.physicsBody.categoryBitMask = ballCategory;
ball.physicsBody.contactTestBitMask = bottomEdgeCategory;
[self addChild:ball];
}
}
In the following code I got rid of the Global Variable and tested all nodes for the specified name of #"ball" and return YES if none were found:
static const uint32_t ballCategory = 1; //00000000000000000000000000000001
static const uint32_t edgeCategory = 2; //00000000000000000000000000000010
static const uint32_t bottomEdgeCategory = 4; //00000000000000000000000000000100
SKSpriteNode *ball;
#implementation EasyScene
-(void)didBeginContact:(SKPhysicsContact *)contact {
//create placeholder for the "non ball" object
SKPhysicsBody *notTheBall;
SKPhysicsBody *theBall;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
notTheBall = contact.bodyB;
theBall = contact.bodyA;
} else {
notTheBall = contact.bodyA;
theBall = contact.bodyB;
}
if (notTheBall.categoryBitMask == bottomEdgeCategory) {
NSLog(#"hit bottom edge");
// SKAction *playSFX = [SKAction playSoundFileNamed:#"gameover.mp3" waitForCompletion:NO];
// [self runAction:playSFX];
// EasyEndGameScene *end = [EasyEndGameScene sceneWithSize:self.size];
// [self.view presentScene:end transition:[SKTransition doorsCloseHorizontalWithDuration:1]];
// [GameState sharedInstance].score = 0;
// [gameMusic pause];
[theBall.node removeFromParent];
}
if ([self isGameWon]) {
EasyEndGameScene *end = [EasyEndGameScene sceneWithSize:self.size];
[self.view presentScene:end transition:[SKTransition doorsCloseHorizontalWithDuration:1]];
}
}
-(BOOL)isGameWon {
unsigned count = 0;
for (SKNode* node in self.children)
if ([node.name isEqual:ball])
count++;
return count == 0;
}
- (void) addBalls:(CGSize)size {
for (int i = 0; i < 3; i++) {
//create brick sprite from image
SKSpriteNode *ball = [SKSpriteNode spriteNodeWithImageNamed:#"ball-image"];
ball.name = #"ball";
//resize balls
ball.size = CGSizeMake(self.size.width/5.5, self.size.width/5.5);
//position and space out balls
int xPos = size.width/3 * (i+.5);
int yPos = self.size.height - (self.size.width/7);
ball.position = CGPointMake(xPos, yPos);
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width/2];
ball.physicsBody.categoryBitMask = ballCategory;
ball.physicsBody.contactTestBitMask = bottomEdgeCategory;
[self addChild:ball];
}
}
Remove the ball global variable, as it's not needed.
Test all nodes for the specified name of #"ball" and return YES if none were found:
-(BOOL)isGameWon {
for (SKNode* node in self.children)
if ([node.name isEqualToString:#"ball"])
return NO;
return YES;
}
I think it should be
return numberOfBalls == 0
in your isgameWon method
you forget an extra =

Having issues with touchesBegan method

I have my sound on logo showing up on the screen and the sound off logo appears when i test it. what I want it to do is change from sound on to sound off when I tap on it. The buttons do acknowledge the tap but nothing happens. I don't have much experience in change node images when they're tapped so I don't really know if I used the most efficient code. Can someone look over my code and see what's wrong? Thanks in advance!
#implementation MyScene
{
SKSpriteNode *soundLogo;
SKSpriteNode *soundOff;
}
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.zPosition = 0;
soundOff.alpha = 0;
//[self addChild:soundOff];
}
-(void) addSoundOn:(CGSize)size {
soundLogo = [SKSpriteNode spriteNodeWithImageNamed:#"soundLogo"];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
//soundLogo.alpha = 1;
soundLogo.zPosition = 100;
[self addChild:soundLogo];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"soundOn"]) {
soundOff.zPosition = 100;
soundOff.alpha = 1;
soundLogo.alpha = 0;
soundLogo.zPosition = 0;
// [node removeFromParent];
// [node addChild:soundOff];
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
soundLogo.zPosition = 100;
soundLogo.alpha = 1;
soundOff.alpha = 0;
soundOff.zPosition = 0;
// [node removeFromParent];
// [node addChild:soundLogo];
NSLog(#"sound off is pressed");
}
}
It seems nothing wrong in your addSoundOff and addSoundOn functions. What you can do as one of the solutions to change alpha and zPosition properties of SKSpriteNode . And also createsoundOff and soundLogo as instance variables under the implementation. So here is the all code:
#import "MyScene.h"
#implementation MyScene
{
SKSpriteNode *soundLogo;
SKSpriteNode *soundOff;
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
[self addSoundOn:self.size];
[self addSoundOff:self.size];
}
return self;
}
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.alpha = 0;
soundOff.zPosition = 0;
[self addChild:soundOff];
}
-(void) addSoundOn:(CGSize)size {
SKTexture *soundOn = [SKTexture textureWithImageNamed:#"soundLogo"];
soundLogo = [SKSpriteNode spriteNodeWithTexture:soundOn];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
soundLogo.zPosition = 100;
[self addChild:soundLogo];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//sound logo pressed to turn sound on/off
if ([node.name isEqualToString:#"soundOn"]) {
soundOff.alpha = 1;
soundOff.zPosition = 100;
soundLogo.alpha = 0;
soundLogo.zPosition = 0;
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
soundOff.alpha = 0;
soundOff.zPosition = 0;
soundLogo.alpha = 1;
soundLogo.zPosition = 100;
NSLog(#"sound off is pressed");
}
}
#end

How can i remove a SKSpriteNode from parent, when the background is the same color as the sprite?

Im making a game where the colour of a square will change every second and the background will also change colour every second, the user has to tap the square when it is the same colour as the background and the score will increase. But i cant work out how to do this.
This is the code i have so far:
#import "MyScene.h"
#implementation MyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
[self performSelector:#selector(backgrounds) withObject:nil ];
[self performSelector:#selector(createSquare) withObject:nil afterDelay:0];
[self performSelector:#selector(createPSquare) withObject:nil afterDelay:0];
}
return self;
}
-(void) backgrounds {
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:#"blueOutline"];
background.name = #"blueOutline";
background.size = CGSizeMake(320, 480);
background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
[self addChild:background];
//meathod sequence at interval
}
-(void) createSquare {
SKSpriteNode *blueSprite = [SKSpriteNode spriteNodeWithImageNamed:#"blue"];
blueSprite.name = #"blueSprite";
blueSprite.size = CGSizeMake(50, 50);
blueSprite.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
[self addChild:blueSprite];
//meathod sequence at interval
}
-(void) createPSquare {
SKSpriteNode *pinkSprite = [SKSpriteNode spriteNodeWithImageNamed:#"pink"];
pinkSprite.name = #"pinkSprite";
pinkSprite.size = CGSizeMake(50, 50);
pinkSprite.position = CGPointMake(CGRectGetMidX(self.frame)+10,CGRectGetMidY(self.frame));
[self addChild:pinkSprite];
//meathod sequence at interval
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"blueSprite"]) {
[node runAction:[SKAction removeFromParent]]; //Removes Sprite from parent
}
if ([node.name isEqualToString:#"pinkSprite"]) {
[node runAction:[SKAction removeFromParent]]; //Removes Sprite from parent
}
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}
#end
I suggest you generalize the code that creates the squares and backgrounds to simplify adding more colors to your game. Here's an example of how to do that:
Define a type that identifies the type of sprite node to create
typedef NS_ENUM (NSInteger, SpriteType) {
SpriteTypeBackground,
SpriteTypeSquare
};
This method adds a square and a background to the scene each with a randomly selected color
- (void) addSquareAndBackground {
_background = [self createSpriteWithType:SpriteTypeBackground];
_square = [self createSpriteWithType:SpriteTypeSquare];
}
This removes the square and background from the scene
- (void) removeSquareAndBackground {
[_background removeFromParent];
[_square removeFromParent];
}
This creates either a square or a background sprite based on the specified type
-(SKSpriteNode *) createSpriteWithType:(SpriteType)type {
// Select a color randomly
NSString *colorName = [self randomColorName];
SKSpriteNode *sprite;
if (type == SpriteTypeBackground) {
NSString *name = [NSString stringWithFormat:#"%#Outline",colorName];
sprite = [SKSpriteNode spriteNodeWithImageNamed:name];
sprite.name = name;
sprite.size = CGSizeMake(320, 480);
}
else {
sprite = [SKSpriteNode spriteNodeWithImageNamed:colorName];
sprite.name = [NSString stringWithFormat:#"%#Sprite",colorName];
sprite.size = CGSizeMake(50, 50);
}
sprite.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
[self addChild:sprite];
return sprite;
}
Randomly select a color name
// Set the total number of colors here
#define kNumberOfColors 2
- (NSString *) randomColorName {
NSString *colorName;
switch (arc4random_uniform(kNumberOfColors)) {
case 0:
colorName = #"blue";
break;
case 1:
colorName = #"pink";
break;
// Add more colors here
default:
break;
}
return colorName;
}
Add this to your touchesBegan method to test for a color match
if (node == _square) {
// Extract the color name from the node name
NSArray *squareNameParts = [node.name componentsSeparatedByCharactersInSet:[NSCharacterSet uppercaseLetterCharacterSet]];
// Extract the color name from the node name
NSArray *backgroundNameParts = [_background.name componentsSeparatedByCharactersInSet:[NSCharacterSet uppercaseLetterCharacterSet]];
// Compare if the colors match
if ([backgroundNameParts[0] isEqualToString: squareNameParts[0]]) {
NSLog(#"Score");
}
}
All that's left is to create an SKAction that calls addSquareAndBackground, waits for one second, and then calls removeSquareAndBackground. Lather, rinse, repeat!
EDIT: Add this above your #implementation MyScene statement:
#interface MyScene()
#property SKSpriteNode *background;
#property SKSpriteNode *square;
#end

Spritekit drastic frame rate drop

I have tried my best to boil this question down as simple as possible. I have a coin object in my game:
#implementation
-(CollectableCoin*)initWithLocation:(CGPoint) Location andValue: (int) val
{
self = [super initWithImageNamed:#"coin"];
[self setScale:.35];
_value = val;
_collected = false;
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.size];
self.physicsBody.categoryBitMask = APAColliderTypeCoin;
self.physicsBody.collisionBitMask = APAColliderTypeBall;
self.physicsBody.mass = 0.00009;
self.physicsBody.restitution = .35;
self.position = Location;
self.name = #"collectableCoin";
return self;
}
#end
I also have a shelf object:
#implementation Shelf
-(Shelf*)initWithLocation:(CGPoint) location andWidth:(NSInteger) width
{
self = [super initWithImageNamed:#"shelf"];
if(self)
{
self.size = CGSizeMake(width, HEIGHT);
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.size];
self.physicsBody.dynamic = false;
self.physicsBody.restitution = 0;
self.position = location;
self.name = #"shelf";
SKSpriteNode* topOfShelf;
if(width > 5)
topOfShelf = [[SKSpriteNode alloc] initWithColor:[UIColor yellowColor] size:CGSizeMake(width-2, 1)];
else
topOfShelf = [[SKSpriteNode alloc] initWithColor:[UIColor yellowColor] size:CGSizeMake(width, 1)];
topOfShelf.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:topOfShelf.size];
topOfShelf.physicsBody.restitution = 1;
topOfShelf.physicsBody.dynamic = false;
topOfShelf.position = CGPointMake(0, location.y + self.size.height/2);
NSLog([NSString stringWithFormat:#"%f", location.y + self.size.height/2]);
NSLog([NSString stringWithFormat:#"%f", location.y]);
topOfShelf.name = #"shelf";
[self addChild:topOfShelf];
}
return self;
}
#end
I create a scene like so:
-(id)initWithSizeTest:(CGSize)size
{
self.physicsWorld.gravity = CGVectorMake(0, 0);
_gameState = READYTOSTART;
self.physicsWorld.contactDelegate = self;
if (self = [super initWithSize:size])
{
self.physicsWorld.gravity = CGVectorMake(0, 0);
for(int i = 0; i < 25; i++)
{
CollectableCoin* orb = [[CollectableCoin alloc] initWithLocation:CGPointMake(i*10, self.size.height*.75) andValue:1];
[self addChild:orb];
}
Shelf* shelf = [[Shelf alloc] initWithLocation:CGPointMake(self.size.width/2, self.size.height/2) andWidth:self.size.width];
[self addChild:shelf];
}
return self;
}
Here is the touchesBegan method:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
if(_gameState == READYTOSTART)
{
self.physicsWorld.gravity = CGVectorMake(0, -2.0);
_gameState = PLAYING;
[[self childNodeWithName:#"taptostart"] removeFromParent];
}
When the scene starts, I have a row of coins hovering above a shelf, gravity is disabled, and I have a solid 60fps. When I tap the screen, the touchesbegan function enables gravity and the coins fall on the shelf, and the frame rate drops to 5fps. The didBeginContact function is not being called because the shelf object is not dynamic nor does it have contact or collision bitmasks, so I am fairly sure that it is not being overloaded by extraneous calls to didBeginContact. This happens on an iPad mini and an iPhone 4s, but not in any of the simulators. This is a very simple example of the actual problem that I am having. Anyone have any insights?

Resources