How to create a pendulum with spritekit - sprite-kit

I'm trying to create a pendalum in spritekit but i cannot figure out how to make the pendalum swing. So far the code is:
transparentpixel = [SKSpriteNode spriteNodeWithImageNamed:#"transparent_pixel"];
[transparentpixel setPosition:CGPointMake(150,150)];
transparentpixel.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(1, 1)];
transparentpixel.physicsBody.dynamic = YES;
[_bg addChild:transparentpixel];
pendalum = [SKSpriteNode spriteNodeWithImageNamed:#"pendalum_image"];
[pendalum setPosition:CGPointMake(150,120)];
pendalum.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pendalum.size];
pendalum.physicsBody.dynamic = YES;
[_bg addChild:pendalum];
CGPoint pendalumjointanchor = CGPointMake(150,150);
SKPhysicsJointPin *pendalumJointPin = [SKPhysicsJointPin jointWithBodyA:transparentpixel.physicsBody bodyB:pendalum.physicsBody anchor:pendalumjointanchor];
[self.physicsWorld addJoint:pendalumJointPin];
I can't figure out how to make the pendalum swing indefinetely.

You can create physics bodies on each side of the pendulum around where the pendulum would reach it's max height.
Set an event to trigger when the pendulum hits these physics bodies. In this event, Apply a downward force.
After playing with the physics bodies locations and the amount of force, you should be able to achieve something very similar to the effect you are after.

Related

Moving sprite "smoothly"

I'm trying to move a sprite in a set direction on-screen, using the physicsBody.velocity property. However, the motion is quite "jumpy" (makes the game look like it's lagging). I assume this has something to do with the different time intervals between each call to the update-method. How could I achieve a more "smooth" motion?
Right now this is the code I have in my update-loop to make the sprite move forward:
if (_movingForward) {
CGFloat forwardVel = _ball.physicsBody.velocity.dx;
forwardVel += 20.0;
if (forwardVel > bMaxForwardVelocity) {
forwardVel = bMaxForwardVelocity;
}
_ball.physicsBody.velocity = CGVectorMake(forwardVel, _ball.physicsBody.velocity.dy);
}
As you can see, I'm trying to make the speed pick up, so it doesn't immediately reach it's terminal velocity. This is to make the motion look more natural. However, the lagging is ruining this effect greatly, even when the sprite supposedly is traveling at a set speed.
EDIT 1:
I'm trying to make a platform-style game (like Super Mario etc) where the _ball moves horizontally along the ground when the user taps the screen. The code for moving the ball to the right is included above the edit. The ground is made up of multiple tiles, each 32x32 and positioned right next to each other with no gap in-between.
As per request, here's the code for setting up the _balls physicsBody:
self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:self.size.width/2.0];
self.physicsBody.dynamic = YES;
self.physicsBody.restitution = 0.5f;
self.physicsBody.usesPreciseCollisionDetection = YES;
self.physicsBody.allowsRotation = NO;
self.physicsBody.mass = 0.5f;
self.physicsBody.friction = 0.0f;
self.physicsBody.linearDamping = 0.0f;
self.physicsBody.categoryBitMask = CollisionCategoryBall;
And here's the code for the physicsBody of each individual tile:
tile.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:tile.size];
tile.physicsBody.dynamic = NO;
tile.physicsBody.categoryBitMask = CollisionCategoryGround;
The physicsWorld is set up like this:
self.physicsWorld.gravity = CGVectorMake(0, -4);
self.physicsWorld.contactDelegate = self;
Thanks!
EDIT 2:
This is a side-scrolling game, so the "camera" follows the ball. Here's the code for moving the background layer:
- (void)centerViewOn:(CGPoint)centerOn {
CGFloat x = Clamp(centerOn.x, (self.size.width / 2.0), (_bgLayer.layerSize.width) - (self.size.width / 2.0));
_worldNode.position = CGPointMake((int)-x, _worldNode.position.y);
}
The reason for the Clamp is so the "camera" doesn't scroll beyond the bounds of the background. This is when the ball is close to either the start or end of the level.
I'm casting the position to an int because without it, small gaps sometimes occur between the tiles. I was told this was because of some inaccuracy or something. However, even without casting the position to int, it's still a bitt "laggy". But because of the gaps between the tiles, it looks even worse.
The issue was with your scrolling code.
change this line :
_worldNode.position = CGPointMake((int)-x, _worldNode.position.y);
to
_worldNode.position = CGPointMake(-x, _worldNode.position.y);
The movement is then silky smooth.
But then you do get those seams. You should solve that in the placement of those tiles. You are likely positioning your _worldNode tiles with float values.

