Making velocity of an SKSprite node relative to parent (not view/scene) - ios

I'm using SpriteKit in Swift (3.0).
I store all the SKSprites nodes in my game as children of a "world" node
However when I apply a velocity to one of those nodes, they move relative to the screen, and not "world" (world is rotating, moving, etc.)
Heres how I implement it:
let movingObject = SKSpriteNode(color: UIColor.green, size: CGSize(width: 10, height: 10))
movingObject.physicsBody = SKPhysicsBody(rectangleOf: movingObject.size)
movingObject.physicsBody?.velocity = CGVector(dx: 0, dy: 200)
world.addChild(movingObject)
I need my node's velocity to move in respect to its parent, not the scene/view it is in. How do I do that?
Thanks!

Related

didBeginContact() called before contact occurred

I have two sprite nodes where I have made sure both self.size and the size of their respective physics bodies is the same, but I still get a very odd behavior like this:
The photo is taken as the collision has been detected and i paused the scene. Why does this happen?
Here is the code for setting the different sizes:
Inside init() of my Player class (circular node):
super.init(texture: texture, color: color, size: CGSize(width: 100, height: 100))
then:
self.physicsBody = SKPhysicsBody(circleOfRadius: self.size.width/2, center: self.position)
Turn on physics visual representation in you GameViewController.swift, like this:
skView.showsPhysics = true
self.size in your case probably referring to the scene. What you need is to set physics body's size like this:
yourNode.physicsBody = SKPhysicsBody(rectangleOfSize: yourNode.size)
Also keep in mind that if you are altering node's anchor point,you may end up with unexpected results. Anchor point defines how texture is drawn relative to the node. It has no effect on node's physics body.

How to create a ring with 3D effect using Sprite Kit?

I want to create a ring with a 3D effect using Sprite Kit. (SEE IMAGES)
I tried subclassing a SKNode and adding two nodes as children. (SEE CODE)
One node was a complete SKShapeNode ellipse, and the other was half ellipse using SKCropNode with a higher zPosition.
It looks good, but the SKCropNode increases the app CPU usage from 40% to 99%.
Any ideas on how to reduce the SKCropNode performance cost, or any alternative to create the same ring 3D effect?
class RingNode: SKNode {
let size: CGSize
init(size: CGSize, color: SKColor)
{
self.size = size
self.color = color
super.init()
ringPartsSetup()
}
private func ringPartsSetup() {
// LEFT PART (half ellipse)
let ellipseNodeLeft = getEllipseNode()
let leftMask = SKSpriteNode(texture: nil, color: SKColor.blackColor(), size: CGSize(
width: ellipseNodeLeft.frame.size.width/2,
height: ellipseNodeLeft.frame.size.height))
leftMask.anchorPoint = CGPoint(x: 0, y: 0.5)
leftMask.position = CGPoint(x: -ellipseNodeLeft.frame.size.width/2, y: 0)
let leftNode = SKCropNode()
leftNode.addChild(ellipseNodeLeft)
leftNode.maskNode = leftMask
leftNode.zPosition = 10 // Higher zPosition for 3D effect
leftNode.position = CGPoint(x: -leftNode.frame.size.width/4, y: 0)
addChild(leftNode)
// RIGHT PART (complete ellipse)
let rightNode = getEllipseNode()
rightNode.position = CGPoint(x: 0, y: 0)
rightNode.zPosition = 5
addChild(rightNode)
}
private func getEllipseNode() -> SKShapeNode {
let ellipseNode = SKShapeNode(ellipseOfSize: CGSize(
width: size.width,
height: size.height))
ellipseNode.strokeColor = SKColor.blackColor()
ellipseNode.lineWidth = 5
return ellipseNode
}
}
You've got the right idea with your two-layer approach and the half-slips on top. But instead of using a shape node inside a crop node, why not just use a shape node whose path is a half-ellipse? Create one using either CGPath or UIBezierPath API — use a circular arc with a transform to make it elliptical — then create your SKShapeNode from that path.
You may try converting your SKShapeNode to an SKSpriteNode. You can use SKView textureFromNode: (but we aware of issues with scale that require you to use it only after the node has been added to the view and at least one update cycle has run), or from scratch using an image (created programatically with a CGBitmapContext, of course).

How to Detect if a SKSpriteNode is in a SKShapeNode

I put a circular attack oval on a blue space ship and, if any SKSpriteNode enters the SKShapeNode (attack oval) the blue space ship can fire on the SKSpriteNode. The problem is that I can't figure out how to do the detection. I have tried physical bodies but, I can't have contact without having a collision.
Here is an example. I want the purple/blue attack circle to detect A,B,C,D,E
Here is the code I think you will need. RSSprite is short for red ship sprite
blueShip.position = CGPoint(x: 800, y: 400)
attackCircle = SKShapeNode(ellipseOfSize: CGSize(width: 1000, height: 400))
attackCircle.position = CGPoint(x: blueShip.position.x, y: blueShip.position.y)
RSSprite!.position = CGPoint(x: 200, y: 700)
RSSprite!.physicsBody = SKPhysicsBody(rectangleOfSize: RSSprite!.size)
In the update method you can check for an intersection of 2 nodes like this:
if([nodeA intersectsNode:nodeB]) {
// you have a collision
}

Physics not Detecting Collision

I simply have put a square shape node onto a scene, and made the physicsBody for the scene be the edge of the screen. I turned on the physics view so you can see all of the physics stuff. The square has a physics body around it, as does the border of the scene. However, when the square runs into the border, nothing happens. The square just passes straight through. Here is how I initialize the square:
let rect1 = CGRect(x: 100, y: 100, width: 50, height: 50)
let square = Square(rect: rect1)
square.fillColor = UIColor.blackColor()
square.zPosition = 200
square.physicsBody = SKPhysicsBody(edgeLoopFromRect: rect1)
square.physicsBody?.allowsRotation = false
square.physicsBody?.affectedByGravity = false
square.physicsBody?.restitution = 0.4
self.addChild(square)
Here is how I initialize the physics body for the scene:
let physicsBody = SKPhysicsBody(edgeLoopFromRect: view.bounds)
self.physicsBody = physicsBody
Very similar code has worked for me on other games, so I am not sure why no collisions happen. Any help is greatly appreciated thanks!
The movement of the balls must be caused by physics rather than just setting the position. The issue was fixed through using impulses to move the balls which then made them collide with the various objects.

How to fix a node in a position using SpriteKit

I have created a world using SpriteKit, containing a SKShapeNode. I'd like to tie it into the ceiling. The gravity and other stuff still have their effect on this shape, but it should hang from the ceiling. Like a lamp, or a rope.
My shape:
let shape = SKShapeNode(rectOfSize: CGSize(width: self.tamanhoQuadrado, height: self.tamanhoQuadrado))
When I add this:
shape.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: self.tamanhoQuadrado, height: self.tamanhoQuadrado))
It falls to the ground. I haven't found a property that can ignore gravity.
Found it!
//no gravity
shape.physicsBody!.affectedByGravity=false
//make it stay on it's place
shape.physicsBody!.dynamic=false

Resources