Can't disable physics in Sprite Kit - ios

I have two nodes one near another. And I want one node to be on top of another when I tap. I do so like this:
SKAction *moveUp= [SKAction moveByX:0 y:25 duration:0.1];
SKAction *moveDown= [SKAction moveByX:0 y:-25 duration:0.1];
SKAction *playerSequence = [SKAction sequence:#[moveUp,moveDown]];
[self.player runAction:[SKAction repeatAction:playerSequence count:1] withKey:#"attack"];
And instead I get that one node pushes the other (bots nodes created via editor and both body type is set to none).
I tried adding these to didMoveToView on both nodes:
node.physicsBody.dynamic = NO;
node.physicsBody.collisionBitMask = 0;
node.physicsBody.contactTestBitMask = 0;
node.physicsBody.affectedByGravity = NO;
I even tried setting velocity to 0 on Update. And still no effect.

Set your bit masks in
-(void)didBeginContact:(SKPhysicsContact *)contact
as shown in this post.
I think you have a timing issue if you set the bit masks in
didMoveToView
because only one of those will be run at a time and both physics bodies will need to mutually agree not contact each other.

You have to set the physics body to nil:
node.physicsBody = nil;

Related

Objective c SpriteKit node

i want to make simple game in SpriteKit, basically what i want do do is make node what shows up on touch and disappear after like 5 sec. here are sample of code that is for board:
SKSpriteNode* board = [[SkSpriteNode alloc] initWithImageNamed:#"board"];
board.name = boardCategoryName;
board.position = CGPointMake (CGRectGetMaxX(self.frame),board.frame.seize.height *4.6f);
[self.addChild:board];
board.physicsBody = [SKphysicsBody bodyWithRectangleOFSize:board.frame.size];
board.physicsBody.restitution =0.1f;
board.physicsBody.friction = 0.4f;
board.physicsBody.dynamic = No;
Mr T does present 1 option, but personally I would use the SKActions sequence, waitForDuration, and removeFromParent() when dealing with nodes, like this:
let waitDuration = SKAction.waitForDuration(5)
let killAction = SKAction.removeFromParent()
let seqAction = SKAction.sequence([waitDuration,killAction])
....
board.runAction(seqAction)
There are many ways you can do it. One way is to call [board removeFromParent] after 5 seconds. This could be a call by NSTimer or you can use the update method which runs continuously,and check for the flag if node is added on the screen or not, and then remove the node after 5 seconds. You might need to set the flag in the touchesBegan method.
Edit:
You can also make use of SKAction waitForDuration
Sample code:
SKAction *delay = [SKAction waitForDuration:5];
SKAction *remove = [SKAction removeFromParent];
SKAction *actionSequence = [SKAction sequence:#[delay,remove]];
[board runAction:actionSequence];
So that after the wait is done, the node will be removed.

Collision detection between two sprites (without a physic body?) iOS

I am having trouble getting collision detection to work with my two objects. Here is my current code:
_firstPosition = CGPointMake(self.frame.size.width * 0.817f, self.frame.size.height * .40f);
_squirrelSprite = [SKSpriteNode spriteNodeWithImageNamed:#"squirrel"];
_squirrelSprite.position = _firstPosition;
_atFirstPosition = YES;
[self addChild:_squirrelSprite];
SKAction *wait = [SKAction waitForDuration:3.0];
SKAction *createSpriteBlock = [SKAction runBlock:^{
SKSpriteNode *lightnut = [SKSpriteNode spriteNodeWithImageNamed:#"lightnut.png"];
BOOL heads = arc4random_uniform(100) < 50;
lightnut.position = (heads)? CGPointMake(257,600) : CGPointMake(50,600);
[self addChild: lightnut];
SKAction *moveNodeUp = [SKAction moveByX:0.0 y:-700.0 duration:1.3];
[lightnut runAction: moveNodeUp];
}];
SKAction *waitThenRunBlock = [SKAction sequence:#[wait,createSpriteBlock]];
[self runAction:[SKAction repeatActionForever:waitThenRunBlock]];
I was following this answer at first: Sprite Kit Collision Detection but when I set the physics body to my squirrel and nut they would just fall. Is there any way to not mess with the physics (I'm happy with how everything currently works in the app) and just make it so that when one object touches the other the game will end? Is there a way to just set a radius around a sprite? Thank you for any help or information that can be provided.
Physics bodies are required for collision detection. If you don't also want gravity, either set the physics world's gravity to zero or turn off the affectedByGravity property on each physics body.
You can use the Pythagorean theorem to determine the distance between two sprite nodes. Here's an example of how to do that:
CGFloat dx = sprite1.position.x - sprite2.position.x;
CGFloat dy = sprite1.position.y - sprite2.position.y;
CGFloat distance = sqrt(dx*dx+dy*dy);
// Check if the two nodes are close
if (distance <= kMaxDistance) {
// Do something
}

Scaling Physics Bodies in Xcode Spritekit

I recently came across an issue where I would increase the size of a node, but the physics body would remain the same size. I tried to look up solutions to this with no success. How can I make the body scale with the size of the node?
CGPoint location = CGPointMake(randX, -self.frame.size.height - expander.size.height);
SKAction *moveAction = [SKAction moveTo:location duration:randDuration];
SKAction *expandAction = [SKAction resizeToWidth:(expander.size.width * 1.4) height:(expander.size.width * 1.4) duration:1.0];
SKAction *collapseAction = [SKAction resizeToWidth:(expander.size.width) height: (expander.size.height) duration:1.0];
SKAction *doneAction = [SKAction runBlock:(dispatch_block_t)^() {
expander.hidden = YES;
}];
SKAction *expandCollapseAction = [SKAction repeatActionForever:[SKAction sequence:#[expandAction, collapseAction]]];
SKAction *moveExpandAction = [SKAction group:#[moveAction, expandCollapseAction]];
SKAction *moveExpanderActionWithDone = [SKAction sequence: #[moveExpandAction, doneAction ]];
[expander runAction:moveExpanderActionWithDone withKey: #"expanderMoving"];
I thought this won't work, but it looks like that physics body is scaled after all. Here is the code which can reproduce physics body scaling on iOS8 :
- (void)didMoveToView:(SKView *)view {
/* Setup your scene here */
SKSpriteNode *s = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(100,100)];
s.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame)+100);
s.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:s.size];
s.physicsBody.dynamic = YES;
s.physicsBody.affectedByGravity = NO;
[self addChild:s];
[s runAction:[SKAction scaleTo:0.3f duration:5]];
[s.physicsBody applyImpulse:CGVectorMake(0,30)];
}
If I recall correctly , this wasn't worked earlier, but I just tried it and it looks like it work. Still, this is not fully tested and I am not sure if this will mess up the physics simulation. Contact detection will probably work though. I just wanted to show that actual physics bodies are scaled when sprite is scaled . Here is the result:
From the gif above it can be seen that physics body is scaled along with sprite (without re-creating another different sized physics body). The blue bounding box around the sprite is visual representation of sprite's physics body (enabled in view controller with skView.showsPhysics = YES);
this is strange you can do it add physics body before adding it to the SKNode or SKScene for e.g.
SKTexture *texture=[_gameTexture textureNamed:#"mysprite"];
SKSpriteNode *bubble=[SKSpriteNode spriteNodeWithTexture:texture];
bubble.anchorPoint=CGPointMake(0.5,0.5);
//_bubble.name=[#"bubble" stringByAppendingFormat:#"%d ",index];
bubble.name=newcolor;
// _bubble.userInteractionEnabled=YES;
_bubble.position=CGPointMake(newPosition.x, newPosition.y);
//
bubble.physicsBody=[SKPhysicsBody bodyWithCircleOfRadius:60];
bubble.physicsBody.dynamic=NO;
bubble.physicsBody.linearDamping=0;
bubble.physicsBody.restitution=0;
bubble.physicsBody.density=1;
bubble.physicsBody.allowsRotation=NO;
bubble.physicsBody.affectedByGravity=NO;
//_bubble.physicsBody.velocity=CGVectorMake([self getRandomNumberBetween:-10 to:7], [self getRandomNumberBetween:-10 to:7]);
// _bubble.physicsBody.usesPreciseCollisionDetection=YES;
bubble.physicsBody.categoryBitMask=ballCategory;
bubble.physicsBody.collisionBitMask=ballCategory | pathCategory ;
bubble.physicsBody.contactTestBitMask=ballCategory | pathCategory ;
[self addChild:_bubble];
bubble.xScale=_bubble.yScale=2;
bubble.alpha=0.5;

SKAction scaleXTo:-1

I am trying to mirror my SKSpriteNode using SKAction *mirrorDirection = [SKAction scaleXTo:-1 y:1 duration:0.0]; but every time I do, the sprite's physics body seems to get messed up and it drops off the screen. I have several objects (floors) beneath the sprite and it falls through all of them as if they are not there.
This only happens when I mirror the sprite. Anyone know how to fix this?
Update:
Reseting the physics body as one answer suggested unfortunately did not fix the problem. It appears that only the contact part of the physics body malfunctions. Gravity still has an effect as the little guy drops like a rock.
I also tried to reset by again self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width, self.size.height)];
right after the self.xScale = -1; but this also did not fix the issue.
Add your mirror-able node as a child of some regular SKNode and set the physics body on this parent node instead of the negatively scaled node.
I don't know how to fix this but I would like to suggest one way you could create a mirrored sprite.
To achieve this set the x or y scale of your sprite node to -1. Then use the SKView method textureFromNode: to create a texture from this mirrored node.
You can then use this texture to create a new sprite node that is mirrored but doesn't require any negative scaling.
Don't use an SKAction, just set it directly to the SKSpriteNode's xScale property.
self.yourSprite.xScale = -1;
Roecrew is right about setting the xScale property directly. I would suggest you try this:
node.xScale = -1;
node.physicsBody = node.physicsBody;
You will need to 'reset' the physicsBody each time you change the xScale property.
The xScale issue with physicsBody is a bug in SpriteKit, but I was able to 'retain' the physicsBody using the second line.
I'm meeting the problem exactly like yours. I spent about 2 hours to figure it out.
Just init your physicsBody after you scaleX, i dont know why but i had correct this issue by doing this way.
walkRight = [SKAction sequence:#[resetDirection,[SKAction runBlock:^{
[self changePhysicsDirectionRight];
}],[SKAction repeatActionForever: walk]]];
walkLeft = [SKAction sequence:#[mirrorDirection,[SKAction runBlock:^{
[self changePhysicsDirectionLeft];
}],[SKAction repeatActionForever: walk]]];
walkRight and walkLeft is my action when changing direction, and resetDirection and mirrorDirection is exactly the action i used to scaleXTo:1 and scaleXTo:1
So after i scaleXTo i use a method call changePhysicsDirectionRight to re-init my physicBody like
- (void)changePhysicsDirectionRight{
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width,self.size.height)];
self.physicsBody.categoryBitMask = guyCategory;
self.physicsBody.contactTestBitMask = 0;
self.physicsBody.collisionBitMask = 0;
}
Remember to re-assign all your category and everything like you init before.
I hope someone pro at spritekit can tell me the reason why ....

Sprite Kit, force stop on physics

I'm creating an ongoing learning project (basically I code while learning to use the framework in hope it will be useful for me and for someone else) for Sprite Kit (you can find it here if you are interested) but I'm facing some performance problems with my code.
The project puts cubes on the screen and make them falling. Here's the class that creates the piece
// The phisics for our falling piece:
// It will be a square, subject to gravity of 5: check common.h (9.8 is way too much for us)
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width, self.size.height)];
self.physicsBody.dynamic = YES;
self.physicsBody.mass = 100;
self.physicsBody.collisionBitMask = piecesCollisionBitmask;
self.physicsBody.allowsRotation = NO;
and here is the scene file with the loop.
//schedule pieces
SKAction *wait = [SKAction waitForDuration:1];
SKAction *pieceIsFalling = [SKAction runBlock:^{
FLPPiece *piece = [[FLPPiece alloc] init];
[self addChild:piece];
}];
SKAction *fallingPieces = [SKAction sequence:#[wait,pieceIsFalling]];
[self runAction:[SKAction repeatActionForever:fallingPieces]];
I suspect that physics is behind my frame rate drop. I would like to stop physics execution on node while keeping it on the screen as soon as it collides with something else.
Is that possible? How can I do that?

Resources