Move SKSpriteNode with Physics

I am trying to move an SKSpriteNode with physics by setting it's velocity. I am doing this on top of another SKNode (the map) that is part of the SKScene. Positions of "cities" are stored in custom Location objects.
I know the location of the initial SKSpriteNode (the ship) and I know the desired location. From what I've read, I can move the sprite by setting it's velocity. I do so like this:
float dy = _player.desiredLocation.yCoordinate - _mapNode.pin.position.y;
float dx = _player.desiredLocation.xCoordinate - _mapNode.pin.position.x;
_mapNode.pin.physicsBody.velocity = CGVectorMake(dx, dy);
This is all inside the didSimulatePhysics function inside the SKScene. Once the user taps a Location, I find the position and set the velocity. This seems to work well the FIRST time, but the sprite moves all over the place in subsequent times. Any idea what could be going wrong here?
PS: Setting skView.showsPhysics = YES; puts the circle of the physics body way off the position of the sprite.
In the map node:
self.pin = [SKSpriteNode spriteNodeWithImageNamed:[IPGameManager sharedGameData].world.player.ship.type];
self.pin.userInteractionEnabled = NO;
self.pin.position = CGPointMake([IPGameManager sharedGameData].world.player.location.xCoordinate, [IPGameManager sharedGameData].world.player.location.yCoordinate);
self.pin.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10.0];
self.pin.physicsBody.dynamic = YES;
self.pin.physicsBody.allowsRotation = NO;
self.pin.physicsBody.friction = 0.0;
self.pin.physicsBody.linearDamping = 0.0;
[self addChild:self.pin];

Is there a way to make a soft body with Spritekit using SKSpriteNode and PhysicsBody parameters?

