Sprite Kit Collision without bouncing - ios

I setup a hero and some platforms that are moving from the top downwards.
With these I have collisionBitMasks that detect when the hero lands on a platform if the hero comes from above (to let the hero jump through the platforms)
if (_hero.physicsBody.velocity.dy > 0) {
_hero.physicsBody.collisionBitMask = 0;
}
else {_hero.physicsBody.collisionBitMask = platformCategory;
}
Everything works fine, except that the hero keeps bouncing on the platform.
Is there a way to let him sit on it, while the platform is moving down?
I tried using physicsBody.resting and physicsBody.friction, but without any success.
Thanks for help Guys

Had the same issue just a minute ago. It works with setting the restitution but you need to set both restitutions. The one of the hero AND the one of the platform (or in my case the scene boundaries).
so:
hero.physicsBody.collisionBitMask = platformCategory
hero.physicsBody.restitution = 0.0
platform.physicsBody.restitution = 0.0
any_other_object_that_should_still_bounce.physicsBody.restitution = 1.0
will do it. All other objects on the screen still bounce on the platform as long as you set their restitution > 0

The trick is to avoid any physics behavior while the hero is on the platform by resetting the hero body's velocity and setting the hero's position to a fixed vertical offset from the platform's position.
In semi-pseudo-code:
-(void) didSimulatePhysics
{
if (<hero on platform>)
{
hero.physicsBody.velocity = CGPointZero;
hero.position = CGPointMake(hero.position.x,
platform.position.y + <offset as needed>);
}
}

Have you tried altering the restitution property of the nodes' physics bodies?
_hero.physicsbody.restitution = 0;
It controls the bounciness...

