iGetIt
iGetIt

Reputation: 695

How to set physics body for a sprite with rounded corners

I have created a SKShapeNode in the following way,

let sprite = SKShapeNode(rect: CGRect(x: -20, y: -10, width: 40, height: 20), cornerRadius: 10)

I also set a physics body like so,

sprite.physicsBody = SKPhysicsBody(rectangleOf: sprite.frame.size)

but I realized that the collisions and contacts weren't precise, so I changed showsPhysics to true and got the following. How can I make the physics body precise, even for the rounded corners?

enter image description here

Upvotes: 2

Views: 1313

Answers (3)

Simone Pistecchia
Simone Pistecchia

Reputation: 2842

From the documentation:

Maybe the #4 is your case

enter image description here

let spaceShipTexture = SKTexture(imageNamed: "spaceShip.png")

Spaceship 1: circular physics body

let circularSpaceShip = SKSpriteNode(texture: spaceShipTexture)
circularSpaceShip.physicsBody = SKPhysicsBody(circleOfRadius: max(circularSpaceShip.size.width / 2,
                                                                  circularSpaceShip.size.height / 2))  

Spaceship 2: rectangular physics body

let rectangularSpaceShip = SKSpriteNode(texture: spaceShipTexture)
rectangularSpaceShip.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: circularSpaceShip.size.width,
                                                                     height: circularSpaceShip.size.height))

Spaceship 3: polygonal physics body

let polygonalSpaceShip = SKSpriteNode(texture: spaceShipTexture)
let path = CGMutablePath()
path.addLines(between: [CGPoint(x: -5, y: 37), CGPoint(x: 5, y: 37), CGPoint(x: 10, y: 20),
                        CGPoint(x: 56, y: -5), CGPoint(x: 37, y: -35), CGPoint(x: 15, y: -30),
                        CGPoint(x: 12, y: -37), CGPoint(x: -12, y: -37), CGPoint(x: -15, y: -30),
                        CGPoint(x: -37, y: -35), CGPoint(x: -56, y: -5), CGPoint(x: -10, y: 20),
                        CGPoint(x: -5, y: 37)])
path.closeSubpath()
polygonalSpaceShip.physicsBody = SKPhysicsBody(polygonFrom: path)

Spaceship 4: physics body using texture’s alpha channel

let texturedSpaceShip = SKSpriteNode(texture: spaceShipTexture)
texturedSpaceShip.physicsBody = SKPhysicsBody(texture: spaceShipTexture,
                                              size: CGSize(width: circularSpaceShip.size.width,
                                                           height: circularSpaceShip.size.height))

Upvotes: 3

ThiagoAM
ThiagoAM

Reputation: 1542

Remember that too much precision is very bad for performance. Read this: https://developer.apple.com/reference/spritekit/skphysicsbody

For general cases, it would be better to ignore the corners and stick with the normal rectangle physics, unless you REALLY need that precision. If you do, you could use a SKTexture on a SKSpriteNode instead of a ShapeNode. That would be much easier, because you could simply do this:

let size = CGSize(width: 100, height: 50)
let roundedRectangleTexture = SKTexture(image: UIImage(named: "textureImage")!)
let mySpriteNode = SKSpriteNode(texture: roundedRectangleTexture, size: size)
mySpriteNode.physicsBody = SKPhysicsBody(texture: roundedRectangleTexture, size: size)

With a texture, you can easily make a more detailed and precise physicsBody by simply using the SKPhysicsBody(texture: size:) constructor.

Upvotes: 3

Stephen
Stephen

Reputation: 317

I would follow the documentation of SKPhysicsBody, and create a polygonal shape that approximates the rounded corners of your sprite.

An example on the documentation shows that you can define a polygonal physics body like so:

// Spaceship 3: polygonal physics body
let polygonalSpaceShip = SKSpriteNode(texture: spaceShipTexture)
let path = CGMutablePath()
path.addLines(between: [CGPoint(x: -5, y: 37), CGPoint(x: 5, y: 37), CGPoint(x: 10, y: 20),
                        CGPoint(x: 56, y: -5), CGPoint(x: 37, y: -35), CGPoint(x: 15, y: -30),
                        CGPoint(x: 12, y: -37), CGPoint(x: -12, y: -37), CGPoint(x: -15, y: -30),
                        CGPoint(x: -37, y: -35), CGPoint(x: -56, y: -5), CGPoint(x: -10, y: 20),
                        CGPoint(x: -5, y: 37)])
path.closeSubpath()
polygonalSpaceShip.physicsBody = SKPhysicsBody(polygonFrom: path)

Upvotes: 0

Related Questions