Physics Body edges IOS8, Sprite Kit - ios

SO following an IOS game tutorial, its IO7 as not many for 8 are out yet.
The following code is supposed to be a ball bouncing around but only bounces on the top and bottom of the screen, if it hits the side edges the ball goes of screen
#import "GameScene.h"
#implementation GameScene
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
self.backgroundColor =[SKColor whiteColor];
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
self.physicsWorld.gravity = CGVectorMake(0, 0);
SKSpriteNode *ball = [SKSpriteNode spriteNodeWithImageNamed:#"ball"];
ball.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.frame.size.width/2];
//ball.physicsBody.friction = 0;
ball.physicsBody.linearDamping = 0;
ball.physicsBody.restitution = 1;
[self addChild:ball];
CGVector myVector = CGVectorMake(0, 5);
[ball.physicsBody applyImpulse:myVector];
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}
#end
There has to be something simple here but i can't seem to find an answer on stack overflow

Use NSLog to check the size of your view: NSLog(#"%f,%f",self.size.width,self.size.height);
There is a problem with SpriteKit that causes the view dimensions to be off of what you expect. If this is what is happening in your case, then make sure to change the size of your view to the correct one:
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
self.size = self.view.frame.size;
self.backgroundColor =[SKColor whiteColor];
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
self.physicsWorld.gravity = CGVectorMake(0, 0);
SKSpriteNode *ball = [SKSpriteNode spriteNodeWithImageNamed:#"ball"];
ball.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.frame.size.width/2];
//ball.physicsBody.friction = 0;
ball.physicsBody.linearDamping = 0;
ball.physicsBody.restitution = 1;
[self addChild:ball];
CGVector myVector = CGVectorMake(50, 20);
[ball.physicsBody applyImpulse:myVector];
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}

Related

Sprite Kit didBeginContact not called between body and edgeRect

I have a game where I'm flicking bodies off the screen. I want to detect when these bodies are coming into contact with the edges (still letting the bodies pass through to off the screen) of the screen and I've implemented everything but still it is not working..here's my code:
GameScene.h
typedef NS_OPTIONS(uint32_t, FAPhysicsCategory) {
FAWallCategory = 1 << 0,
FABottomWallCategory = 1 << 1,
FAAnimalCategory = 1 << 2,
};
GameScene : SKScene <SKPhsyicsContactDelegate>
GameScene.m
-(void)setupWorldPhysics
{
// Set world gravity
self.physicsWorld.gravity = CGVectorMake(0.0, -5.0);
float bottomOffset = 400.0;
CGRect newFrame = CGRectMake(0, -bottomOffset, self.frame.size.width, self.frame.size.height + bottomOffset);
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:newFrame];
self.physicsBody.categoryBitMask = FAWallCategory;
self.physicsBody.contactTestBitMask = FAAnimalCategory;
self.physicsBody.collisionBitMask = 0;
}
-(void)launchBody {
SKSpriteNode* animalSprite = [SKSpriteNode spriteNodeWithImageNamed:[animalImagesArray objectAtIndex:animalChoice]];
animalSprite.position = CGPointMake(self.size.width/2, -animalSprite.size.height);
animalSprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:25];
animalSprite.physicsBody.dynamic = YES;
animalSprite.physicsBody.allowsRotation = YES;
animalSprite.name = #"animalSprite";
animalSprite.physicsBody.categoryBitMask = FAAnimalCategory;
animalSprite.physicsBody.contactTestBitMask = FAWallCategory;
animalSprite.physicsBody.collisionBitMask = 0;
animalSprite.physicsBody.usesPreciseCollisionDetection = YES;
[self addChild:animalSprite];
}
Alright so it's late and I'm exhausted and I feel like an idiot..i was missing:
self.physicsWorld.contactDelegate = self;
tool

Moving a camera in SpriteKit

