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
Related
If I wanted to draw a simple red rectangle, should I use an SKShapeNode or an SKSpriteNode? What is the performance (speed to render) difference?
Are there any exceptions (like applying transparency, or maybe creating a physicsBody)?
I know what the primary purpose of both are, but I'm not sure which is better on performance for drawing a simple red square.
Code:
// Shape
let myShape = SKShapeNode(rectOf: CGSize(width: 100, height: 100))
myShape.fillColor = .red
myShape.strokeColor = .clear
// Sprite
let mySprite = SKSpriteNode(color: .red, size: CGSize(width: 100, height: 100))
SKSpriteNode offers higher performance than SKShapeNode class. See documentation here
If you want to add physicsbody to SKShapeNode, you should be aligned with shapenode points. For more sophisticated performance use SKSpriteNode. SKShapeNodes are useful when it is difficult to use a texture(may be a custom shape) and for building or displaying debugging information.
Furthermore, drawing/displaying a red rectangle is OK with SKShapeNode.
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!
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.
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).
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.