You can use the Collision category:
When the velocity.dy is < 0 the hero is falling.
func collisionWithPlayer(player: SKNode) {
// 1
if player.physicsBody?.velocity.dy < 0 && (player.position.y - player.frame.size.height / 2.0) >= (self.position.y){
// 2
player.physicsBody?.collisionBitMask = CollisionCategoryBitMask.Platform
}

Related

SpriteKit move physics body on touch (air hockey game)

I'm trying to make an air hockey game using SpriteKit. I trying to make the pucks draggable but I can't make them continue to move after the touch has ended. Right now I am binding the touch and the puck and setting it's position when the touch moves.
using the physics system:
override func update(currentTime: NSTimeInterval) {
for (touch, node) in draggingNodes {
let targetPosition = touch.locationInNode(self)
let distance = hypot(node.position.x - targetPosition.x, node.position.y - targetPosition.y)
var damping = sqrt(distance * 100)
if (damping < 0) {
damping = 0.0
}
node.physicsBody!.linearDamping = damping
node.physicsBody!.angularDamping = damping
let translation = CGPointMake(targetPosition.x - node.position.x, targetPosition.y - node.position.y)
node.physicsBody!.velocity = CGVectorMake(translation.x * 100, translation.y * 100);
}
}
You're likely going to need to do a lot more reading. Either you'll use the physics system:
In which case you'll impart an impulse onto the puck on the touch end event, having calculated the speed based on a delta in position and delta in time from last frame to current frame (or some type of average over more than 1 frame).
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Physics/Physics.html
[OR]
You'll manually set velocity on the puck (not using the physics system), and then manually update the puck's position per frame based on that velocity, then recalculate its vector when it comes into contact with another object based on angle of of incidence.

SpriteKit: SKPhysicsBody slips away

I have a SKSpriteNode (Bird) with a SKPhysicsBody (Circle).
The bird node is affected by gravity and falls down, until it reaches a y position of 100px.
override func didSimulatePhysics() {
if (bird.position.y < 100) {
bird.position = CGPointMake(bird.position.x, 100)
}
}
The problem is, that the physicsBody is moving away from the Node.
The physicsBody should stay centered on the Bird.
As soon as I tap the screen the Bird gets an impulse and moves up. Immediately the physicsBody is back in place.
This is the physicsBody code:
bird.physicsBody = SKPhysicsBody(circleOfRadius: bird.frame.width * 0.5)
bird.physicsBody!.contactTestBitMask = PhysicsCategory.LeftBoard | PhysicsCategory.RightBoard | PhysicsCategory.Border
bird.physicsBody!.categoryBitMask = PhysicsCategory.Bird
bird.physicsBody!.collisionBitMask = PhysicsCategory.None
bird.physicsBody!.mass = 1
bird.physicsBody!.affectedByGravity = false
bird.physicsBody!.allowsRotation = false
You need to stop the velocity. You are forcing the position but the velocity continues after each step.
Also you should typically make such changes in the update method before the physics are simulated.

Centering Camera on Velocity Applied Node Not Working

I have a subclass of SKNode which consists of a few sprites that make up a player. I would like the "camera" to center on this node (Always have the player in the center). Now before you down vote this for it being a duplicate, hear me out. The Apple documents suggest making the player node completely static, and instead moving around a camera node. However in my case I'm applying multiple properties of physics to my character, including velocity impulses. My first thought would be to just apply these impulses to the camera node itself, however this has become impossible due to the fact that the character has a small soft-body physics engine on it. I'm applying velocity to it like so:
player.primaryCircle.physicsBody!.velocity = CGVector(dx: player.primaryCircle.physicsBody!.velocity.dx+relVel.dx*rate, dy: player.primaryCircle.physicsBody!.velocity.dy+relVel.dy*rate)
I managed to get it to partially work with the following code:
override func didSimulatePhysics() {
self.player.position = player.primaryCircle.position
self.camera.position = player.position
centerOnNode(camera)
}
func centerOnNode(node: SKNode) {
let cameraPositionInScene: CGPoint = node.scene!.convertPoint(node.position, fromNode: node.parent!)
node.parent!.position = CGPoint(x:node.parent!.position.x - cameraPositionInScene.x, y:node.parent!.position.y - cameraPositionInScene.y)
}
However that didn't 100% work, as seen here: (It should be focused on the red circle)
http://gyazo.com/b78950e6cc15b60f390cd8bfd407ab56
As you can see, the world/map is moving, however it doesn't seem to be moving fast enough to center the player in the middle. (And note that the "Unamed" text is at a fixed spot on the screen -- That's why it seems to always be in the center)
I think this should still work with physics unless I am not truly understanding the question. We did something similar with our SKATiledMap with that Auto Follow Feature. What you need to do is make sure the player is added to a node you can move (usually a map) as a child and then in the update function you do something like this...(sorry it isn't in swift)
-(void)update
{
if (self.autoFollowNode)
{
self.position = CGPointMake(-self.autoFollowNode.position.x+self.scene.size.width/2, -self.autoFollowNode.position.y+self.scene.size.height/2);
//keep map from going off screen
CGPoint position = self.position;
if (position.x > 0)
position.x = 0;
if (position.y > 0)
position.y = 0;
if (position.y < -self.mapHeight*self.tileWidth+self.scene.size.height)
position.y = -self.mapHeight*self.tileWidth+self.scene.size.height;
if (position.x < -self.mapWidth*self.tileWidth+self.scene.size.width)
position.x = -self.mapWidth*self.tileWidth+self.scene.size.width;
self.position = CGPointMake((int)(position.x), (int)(position.y));
}
}
Map being the node that the player is added to. Hopefully that helps. Also here is the link to the git hub project we have been working on. https://github.com/SpriteKitAlliance/SKAToolKit

How to stop a sprite from bouncing off a specific surface

Hi I am making a endless scrolling game where the character basically avoids obstacles as they come and he can jump over them. I got everything to work pretty well but I see that the character texture will bounce slightly after hitting the ground. I want the sprite to stop immediately after touching down. I tried setting the .restitution property to 0 but i still see it bouncing. Here is the setup code for my stickman character and the edge physics category in question
stickman.physicsBody?.dynamic = true
stickman.physicsBody?.allowsRotation = false
stickman.physicsBody?.usesPreciseCollisionDetection = true
stickman.physicsBody?.categoryBitMask = PhysicsCategory.Stickman
stickman.physicsBody?.collisionBitMask = PhysicsCategory.Edge
stickman.physicsBody?.contactTestBitMask = PhysicsCategory.Obstacle | PhysicsCategory.Edge
stickman.physicsBody?.restitution = 0
self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
physicsBody = SKPhysicsBody(edgeLoopFromRect: playableRect)
physicsWorld.contactDelegate = self
physicsBody?.categoryBitMask = PhysicsCategory.Edge
Where playable rect is just the screen boundary for universal deployment purposes.
Has anyone run into this problem. I couldn't quite find the same issue in other posts.
Set the restitution of the physics body your sprite is running into to 0 as well. Both physics bodies in a physics collision need to have a restitution of 0 to result in no bounciness.

Swift SKSpriteNode Position Issues - logging correct, placement wrong

the situation
I am working through a Lynda.com video series (iOS Game Dev. With Sprite Kit), the tutorial is last gen for Objective-C and as a training exercise I am converting it to Swift and playing with new functionality. The goal is an old school brick breaking game.
I have an updated full project repository on GitHub here
the issue
in the GameScene.swift file, I have written a method addBricks(size: CGSize) :
func addBricks (size: CGSize){
println(" the input parameter size: \(size)")
var maxRows = 1
var maxCols = 1
var xPos : CGFloat
var yPos : CGFloat
for (var rows = 0; rows < maxRows; rows++){
for (var i = 0; i < maxCols ; i++){
var brick: SKSpriteNode = SKSpriteNode(imageNamed: "brick")
brick.physicsBody = SKPhysicsBody(rectangleOfSize: brick.frame.size)
xPos = CGFloat(size.width) / CGFloat(maxCols+1) * CGFloat(i + 1)
yPos = CGFloat(size.height) - CGFloat(80 * rows) - 100.0
brick.physicsBody.dynamic = false
brick.physicsBody.categoryBitMask = brickCategory
brick.shadowCastBitMask = 1
brick.lightingBitMask = 1
//brick.position = CGPointMake(CGFloat(xPos), CGFloat(yPos))
brick.position = CGPointMake(320.0, 1036.0)
println("Brick position - xpos: \(xPos), ypos: \(yPos) || overall:\(brick.position)")
self.addChild(brick)
}
}
}
I first call it in the scene from didMoveToView() and everything is peachy, my brick nodes are placed in the appropriate locations. In my game logic I later call this method from didBeginContact(), when the ball strikes the paddle after a logic check to see there are no bricks left. In the "When you run out of bricks, add more" sense...
func didBeginContact(contact: SKPhysicsContact!){
var notTheBall : SKPhysicsBody
// check the contacts and find the one thats not the ball
if ( contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask ){
notTheBall = contact.bodyB
} else {
notTheBall = contact.bodyA
}
/* more logic here for other contacts */
if ( notTheBall.categoryBitMask == paddleCategory ){
self.runAction(playSFXBlip)
//println("\(self.children.count) and \(staticSize)")
if ( self.children.count <= 5 ){
addBricks(self.frame.size)
}
}
}
On any subsequent method calls to addBricks(), ALL of the bricks are placed in what appears to be point 0,0 at the bottom left of the view, even when console is showing they are placed at a different position:
the self object is the current instance of SKScene println(self) -> <SKScene> name:'(null)' frame:{{0, 0}, {640, 1136}}
i've tried:
casting all elements of my position calculation as Floats and CGFloats
debugging the addBricks method by setting static float values
making a property for frame size outside of the contact method and passing that size to addBricks.
google-ing and consulting the Swift Programming Language Guide and the docs for anything relevant
what's causing inappropriate positioning? thanks in advance sorry for the TL;DR
The problem is, that you're trying to set the position of a Node in your didBeginContact method. You cannot position a node in didBeginContact that already has a physicsbody.
The ideal solution would be to add the bricks without a physicsbody, then set it's position to where ever you like, and finally add the physicsbody.
Another solution is to create some code that is being called after you've run your didBeginContact. For example
func didBeginContact(contact: SKPhysicsContact!){
var notTheBall : SKPhysicsBody
if ( contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask ){
notTheBall = contact.bodyB
} else {
notTheBall = contact.bodyA
}
if ( notTheBall.categoryBitMask == paddleCategory ){
addBricksInUpdate = true
}
}
func update:(currentTime: CFTimeInterval) {
if (addBricksInUpdate) {
if ( self.children.count <= 5 ){
addBricks(self.frame.size)
}
}
}
I don't know enough about what "self" is when you are calling, or what self's properties and values are, but when child nodes appear in the bottom left corner it is usually for one of two reasons:
1-The objects have been placed at (0,0) - either because that's their position, or because some other constraint, like size or rect, returned zero values. So you have a parent with size (0,0), or converted coordinates, etc.
[OR]
2- The parent node to the objects is offset/scaled/positioned from the "screen" rect in such a way that the values you are inputting for position on the child have had the children end up looking like they are in the bottom left corner, even though they are actually being placed relative to the parent or the paren't coordinate space. This is easily checked by seeing if different coords still put the object in the same place.
So, check the anchor points for your parent, be it a scene or a node. And check the size and position of the parent. I've heard mention that there are strange default size settings for the sks file in swift with regards to sprite kit and scene size, but haven't opened a swift project yet.

Resources