Physicsbody doesn't adhere to node's anchor point
Asked Answered
S

7

36

My scene has a bunch of rectangles with physics bodies that are the same size as the rectangle. I like to anchor all of my objects to CGPointZero, however I've noticed when I do that the physicsbody remains anchored in the middle. In other words, the position of my physics body is like 100 pixels lower and to the left of the visual representation.

Here is a simple snippet of code:

SKSpriteNode* square = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:CGSizeMake(width, height)];
square.anchorPoint = CGPointZero; //position based on bottom-left corner
square.position = CGPointMake(x, y);

square.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(width, height)];

Any ideas or advice to solving this problem would be appreciated. For example, if I could visualize the physics bodies, that might help, but I'm not sure how to.

UPDATE: So I've solved the problem by simply not setting the anchor point and repositioning my rectangles. So the problem still exists, but I have a work around in place and the work around is working well.

Sheepskin answered 18/11, 2013 at 10:14 Comment(3)
This is useful to find where your physics body actually is: #20085468Dianoia
AnchorPoint slides the texture around the node's position. The anchorPoint has no effect on physics shapes/bodies simply because it only defines the texture's offset relative to the node's position. If you want your shapes further down the corner, leave anchorPoint at its default and change the position accordingly. Also changing anchorPoint will adversely affect rotation and position of child nodes.Dramshop
saying that changing the anchor point well adversely affect rotation and position of child node is naive. Maybe I want to rotate on 0,0. I definitely want to position that way, considering all low level graphics APIs work off of the bottom left corner, and web development works of the top right corner. Working from the centre is actually very unique in the grand scheme of graphics development. With that said, your first 2 sentences are clear and correct. I suppose, I wish I could change the physics body anchor point :\Sheepskin
D
13

I wrote this to fix Apple's lack thereof:

use pathForRectangleOfSize:withAnchorPoint: to replace your call to bodyWithRectangleOfSize: whose brief documentation tells us the problem: "Creates a rectangular physics body centered on the owning node’s origin."

@implementation SKPhysicsBody (CWAdditions)

+ (CGPathRef)pathForRectangleOfSize:(CGSize)size withAnchorPoint:(CGPoint)anchor {
  CGPathRef path = CGPathCreateWithRect( CGRectMake(-size.width * anchor.x, -size.height * anchor.y,
                                                    size.width,   size.height), nil);
  return path;
}

+ (SKPhysicsBody *)bodyWithRectangleOfSize:(CGSize)size withAnchorPoint:(CGPoint)anchor {
  CGPathRef path = [self pathForRectangleOfSize:size withAnchorPoint:anchor];
  return [self bodyWithPolygonFromPath:path];
}

@end

Edit: There is a new API in 7.1 to provide for this oversight.

+ (SKPhysicsBody *)bodyWithRectangleOfSize:(CGSize)s center:(CGPoint)center
Dianoia answered 31/1, 2014 at 19:51 Comment(3)
I'm using 7.1 and that still doesn't work :(, also the link doesn't show anything regarding a withAnchorPoint method. [I cmd+f'd the page for withAnchorPoint] I did find [SKPhysicsBody bodyWithRectangleOfSize:square.size center: CGPointZero];Sheepskin
The center: are the apple initializer additions in 7.1. Center should be the anchor point in a [0-1, 0-1] range.Dianoia
The new API 7.1 center: method... +1Desrosiers
C
8

You can use

      [SKPhysicsBody bodyWithRectangleOfSize:size center: center];


       CGPoint center = CGPointMake(size.width*(anchorPoint.x-0.5f), size.height*(0.5f-anchorPoint.y))

should transform the bounding box according to the anchorPoint of the parents node

Coquette answered 4/9, 2014 at 22:45 Comment(1)
Of all the answers posted here, this was the only one that solved my issue with the physicsBody anchor point misaligned with the node anchor point. Thanks!Amoy
M
6

I am using Swift but the SKPhysicsBody was kind of half width and height wrong. I am using anchor point(0,0). Then I used the method with rectangleOfSize, center :

var cc = SKSpriteNode(color: UIColor.greenColor(), size: CGSizeMake(32, 64))
cc.physicsBody = SKPhysicsBody(rectangleOfSize: cc.size, center: CGPointMake(32/2, 64/2))

I hope it works for you too guys...thanks !

Megass answered 22/11, 2014 at 2:20 Comment(0)
E
5

You need the anchorPoint only when you set your spriteNode's position. I don't quite understand why would you need to move physicsBody (which is the same size of node, I presume) to a corner... But you might find useful this class method [SKPhysicsBody bodyWithPolygonFromPath:path].

Here is a nice generator for that: http://dazchong.com/spritekit/

Endeavor answered 18/11, 2013 at 11:4 Comment(2)
Neat tool, but it doesn't solve my problem. The problem is, the anchorPoint of the physics body appears to be the default width/2, height/2, even though I've set the anchorPoint of it's node to 0,0.Sheepskin
The physics body (via the call being made above) is created centered on the {0, 0} point of the sprite. If your {0, 0} point is not at the center of the sprite, the call is not useful. So, he wants to move the physics not back from the corner, not too it. You're call on the bodyWithPolygonFromPath: method is right on.Dianoia
H
2

I have run in to this myself when using SpriteKit. Unfortunately there appears to be issues based on the timing of creating a physics body and actually adding the node to the scene. If you swap the order from your code and ensure you don't do ANY physics changes until the node is actually in the render tree, that should resolve the 'weirdness' and everything will be all gravy.

Hypersensitive answered 7/4, 2014 at 14:42 Comment(1)
Thanks bro - my head was seriously wrecked with a similar issue, node was being added at origin until I moved the physics allocation until after the position allocationPovertystricken
U
1

Swift 4.1

let centerPoint = CGPoint(x: house1.size.width / 2 - (house1.size.width * house1.anchorPoint.x), y: house1.size.height / 2 - (house1.size.height * house1.anchorPoint.y))

house1.physicsBody = SKPhysicsBody(rectangleOf: house1.size, center: centerPoint)

Unhesitating answered 18/6, 2018 at 2:27 Comment(0)
T
0

Use default anchor point and it should solve your problem. I had the same problem and I had to programmatically set anchor point to x: 0.5 and y: 0.5 for every physics body in scene. This solved my problems.

Teledu answered 15/2, 2019 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.