I have the following sprite that falls to the bottom of the screen:
// The View
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
self.physicsWorld.contactDelegate = self;
// The Sprite
SKSpriteNode *cube = [[SKSpriteNode alloc] initWithImageNamed:#"cube"];
[cube setPosition:CGPointMake(160,250);
[self addChild:cube];
// The Physics
cube.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:cube.frame.size];
cube.physicsBody.dynamic = YES;
cube.physicsBody.affectedByGravity = YES;
cube.physicsBody.mass = 0.02;
Is there a way to make it so its sides are bulging when it hits the bottom border of the screen? Something that would be Jelly like or a soft body that still maintains its shape to some extent but bulges out under its own weight? I hope this makes sense....
Visit the site https://gist.github.com/kazukitanaka0611/4b9d4ac9dff0cd317b6c it have explanation and source code for soft bodies (jelly) in sprite kit
quick and easy way without math:
1 use flash to tween your box warping.
2 export the tweened frames as a sprite sheet (texture atlas)
3 animate the texture atlas on contact with an edge physics body in your scene.
your box will fall and on contact animate the separate images to give the impression its warping/bulging sides.
i used this method and it works - in other words it gives the desired effect, which in my view is what is important - your gamers don't care how you did it, as long as it looks great.

Reanimating a bouncing ball in sprite-kit

Reanimating a bouncing ball in sprite-kit
I have a question about the best way to reanimate a bouncing ball. Using Ray Wenderlich's tutorial on building a break out game as a reference I have a number of circular shape nodes which continually bounce around a gravity-less environment. When the user touches one of them, it centers on the screen, stops moving, and transforms into something else. When the user touches it again, it is supposed to transform back into the circular shape node and then continue bouncing around the screen.
I have it all working as I like except for reanimating the ball. The manner in which I stop the animation is simply to set the physicsBody to nil. Once I want to reanimate, I call the method that sets up the physicsBody for the node and I apply an impulse to it. But frustratingly, the impulse does not have the effect I think it should. Clearly, my expectations are incorrect.
Here is the code in question:
- (void)applyPhysics
{
// Set physics properties
self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:self.frame.size.width/2];
self.physicsBody.friction = 0.0f;
self.physicsBody.restitution = 1.0f;
self.physicsBody.linearDamping = 0.0f;
self.physicsBody.allowsRotation = NO;
self.physicsBody.collisionBitMask = wallCategory;
self.physicsBody.categoryBitMask = bubbleCategory;
}
- (void)morphPicker
{
BOOL check = NO;
if (check) NSLog(#"morphPicker called.");
[self runAction:[SKAction fadeAlphaTo:0.0 duration:.5]];
if (self.flipped) {
if (check) NSLog(#"The information side is showing.");
self.fillColor = bubbleColors[self.index % bubbleColors.count];
self.alpha = .9;
// Resume physics:
[self applyPhysics];
[self.physicsBody applyImpulse:CGVectorMake(10.0f, -10.0f)];
} else {
// stop physics:
self.physicsBody = nil;
if (check) NSLog(#"The statistic side is showing.");
self.fillColor = [SKColor blackColor];
self.alpha = .9;
[self transformToPickerNode];
[self removeAllChildren];
}
self.flipped = !self.flipped;
}
So my questions are these:
How should I be reanimating the ball if applying an impulse to it is not the correct method?
Is there a more elegant way to stop the animation after centering the node than setting the physicsBody to nil? Even to my novice instincts it feels like a brutish method.
After all my trials and searching for an answer to this I firmly believe that there is no elegant way to apply a new impulse to a sprite and expect it to move in the physics world. Thus my answer must be "it cannot be done at this point." However, my solution of removing all the the animated sprites from the scene and recreating them turned out to be the best solution for a completely different reason. The nature of my physics world caused my "floating bubbles" to eventually end up in the corners of the scene where they remained unmoving. Occasionally removing and recreating them had the effect of sending them happily bouncing around the scene again :)

SpriteKit 1 Dimensional Movement

I'm using apple's Sprite Kit and I need to move a SKSprite Node in horizontal movement only. I want the rest of the physics to apply but only in the horizontal component.
Context: This is for an object supposedly on a slider that can bounce back and forth. I have everything done but if it is hit the end the wrong way it simply floats off vertically, how can I simply make it ignore all forces in the vertical direction.
By putting the node's position back at the desired Y coordinate every frame after physics has been simulated:
-(void) didSimulatePhysics
{
CGPoint pos = horizontalMoveNode.position;
pos.y = fixedVerticalPosY;
horizontalMoveNode.position = pos;
}
Add this method to your scene class and apply it to whichever node(s) you want to lock in at a given Y coordinate.
You could use constraints for this purpose. I made a short sample with a node that only moves in a fixed X range and never leaves a specified Y position:
SKSpriteNode* node = [SKSpriteNode node];
node.color = [SKColor greenColor];
node.size = CGSizeMake(20, 20);
SKRange* rangeX = [[SKRange alloc] initWithLowerLimit: 100 upperLimit: 400];
SKRange* rangeY = [SKRange rangeWithConstantValue: 100];
SKConstraint* positionConstraint = [SKConstraint positionX: rangeX Y: rangeY];
NSArray* constraintArray = [NSArray arrayWithObject: positionConstraint];
node.constraints = constraintArray;
[self addChild: node];
This method is from SKAction class to move objects only on Horizontal or X-axis:-
[mySpriteNode runAction:[SKAction moveToX:260 duration:0.5]];
I hope this work's for you.