//UPDATE
The updated code has been added that works as I expected. See didSimulatePhysics method in the updated code below. In my case, I only care about moving a character left or right on the x axis where 0 on the x axis is the absolute left and right on the x axis is a configurable value. The Apple adventure game really helped a lot too.
//ORIGINAL POST BELOW
I'm working with Apple SpriteKit and I'm struggling to implement a camera as I would like it to behave. What I've done in the code is load a sprite character, two buttons, and a red box that is off to the right outside of the view at the start. What I'd like to be able to do is move the character with the buttons, and once the player reaches the middle or end of the screen, the camera will then re-adjust to uncover what couldn't be seen in the view. So moving to the right should eventually show the red box that is off outside of the view initially once the player gets there. However, with the code I'm using below, I'm unable to get the camera to follow and adjust the coordinates to the main character at all. I've looked at Apple's advanced scene processing doc as well as a few other stack overflow posts but can't seem to get it right. If anyone could offer some advice it would be appreciated.
#define cameraEdge 150
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
/* Setup your scene here */
//320 568
self.backgroundColor = [SKColor whiteColor];
myWorld = [[SKNode alloc] init];
[self addChild:myWorld];
mainCharacter = [SKSpriteNode spriteNodeWithImageNamed:#"0"];
mainCharacter.physicsBody.dynamic = YES;
mainCharacter.name = #"player";
mainCharacter.position = CGPointMake(20, 20);
CGRect totalScreenSize = CGRectMake(0, 0, 800, 320);
SKSpriteNode *box = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(60, 60)];
SKSpriteNode *boxTwo = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(60, 60)];
SKSpriteNode *boxThree = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(60, 60)];
boxThree.position = CGPointMake(40, 50);
[myWorld addChild:boxThree];
boxTwo.position = CGPointMake(1100, 50);
box.position = CGPointMake(650, 50);
[myWorld addChild:box];
[myWorld addChild:boxTwo];
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:totalScreenSize];
self.physicsWorld.gravity = CGVectorMake(0, -5);
mainCharacter.name = #"mainCharacter";
mainCharacter.physicsBody.linearDamping = 0;
mainCharacter.physicsBody.friction = 0;
mainCharacter.physicsBody.restitution = 0;
mainCharacter.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:mainCharacter.size];
[myWorld addChild:mainCharacter];
[self addChild:[self buildLeftButton]];
[self addChild:[self buildRightButton]];
}
return self;
}
- (void)didSimulatePhysics
{
SKSpriteNode *hero = mainCharacter;
if(hero)
{
CGPoint heroPosition = hero.position;
CGPoint worldPosition = myWorld.position;
NSLog(#"%f", heroPosition.x);
CGFloat xCoordinate = worldPosition.x + heroPosition.x;
if(xCoordinate < cameraEdge && heroPosition.x > 0)
{
worldPosition.x = worldPosition.x - xCoordinate + cameraEdge;
self.worldMovedForUpdate = YES;
}
else if(xCoordinate > (self.frame.size.width - cameraEdge) && heroPosition.x < 2000)
{
worldPosition.x = worldPosition.x + (self.frame.size.width - xCoordinate) - cameraEdge;
self.worldMovedForUpdate = YES;
}
myWorld.position = worldPosition;
}
}
-(SKSpriteNode *)buildLeftButton
{
SKSpriteNode *leftButton = [SKSpriteNode spriteNodeWithImageNamed:#"left"];
leftButton.position = CGPointMake(20, 20);
leftButton.name = #"leftButton";
leftButton.zPosition = 1.0;
return leftButton;
}
-(SKSpriteNode *)buildRightButton
{
SKSpriteNode *leftButton = [SKSpriteNode spriteNodeWithImageNamed:#"right"];
leftButton.position = CGPointMake(60, 20);
leftButton.name = #"rightButton";
leftButton.zPosition = 1.0;
return leftButton;
}
-(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:#"leftButton"])
{
[mainCharacter.physicsBody applyImpulse:CGVectorMake(-120, 0)];
}
else if([node.name isEqualToString:#"rightButton"])
{
[mainCharacter.physicsBody applyImpulse:CGVectorMake(120, 10)];
}
}
If you want the view to always be centered on your player's position, modify your code with these points in mind:
1) Create a SKNode and call it myWorld, worldNode or any other name like that.
2) Add the worldNode [self addChild:worldNode];
3) Add all other nodes to the worldNode, including your player.
4) In the didSimulatePhysics method, add this code:
worldNode.position = CGPointMake(-(player.position.x-(self.size.width/2)), -(player.position.y-(self.size.height/2)));
Your view will now always be centered on your player's position.
Update May 2015:
If you are using a map created with Tiled Map Editor, you can use the free SKAToolKit framework. Features include player camera auto follow, test player, test HUD and sprite buttons.

Prevent player from falling through the ground - Sprite Kit

I've been trying to work on a simple Sprite Kit game that involves dodging red balls. I'm using the built-in gravity mechanism, but I'm having trouble preventing the player from falling through the ground. I've looked up a solution (set ground.physicsBody.dynamic = NO), but the player still falls through. What exactly do I need to do?
Edit: The green and brown texture is the ground. Right now the player is set to not being dynamic, so it is 'flying'
Here is my code in the MyScene.m file:
//
// MyScene.m
// DodgeMan
//
// Created by Cormac Chester on 3/8/14.
// Copyright (c) 2014 Testman Industries. All rights reserved.
//
#import "MyScene.h"
#import "EndGameScene.h"
static const uint32_t redBallCategory = 0x1 << 0;
static const uint32_t playerCategory = 0x1 << 1;
#implementation MyScene
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
/* Setup your scene here */
//Sets player location
playerLocX = 50;
playerLocY = 100;
//Sets player score
score = 0;
//Set Background
self.backgroundColor = [SKColor colorWithRed:0.53 green:0.81 blue:0.92 alpha:1.0];
//Set Ground
SKSpriteNode *ground = [SKSpriteNode spriteNodeWithImageNamed:#"ground"];
ground.position = CGPointMake(CGRectGetMidX(self.frame), 34);
ground.xScale = 0.5;
ground.yScale = 0.5;
ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size];
ground.physicsBody.dynamic = NO;
//Player
self.playerSprite = [SKSpriteNode spriteNodeWithImageNamed:#"character"];
self.playerSprite.position = CGPointMake(playerLocX, playerLocY);
//Set Player Physics
self.playerSprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.playerSprite.size];
self.playerSprite.physicsBody.dynamic = YES;
self.playerSprite.physicsBody.categoryBitMask = playerCategory;
self.playerSprite.physicsBody.contactTestBitMask = redBallCategory;
self.playerSprite.physicsBody.collisionBitMask = 0;
self.playerSprite.physicsBody.usesPreciseCollisionDetection = YES;
//Score Label
self.scoreLabel = [SKLabelNode labelNodeWithFontNamed:#"Arial-BoldMT"];
self.scoreLabel.text = #"0";
self.scoreLabel.fontSize = 40;
self.scoreLabel.fontColor = [SKColor blackColor];
self.scoreLabel.position = CGPointMake(50, 260);
//Pause Button
self.pauseButton = [SKSpriteNode spriteNodeWithImageNamed:#"pauseButton"];
self.pauseButton.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height - 40);
self.pauseButton.name = #"pauseButton";
//Add nodes
[self addChild:ground];
[self addChild:self.playerSprite];
[self addChild:self.scoreLabel];
//[self addChild:self.pauseButton];
//Sets gravity
self.physicsWorld.gravity = CGVectorMake(0,-2);
self.physicsWorld.contactDelegate = self;
}
return self;
}
-(void)addBall
{
SKSpriteNode *redBall = [SKSpriteNode spriteNodeWithImageNamed:#"locationIndicator"];
int minY = redBall.size.height / 2;
int maxY = self.frame.size.height - redBall.size.height / 2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
NSLog(#"Actual Y: %i", actualY);
//Initiates red ball offscreen
if (actualY >= 75)
{
//Prevents balls from spawning in the ground
redBall.position = CGPointMake(self.frame.size.width + redBall.size.width/2, actualY);
[self addChild:redBall];
}
redBall.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:redBall.size.width/2];
redBall.physicsBody.dynamic = YES;
redBall.physicsBody.categoryBitMask = redBallCategory;
redBall.physicsBody.contactTestBitMask = playerCategory;
redBall.physicsBody.collisionBitMask = 0;
redBall.physicsBody.affectedByGravity = NO;
redBall.physicsBody.usesPreciseCollisionDetection = YES;
//Determine speed of red ball
int minDuration = 3.0;
int maxDuration = 5.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
// Create the actions
SKAction *actionMove = [SKAction moveTo:CGPointMake(-redBall.size.width/2, actualY) duration:actualDuration];
SKAction *actionMoveDone = [SKAction removeFromParent];
SKAction *ballCross = [SKAction runBlock:^{
score++;
self.scoreString = [NSString stringWithFormat:#"%i", score];
self.scoreLabel.text = self.scoreString;
NSLog(#"Score was incremented. Score is now %d", score);
}];
[redBall runAction:[SKAction sequence:#[actionMove, ballCross, actionMoveDone]]];
}
- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast
{
self.lastSpawnTimeInterval += timeSinceLast;
if (self.lastSpawnTimeInterval > 0.5) {
self.lastSpawnTimeInterval = 0;
[self addBall];
}
}
-(void)update:(CFTimeInterval)currentTime
{
/* Called before each frame is rendered */
// Handle time delta.
//Prevents bad stuff happening
CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
self.lastUpdateTimeInterval = currentTime;
if (timeSinceLast > 1) { // more than a second since last update
timeSinceLast = 1.0 / 120.0;
self.lastUpdateTimeInterval = currentTime;
}
[self updateWithTimeSinceLastUpdate:timeSinceLast];
}
NSDate *startTime;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
/* Called when a touch begins */
[super touchesBegan:touches withEvent:event];
//Starts Timer
startTime = [NSDate date];
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//Pauses Scene
if ([node.name isEqualToString:#"pauseButton"])
{
NSLog(#"Pause button pressed");
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
/* Called when a touch ends */
[super touchesEnded:touches withEvent:event];
NSTimeInterval elapsedTime = [startTime timeIntervalSinceNow];
NSString *elapsedTimeString = [NSString stringWithFormat:#"Elapsed time: %f", elapsedTime];
NSLog(#"%#", elapsedTimeString);
for (UITouch *touch in touches)
{
//Gets location of touch
CGPoint location = [touch locationInNode:self];
NSLog(#"Touch Location X: %f \n Touch Location Y: %f", location.x, location.y);
//Prevents destination from being in the ground
if (location.y < 88)
{
location.y = 87.5;
}
//Moves and animates player
//int velocity = elapsedTime * -3000;
int velocity = 800.0/1.0;
NSLog(#"Velocity: %i", velocity);
float realMoveDuration = self.size.width / velocity;
SKAction *actionMove = [SKAction moveTo:location duration:realMoveDuration];
[self.playerSprite runAction:[SKAction sequence:#[actionMove]]];
}
NSLog(#"Touch ended");
}
//Collision between ball and player
- (void)redBall:(SKSpriteNode *)redBall didCollideWithPlayer:(SKSpriteNode *)playerSprite
{
NSLog(#"Player died");
[redBall removeFromParent];
[playerSprite removeFromParent];
SKTransition *reveal = [SKTransition crossFadeWithDuration:0.5];
SKScene *endGameScene = [[EndGameScene alloc] initWithSize:self.size gameEnded:YES];
[self.view presentScene:endGameScene transition: reveal];
}
- (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;
}
//Red ball collides with the player
if ((firstBody.categoryBitMask & redBallCategory) != 0 && (secondBody.categoryBitMask & playerCategory) != 0)
{
[self redBall:(SKSpriteNode *) firstBody.node didCollideWithPlayer:(SKSpriteNode *) secondBody.node];
}
}
#end
you definitely can't set its dynamic to no brother. you need gravity effect that player. (he is not effected by physic world so he is flying right now. we need him to fall down to ground aren't we? :)
So here is the simple solution. idea is that you create a "invisible rectangle block" on the ground surface that has physic body. and you need to set its dynamic to no in order to prevent it falling down
so this block is a node obviously, and its size : as high as the ground , and as wide as the screen. and you need to adjust the position a little bit to put its upper bound right on the ground surface.
good luck
i actually drew a picture but i can't post it here because of my reputation :(
Your problem is with physicsBody's categoryBitMask and collisionTestBitMask.
Your bitwise declarations :
static const uint32_t redBallCategory = 0x1 << 0;
static const uint32_t playerCategory = 0x1 << 1;
This has actually set the following bit patterns (i've shortened to 8 bits for the example) :
redBallCategory - 00000001 and
playerCategory - 00000010
However in the following code, you tell the player to only collide with collision bit mask - 00000000;
self.playerSprite.physicsBody.collisionBitMask = 0;
So your first problem is here. The player will not collide with any category that you have defined.
Your second problem is you have not given the ground a categoryBitMask, or collisionBitMask. By default this means all bits are set, IE the ground's collisionBitMask is equal to 11111111;
There will be no collision between these two physics bodies.
Try this - i have simply added a third physics category, and edited your code slightly to set the ground categoryBitMask / collisionBitMask, and your player collisionBitMask.
static const uint32_t redBallCategory = 0x1 << 0;
static const uint32_t playerCategory = 0x1 << 1;
static const uint32_t groundCategory = 0x1 << 2;
#implementation MyScene
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
/* Setup your scene here */
//Sets player location
playerLocX = 50;
playerLocY = 100;
//Sets player score
score = 0;
//Set Background
self.backgroundColor = [SKColor colorWithRed:0.53 green:0.81 blue:0.92 alpha:1.0];
//Set Ground
SKSpriteNode *ground = [SKSpriteNode spriteNodeWithImageNamed:#"ground"];
ground.position = CGPointMake(CGRectGetMidX(self.frame), 34);
ground.xScale = 0.5;
ground.yScale = 0.5;
ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size];
ground.physicsBody.categoryBitMask=groundCategory;
ground.physicsBody.collisionBitMask=playerCategory|redBallCategory;
ground.physicsBody.dynamic = NO;
//Player
self.playerSprite = [SKSpriteNode spriteNodeWithImageNamed:#"character"];
self.playerSprite.position = CGPointMake(playerLocX, playerLocY);
//Set Player Physics
self.playerSprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.playerSprite.size];
self.playerSprite.physicsBody.dynamic = YES;
self.playerSprite.physicsBody.categoryBitMask = playerCategory;
self.playerSprite.physicsBody.contactTestBitMask = redBallCategory;
self.playerSprite.physicsBody.collisionBitMask = groundCategory|redBallCategory;
self.playerSprite.physicsBody.usesPreciseCollisionDetection = YES;
//Score Label
self.scoreLabel = [SKLabelNode labelNodeWithFontNamed:#"Arial-BoldMT"];
self.scoreLabel.text = #"0";
self.scoreLabel.fontSize = 40;
self.scoreLabel.fontColor = [SKColor blackColor];
self.scoreLabel.position = CGPointMake(50, 260);
//Pause Button
self.pauseButton = [SKSpriteNode spriteNodeWithImageNamed:#"pauseButton"];
self.pauseButton.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height - 40);
self.pauseButton.name = #"pauseButton";
//Add nodes
[self addChild:ground];
[self addChild:self.playerSprite];
[self addChild:self.scoreLabel];
//[self addChild:self.pauseButton];
//Sets gravity
self.physicsWorld.gravity = CGVectorMake(0,-2);
self.physicsWorld.contactDelegate = self;
}
return self;
}
Just:
self.playerSprite.physicsBody.dynamic = NO;
should work.
Your problem occurs due to scaling. For some reason in sprite kit scaling an image doesn't change it's size when used in following code. Judging by your pictures, your physics body rectangle for your ground is actually twice as big as you think and already engulfing the player, which is why there would by no collision detection. This is from recent experience with a very similar style game.
Do you have an edge loop physcis body around the scene? Collision flags and category flags set correctly so the player collides with the ground?
i had same problem and i soved it simply...
On the update method i've putted an if statement:
if(player.position.y<your_closest_value_near_ground){
player.position.y == your_Closest_value_near_ground
}
The comparition differs by the anchor point you have.. hope it helps someone

I want to make a soccer ball by IOS SpriteKit

I want to make a soccer ball by IOS SpriteKit
I was able to create a ball in the code such as the following.
However, it does not bounce at all.
To make rebound rate, How can I do this?
(UITouch *touch in touches) {
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:#"Ball"];
sprite.position = location;
const CGFloat radius = 20.0f;
SKPhysicsBody *pbody = [SKPhysicsBody bodyWithCircleOfRadius:radius];
sprite.physicsBody = pbody;
sprite.size = (CGSize){radius * 2, radius * 2};
sprite.physicsBody.linearDamping=0.12f;
[self addChild:sprite];
}
I have declared like this.
  
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:(CGRect){CGPointZero, size}];
self.physicsWorld.gravity=CGVectorMake(0, -100);
}
return self;
}
This looks like a ball to me
- (void) soccerBallExample
{
// the world bounds
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)];
// the ball
SKShapeNode *ball;
ball = [[SKShapeNode alloc] init];
CGMutablePathRef myPath = CGPathCreateMutable();
CGPathAddArc(myPath, NULL, 0,0, 30, 0, M_PI*2, YES);
ball.path = myPath;
CGPathRelease(myPath);
ball.fillColor = [SKColor blueColor];
ball.position = CGPointMake(200, 200);
[self addChild:ball];
// set the physics
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:30];
ball.physicsBody.restitution = 0.8;
}
In your example, you use a sprite so for radius use
// ball.size.width * 0.5;

SpriteKit: unexpected physics issue

I want a ball-sprite jump off the ground each time to the same height. But with every jump the maximum height position of the ball increases.
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKNode *ground = [SKNode node];
ground.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointZero toPoint:CGPointMake(CGRectGetMaxX(self.frame), 0)];
[self addChild:ground];
SKShapeNode *ball = [[SKShapeNode alloc] init];
CGMutablePathRef myPath = CGPathCreateMutable();
CGPathAddArc(myPath, NULL, 0, 0, 30, 0, M_PI*2, YES);
ball.path = myPath;
ball.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame)-100);
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.frame.size.width/2];
ball.physicsBody.linearDamping = 0.0;
ball.physicsBody.restitution = 1.0;
[self addChild:ball];
}
return self;
}
Any suggestions?
Look at setting both the restitution and friction on both bodies, not just the ball. If it's growing and not shrinking though, there is likely an error with the physics bodies. SKShapeNode is notoriously unreliable in my testing - I would look into using SKSpriteNode instead to maintain your sanity.

Resources