How to prevent SKPhysicsBody stretching - swift

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?

Related

Creating a physicsBody from a texture out of a texture atlas results in weird proportions

I use physicsBodies that are made from an image, I put an image file in the Assets.xcassets file and create the spriteNode using the image name as the imageNamed argument, I then use the spriteNodes texture as the texture argument of the physicsBody and the same size value from the spriteNode as the size argument. This works like a charm below 13.0 (13.0 has some issues with this). However, if I try to do this same thing with the same image files but in a Texture Atlas the spriteNode() still looks perfectly fine but the physicsBody is massively out of proportion, I would be able to get them to line up by dividing the width and height of the physicsBody by different values but the fact that I'm gonna have to brute force something means I've probably done something wrong
Image of result when using spriteAtlas, keep in mind the wings aren't part of the spriteNode and the rectangle around the eagle is a different body: oh no no no
How I create physicsBodies:
func createPigeon(size: CGSize, position: CGPoint) {
//W/o texture atlas
sprite = SKSpriteNode(imageNamed: "pigeonHitBox")
//with textureAtlas
sprite = SKSpriteNode(texture: gameScene.spriteAtlas.textureNamed("pigeonHitBox"))
sprite!.size = size
sprite!.position = position
sprite!.name = "Pigeon"
sprite!.physicsBody = SKPhysicsBody(texture: sprite!.texture!, size: size)
sprite!.zPosition = 1
sprite!.physicsBody!.isDynamic = true
defaultCollisions()
gameScene.addChild(sprite!)
}
So I figured out that the problem was due to the way SpriteKit overlaps and deletes alpha in order to squeeze more images into one atlas. The only fix I could find for this was putting the images I used for hitboxes into the Assets.xcassets file and making sure the animation action had resize set to false.
I get why this is done but this has just resulted in me not being able to put a good 13 images inside a textureAtlas, there should be an option to not axe alpha

How to measure volume or opaque pixel count of part of a sprite in Spritekit

I have a SKSpriteNode which has a PNG texture, partly transparent.
I want to make a logical split line on this sprite and then measure the volume or opaque pixel count in each part. The object of the exercise is to tell what percentage total sprite volume exists in each part.
I have done some research and came empty. Seems there are no built in methods to do so. Can you guide me in the right direction here?
you could create a "pixel perfect" SKPhysicsBody like this:
let sprite = SKSpriteNode(imageNamed: "Spaceship")
sprite.physicsBody = SKPhysicsBody(texture: sprite.texture!,
size: sprite.texture!.size())
And then access the property sprite.physicsBody.area which gives you the area of the body in square meters (you can convert it to points, here is the documentation)

SKSpriteNode or SKShapeNode for Circular Object

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!

Scale a SKPhysicsBody, how?

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
)
)

SKPhysicsBody uses only part of SKTexture

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 =)