I'm reasonably sure I've previously seen code somewhere that scales a SKPhysicsBody, but google and the docs aren't helping, making me more confused than normal.
Is there a way to scale a physic's body in SpriteKit?
The docs, here, don't mention anything about it: https://developer.apple.com/reference/spritekit/skphysicsbody
If you assign a physics body to a sprite and scale that sprite, the physics body will scale with it.
So the answer I think to your question is a solid "no"; at least not in anything I've seen before.
If you care to dabble in a workaround:
Create a new physics body that is larger than what you currently have. Make a method or two to accomplish this.
node.physicsBody = scaledPhysicsBody(bodyToScale: xxxx)
2.
I would just make a blank SKNode and child it to whatever it is that you want to be hit-detectable. Then get rid of the parent's physics body and just use the child's. Now, you can scale the child node (and thus the PB) without affecting the graphics of the main sprite.
just updating this in 2023:
if you create you physics body from the sprites texture, you can use the SKPhysicsBody initialiser with texture and size property like this:
let scale: CGFloat = 0.9
self.physicsBody = SKPhysicsBody(
texture: self.texture!,
size: CGSize(
width: self.size.width * scale,
height:self.size.height * scale
)
)
Related
Does anyone have any guidance how to create a SpriteKit object that looks like a circle with circular physics properties? I've considered using SKShapeNode, yet after reading comments in documentation like this one "the SKSpriteNode class offers higher performance than this class, so use shape nodes sparingly" here https://developer.apple.com/documentation/spritekit/skshapenode, I'm reluctant to use SKShapeNode.
I have code to create an SKSpriteNode from image that makes it look like a circle...
sprite = SKSpriteNode(imageNamed:spriteImage)
...and I've applied a circular physics body...
sprite.physicsBody = SKPhysicsBody(circleOfRadius: (width / 2))
I've set properties such as allowrotation, affectedbygravity and isDynamic to true in the physics body...
physics = sprite.physicsBody
physics.affectedByGravity = true
physics.allowsRotation = true
physics.isDynamic = true
The circle SKSpriteNode still behaves like a square. Instead of rolling like a wheel, the object flops like a square.
cc was right. The original physics body was set to a circle, then at some point in the code the physics body was changed back into a square. I fixed that part of the code and it is working now. Thanks!
I'm trying to make a physics body that outlines the sprite node, example: instead of using SKPhysicsBody(circleOfSize...) and just getting the circle shape or using SKPhysicsBody(RectangleOfSize...) but i thought there was an "AlphaMask" or something like that that would allow, say if my sprite node was the shape of a cup or a "V" shape that would allow objects into the open top and get caught inside the "V"? thanks in advance :)
so the first picture is what i keep getting when i try the rectangle one and the second picture is the type i need!
I think the best solution could be to build a path and after to make:
SKPhysicsBody.init(edgeLoopFrom: path!)
This is the official source documentation:
/**
Creates an edge loop from a path. A loop is automatically created by joining the last point to the first. The path must have no self intersection. Edges have no volume and are intended to be used to create static environments. Edges can collide with body's of volume, but not with each other.
#param path the path to use
*/
public /*not inherited*/ init(edgeLoopFrom path: CGPath)
With this solution you will able to define precisely your shape following CGPath construction (the 'V' shape).
If you're using a PNG image (or any image type that supports clear pixels), you can just create a physicsBody from a texture:
let sprite = SKSpriteNode(imageNamed: "Spaceship")
sprite.physicsBody = SKPhysicsBody(texture: sprite.texture!, size: sprite.texture!.size())
This creates a physicsBody based on the clear and coloured pixels of the texture to do its best at matching the shape.
Be warned that using this isn't always 100% accurate and may cause issues if used with highly complex textures (lag, memory issues, etc...)
As per Apples Docs:
When choosing a shape for your physics
body, do not be overly precise.
More complex shapes require more work to be properly simulated.
SKPhysicsBody Apple Docs
I have a few images that can detect when they get touched right now I am using
plane.physicsBody = SKPhysicsBody(circleOfRadius: plane.frame.height / 2)
but I need it so it is the boarder of the image not a circle or rectangle.
We have a plane and you want a physical body.
Your first approach is circleOfRadius (the physical representation is a circle with a given radius). You can use another shape, such a rectangle:
plane.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(100, height: 100))
As explained in the comments you can also use the shape of a sprite (texture) to create the shape of the physics body:
plane.physicsBody = SKPhysicsBody(texure: plane.texture!, size: plane.size)
But a good way to choose it's this: if you want your game to run smootly on many different devices, don't make sure the physics calculations become too complicated. In other words if you have many object around your plane with physical behavior moving around and colliding with each other, you may choose to use simplified shapes to deal with the physics more efficiently, especially if a shape already looks a lot like a rectangle or a circle.
The sprite I use for my character looks something like this (pink = transparent part):
After I set physicsBody to my node with self.physicsBody = SKPhysicsBody(texture: self.texture!, size: self.size), and set my SKView to show physics, I get an outline like this:
Which is, basically, the right mask, stretched to fit the size of the image.
Is there any way to get a physicsBody exactly around my character?
After playing around for quite a while, I've found the solution:
It's weird, but giving the SKPhysicsBody initializer a new SKTexture made from the same image, used for creating the SKTexture of SKSpriteNode initializer, worked perfectly well for me.
It should work. It works in my code with this line:
self.physicsBody = SKPhysicsBody.init(texture: self.texture!, size: self.frame.size)
Are you sure you do not scale the sprite after the creation of the physics body?
I'm using an SKTexture with an image and set the SKPhysicsBody. Like that:
var moleTexture = SKTexture(imageNamed: "moleTop1")
leftPlayer = SKSpriteNode(texture: moleTexture)
leftPlayer.physicsBody = SKPhysicsBody(texture: moleTexture, size: leftPlayer.texture!.size())
Now after I start my game, I noticed that the physicsBody is set wrong. I've activated the showPhysics property and my image looks like that:
As you see, the only thing which is used by SKPhysicsBody is the little part on the middle left(blue border).
How can I change that so that the whole image will be used?
That looks interesting. I believe it will only create an outline (or one shape) and it appears to be starting from the left and because there are no other pixels near enough it calls it done.
I wonder if you get a different result if those pixels are touching. I would try and validate that first. If that is the case you may have to change the texture or use a different variation of the texture for the physical body.
I hope that helps =)