I want CAEmitterCell emits in a specific angle. I use emitterCell.emissionLongitude = -CGFloat.pi to specify the orientation angle is -pi(which is left), but it emits to right as well.
func setUpEmitterCell() {
emitterCell.contents = UIImage(named: "spark_small")?.cgImage
emitterCell.velocity = 50.0
emitterCell.velocityRange = 500.0
let zeroDegreesInRadians = degreesToRadians(0.0)
emitterCell.spin = degreesToRadians(130.0)
emitterCell.spinRange = zeroDegreesInRadians
emitterCell.emissionRange = degreesToRadians(10.0)
emitterCell.emissionLongitude = -CGFloat.pi
emitterCell.lifetime = 1.0
emitterCell.birthRate = 1000.0
emitterCell.xAcceleration = 0.0
emitterCell.yAcceleration = 0.0
}
This is the problem:
emitterCell.velocity = 50.0
// but then:
emitterCell.velocityRange = 500.0
You are allowing the velocity to range so widely from its original value of 50 that it can be negative. When it is, the cells are emitted in the opposite direction (that is what negative velocity means).
Related
I am making a brick breaker style game in Xcode for iOS. There is no paddle and balls are all launched from the same location (determined by where the first ball falls from the last level). There are a varying number of balls launched each time based on the number of balls the player has created. Each game starts with one ball but the user collects more in playing. When applying an impulse to the ball sprites I can only either move one sprite or all ball sprites at once. How do I move the ball sprites with a delay between each sprites launch?
Below I will go over what I have tried already. Thank you in advance for any help!
So far I have tried a couple of things. First I was trying to create all ball sprites prior to allowing the user to launch and having all ball sprites at the same location. Then I enumerated over them and tried to launch them with a delay there. However this simply launched all balls simultaneously after the delay, not each individually.
gameWorldNode.enumerateChildNodes(withName: BallCategoryName) {
node, stop in
let ball = node as! SKSpriteNode
ball.move(toParent: gameWorldNode)
//Calculate Vector
var dx = CGFloat(touchLocation.x - ball.position.x)
var dy = CGFloat(touchLocation.y - ball.position.y)
//Calculate Magnitude
let magnitude = sqrt(dx * dx + dy * dy)
dx /= magnitude
dy /= magnitude
//Create Vector
let vector = CGVector(dx: 30.0 * dx, dy: 30.0 * dy)
let secondsToDelay = 0.25
DispatchQueue.main.asyncAfter(deadline: .now() + secondsToDelay){
//Apply impulse
ball.physicsBody!.applyImpulse(vector)
}
}
Secondly, It occurred to me that it would probably be better for game performance if I didn't create the ball sprite until right before the impulse is applied, after the previous ball is launched. So I tried the following code. However, while I think I may be on the right path now, the newly created ball sprites don't launch. They get created but for some reason they don't apply the impulse.
let ball = gameWorldNode.childNode(withName: BallCategoryName) as! SKSpriteNode
ball.move(toParent: gameWorldNode)
//Calculate Vector
var dx = CGFloat(touchLocation.x - ball.position.x)
var dy = CGFloat(touchLocation.y - ball.position.y)
//Calculate Magnitude
let magnitude = sqrt(dx * dx + dy * dy)
dx /= magnitude
dy /= magnitude
//Create Vector
let vector = CGVector(dx: 30.0 * dx, dy: 30.0 * dy)
ball.physicsBody!.applyImpulse(vector)
var i = 1
while (i != ballsAvailabe) {
//Create new ball sprite
let nextBall: SKSpriteNode = Ball()
nextBall.position = CGPoint(x: locationX, y: locationY)
gameWorldNode.addChild(nextBall)
let secondsToDelay = 0.1
DispatchQueue.main.asyncAfter(deadline: .now() + secondsToDelay) {
//Apply impulse to ball
nextBall.physicsBody!.applyImpulse(vector)
}
//Update i
i += 1
}
I have also tried to add the sprites to an array and iterate over the array. However, this simply launches each ball at once still.
for _ in 0..<ballsAvailabe {
//Create new ball sprite
let ball: SKSpriteNode = Ball()
ball.position = CGPoint(x: locationX, y: locationY)
ball.physicsBody!.categoryBitMask = nextBallCategory
ball.color = nextBallInPlay
ball.colorBlendFactor = 1
ball.physicsBody!.contactTestBitMask = BottomCategory | AddABallCategory | RedBlockCategory | BlueBlockCategory | OrangeBlockCategory | PurpleBlockCategory | GreenBlockCategory | CyanBlockCategory
ballSprites.append(ball)
gameWorldNode.addChild(ball)
}
for sprite in ballSprites {
let secondsToDelay = 0.3
DispatchQueue.main.asyncAfter(deadline: .now() + secondsToDelay) {
sprite.physicsBody!.applyImpulse(vector)
}
}
EDIT:
Following Johns comment below, I have added code to my second attempt to ensure the physics bodies are created properly. Sorry for all the variables in the code they are just global variables I have created and keep in its own file to ensure I am keeping values consistent throughout the code. This works better. When the user only has one ball it works perfectly. However, when the user has collected more balls to launch it will sometimes launch perfectly with the delay to the expected location. Other times it will launch only the first ball. Other times it will launch to an unexpected location.
Heres the updated code:
//Grab existing ball object
let ball = gameWorldNode.childNode(withName: BallCategoryName) as! SKSpriteNode
//Assign to game world node
ball.move(toParent: gameWorldNode)
//Apply ball properties
ball.color = nextBallInPlay
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width / 2)
ball.physicsBody!.categoryBitMask = RedBallCategory
ball.name = BallCategoryName
ball.colorBlendFactor = 1
ball.physicsBody?.pinned = false
ball.physicsBody?.mass = ballMass
ball.physicsBody?.affectedByGravity = ballGravity
ball.physicsBody?.allowsRotation = ballRotation
ball.physicsBody?.isDynamic = ballDynamic
ball.zPosition = ballZPos
ball.physicsBody?.friction = ballFriction
ball.physicsBody?.restitution = ballRestitution
ball.physicsBody?.linearDamping = ballLinearDaming
ball.physicsBody?.angularDamping = ballAngularDamping
//Stop more launches and accidently using power ups
isFingerOnScreen = true
canBallBeLaunched = false
canUsePowerUps = false
//Ensure physics world speed is accurate
physicsWorld.speed = 1
//Launching location
var dx = CGFloat(touchLocation.x - locationX)
var dy = CGFloat(touchLocation.y - locationY)
//Calculate Magnitude
let magnitude = sqrt(dx * dx + dy * dy)
dx /= magnitude
dy /= magnitude
//Create Vector
let vector = CGVector(dx: 30.0 * dx, dy: 30.0 * dy)
//Apply impule to first ball
ball.physicsBody!.applyImpulse(vector)
//loop to create x number of balls based on what the user has collected
var i = 1
while (i != ballsAvailabe) {
//Create new ball sprite
let nextBall: SKSpriteNode = Ball()
nextBall.position = CGPoint(x: locationX, y: locationY)
gameWorldNode.addChild(nextBall)
//Ball properties
nextBall.color = nextBallInPlay
nextBall.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width / 2)
nextBall.physicsBody!.categoryBitMask = RedBallCategory
nextBall.name = BallCategoryName
nextBall.colorBlendFactor = 1
nextBall.physicsBody?.pinned = false
nextBall.physicsBody?.mass = ballMass
nextBall.physicsBody?.affectedByGravity = ballGravity
nextBall.physicsBody?.allowsRotation = ballRotation
nextBall.physicsBody?.isDynamic = ballDynamic
nextBall.zPosition = ballZPos
nextBall.physicsBody?.friction = ballFriction
nextBall.physicsBody?.restitution = ballRestitution
nextBall.physicsBody?.linearDamping = ballLinearDaming
nextBall.physicsBody?.angularDamping = ballAngularDamping
//Delay between each ball
let secondsToDelay = 0.1
DispatchQueue.main.asyncAfter(deadline: .now() + secondsToDelay) {
//Apply impulse to ball
nextBall.physicsBody!.applyImpulse(vector)
}
//Update i
i += 1
}
I have a flying aircraft which I am following and I am also showing the path the aircraft has followed. I am drawing cylinders as a line for drawing the path. Its kind of drawing a line between 2 points. I have a cameraNode which is set to (0,200,200) initially. At that point I can see the aircraft. But when I start my flight. It goes out of the screen. I want 2 things :
Follow just the aircraft (Path won't matter).
Show whole path and also the aircraft.
I tried finding the min ad max x,y and z and taking average but it din't work. If you see below gif its too zoomed and aircraft has moved out of the screen
Here is how I set my camera:
- (void)setUpCamera {
SCNScene *workingScene = [self getWorkingScene];
_cameraNode = [[SCNNode alloc] init];
_cameraNode.camera = [SCNCamera camera];
_cameraNode.camera.zFar = 500;
_cameraNode.position = SCNVector3Make(0, 60, 50);
[workingScene.rootNode addChildNode:_cameraNode];
SCNNode *frontCameraNode = [SCNNode node];
frontCameraNode.position = SCNVector3Make(0, 100, 50);
frontCameraNode.camera = [SCNCamera camera];
frontCameraNode.camera.xFov = 75;
frontCameraNode.camera.zFar = 500;
[_assetActivity addChildNode:frontCameraNode]; //_assetActivity is the aircraft node.
}
Here is how I am changing camera position which is not working:
- (void)showRealTimeFlightPath {
DAL3DPoint *point = [self.aircraftLocation convertCooridnateTo3DPoint];
DAL3DPoint *previousPoint = [self.previousAircraftLocation convertCooridnateTo3DPoint];
self.minCoordinate = [self.minCoordinate findMinPoint:self.minCoordinate currentPoint:point];
self.maxCoordinate = [self.minCoordinate findMaxPoint:self.maxCoordinate currentPoint:point];
DAL3DPoint *averagePoint = [[DAL3DPoint alloc] init];
averagePoint = [averagePoint averageBetweenCoordiantes:self.minCoordinate maxPoint:self.maxCoordinate];
SCNVector3 positions[] = {
SCNVector3Make(point.x,point.y,point.z) ,
SCNVector3Make(previousPoint.x,previousPoint.y,previousPoint.z)
};
SCNScene *workingScene = [self getWorkingScene];
DALLineNode *lineNodeA = [[DALLineNode alloc] init];
[lineNodeA init:workingScene.rootNode v1:positions[0] v2:positions[1] radius:0.1 radSegementCount:6 lineColor:[UIColor greenColor]] ;
[workingScene.rootNode addChildNode:lineNodeA];
self.previousAircraftLocation = [self.aircraftLocation mutableCopy];
self.cameraNode.position = SCNVector3Make(averagePoint.x, averagePoint.y, z);
self.pointOfView = self.cameraNode;
}
Code in swift or objective c are welcomed.
Thanks!!
The first behavior you describe would most easily be achieved by chaining a look-at constraint and a distance constraint, both targeting the aircraft.
let lookAtConstraint = SCNLookAtConstraint(target: aircraft)
let distanceConstraint = SCNDistanceConstraint(target: aircraft)
distanceConstraint.minimumDistance = 10 // set to whatever minimum distance between the camera and aircraft you'd like
distanceConstraint.maximumDistance = 10 // set to whatever maximum distance between the camera and aircraft you'd like
camera.constraints = [lookAtConstraint, distanceConstraint]
For iOS 10 and earlier, you can implement a distance constraint using SCNTransformConstraint. Here's a basic (though slightly ugly š) implementation that uses linear interpolation to update the node's position.
func normalize(_ value: Float, in range: ClosedRange<Float>) -> Float {
return (value - range.lowerBound) / (range.upperBound - range.lowerBound)
}
func interpolate(from start: Float, to end: Float, alpha: Float) -> Float {
return (1 - alpha) * start + alpha * end
}
let target = airplane
let minimumDistance: Float = 10
let maximumDistance: Float = 15
let distanceConstraint = SCNTransformConstraint(inWorldSpace: false) { (node, transform) -> SCNMatrix4 in
let distance = abs(sqrt(pow(target.position.x - node.position.x, 2) + pow(target.position.y - node.position.y, 2) + pow(target.position.z - node.position.z, 2)))
let normalizedDistance: Float
switch distance {
case ...minimumDistance:
normalizedDistance = self.normalize(minimumDistance, in: 0 ... distance)
case maximumDistance...:
normalizedDistance = self.normalize(maximumDistance, in: 0 ... distance)
default:
return transform
}
node.position.x = self.interpolate(from: target.position.x, to: node.position.x, alpha: normalizedDistance)
node.position.y = self.interpolate(from: target.position.y, to: node.position.y, alpha: normalizedDistance)
node.position.z = self.interpolate(from: target.position.z, to: node.position.z, alpha: normalizedDistance)
return transform
}
The second behavior could be implemented by determining the bounding box of your aircraft and all of its path segments in the camera's local coordinate space, then updating the camera's distance from the center of that bounding box to frame all of those nodes in the viewport. frameNodes(_:), a convenience method that implements this functionality, was introduced in iOS 11 and is defined on SCNCameraController. I'd recommend using it if possible, unless you want to dive into the trigonometry yourself. You could use your scene view's default camera controller or create a temporary instance, whichever suits the needs of your app.
You need to calculate the angle of the velocity so that the camera points in the direction of the moving SCNNode.
This code will point you in the right direction.
func renderer(_ aRenderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: TimeInterval) {
// get velocity angle using velocity of vehicle
var degrees = convertVectorToAngle(vector: vehicle.chassisBody.velocity)
// get rotation of current camera on X and Z axis
let eX = cameraNode.eulerAngles.x
let eZ = cameraNode.eulerAngles.z
// offset rotation on y axis by 90 degrees
// this needs work, buggy
let ninety = deg2rad(90)
// default camera Y Euler angle facing north at 0 degrees
var eY : Float = 0.0
if degrees != 0 {
eY = Float(-degrees) - Float(ninety)
}
// rotate camera direction using cameraNode.eulerAngles and direction of velocity as eY
cameraNode.eulerAngles = SCNVector3Make(eX, eY, eZ)
// put camera 25 points behind vehicle facing direction of velocity
let dir = calculateCameraDirection(cameraNode: vehicleNode)
let pos = pointInFrontOfPoint(point: vehicleNode.position, direction:dir, distance: 25)
// camera follows driver view from 25 points behind, and 10 points above vehicle
cameraNode.position = SCNVector3Make(pos.x, vehicleNode.position.y + 10, pos.z)
}
func convertVectorToAngle(vector: SCNVector3) -> CGFloat {
let degrees = atan2(vector.z, vector.x)
return CGFloat(degrees)
}
func pointInFrontOfPoint(point: SCNVector3, direction: SCNVector3, distance: Float) -> SCNVector3 {
var x = Float()
var y = Float()
var z = Float()
x = point.x + distance * direction.x
y = point.y + distance * direction.y
z = point.z + distance * direction.z
let result = SCNVector3Make(x, y, z)
return result
}
func calculateCameraDirection(cameraNode: SCNNode) -> SCNVector3 {
let x = -cameraNode.rotation.x
let y = -cameraNode.rotation.y
let z = -cameraNode.rotation.z
let w = cameraNode.rotation.w
let cameraRotationMatrix = GLKMatrix3Make(cos(w) + pow(x, 2) * (1 - cos(w)),
x * y * (1 - cos(w)) - z * sin(w),
x * z * (1 - cos(w)) + y*sin(w),
y*x*(1-cos(w)) + z*sin(w),
cos(w) + pow(y, 2) * (1 - cos(w)),
y*z*(1-cos(w)) - x*sin(w),
z*x*(1 - cos(w)) - y*sin(w),
z*y*(1 - cos(w)) + x*sin(w),
cos(w) + pow(z, 2) * ( 1 - cos(w)))
let cameraDirection = GLKMatrix3MultiplyVector3(cameraRotationMatrix, GLKVector3Make(0.0, 0.0, -1.0))
return SCNVector3FromGLKVector3(cameraDirection)
}
func deg2rad(_ number: Double) -> Double {
return number * .pi / 180
}
Hey I have a ball that gets moved by a force-applied. What im trying to get it to do is basically have the causal effect of gravity acting upon it while its moving through the air to its destination. basically when the "move to" action is playing gravity does not take affect so instead of slowly falling down to the ground it instead moves to its final position then it just falls straight down when the "move to" action stops. do to the gravity in the scene.
Im trying to get the ball to be thrown in an arc and land on the target?
Code:
func CreateBall() {
let BallScene = SCNScene(named: "art.scnassets/Footballs.dae")
Ball = BallScene!.rootNode.childNodeWithName("Armature", recursively: true)! //the Amature/Bones
Ballbody = BallScene!.rootNode.childNodeWithName("Ball", recursively: true)!
let collisionCapsuleRadius3 = CGFloat(0.01) // Width of physicsBody
let collisionCapsuleHeight3 = CGFloat(0.01) // Height of physicsBody
Ball.position = SCNVector3Make(Guy.position.x, Guy.position.y, Guy.position.z)
Ball.scale = SCNVector3Make(5, 5, 5)
Ball.rotation = SCNVector4Make(0.0,0.0,0.0,0.0) // x,y,z,w
Ball.physicsBody = SCNPhysicsBody(type: .Dynamic, shape:SCNPhysicsShape(geometry: SCNCapsule(capRadius: collisionCapsuleRadius3, height: collisionCapsuleHeight3), options:nil))
Ball.physicsBody?.affectedByGravity = true
Ball.physicsBody?.friction = 1 //
Ball.physicsBody?.restitution = 0 //bounceness of the object. 1.0 will boounce forever
Ball.physicsBody?.angularDamping = 1 // ability to rotate
Ball.physicsBody?.mass = 1
Ball.physicsBody?.rollingFriction = 1
Ball.physicsBody!.categoryBitMask = BitmaskCollision4
Ball.physicsBody?.contactTestBitMask = BitmaskCollision3 //| BitmaskCollision2
Ballbody.physicsBody?.collisionBitMask = BitmaskCollision2 | BitmaskCollision3 | BitmaskCollision//| BitmaskCollision2
scnView.scene!.rootNode.addChildNode(Ball)
scnView.scene!.rootNode.addChildNode(Ballbody)
}
CreateBall()
now this is where the magic happens:
scnView.scene!.physicsWorld.gravity = SCNVector3(x: 0, y: -9.8, z: 0)
let location = SCNVector3(Guy2.presentationNode.position.x, 0.0, Guy2.presentationNode.position.z + Float(50) )
let moveAction = SCNAction.moveTo(location, duration: 2.0)
Ball.runAction(SCNAction.sequence([moveAction]))
let forceApplyed = SCNVector3(x: 0.0, y: 100.0 , z: 0.0)
Ball.physicsBody?.applyForce(forceApplyed, atPosition: Ball.presentationNode.position, impulse: true)
Combining SCNActions and physics doesn't work, you need to use one or the other. Using physics you can calculate the exact force needed to propel your node to a target.
I have adapted a solution for Unity found here and utilised an SCNVector3 extension that makes some of the calculations much easier.
Basically you pass in an SCNNode that you want to throw, an SCNVector3 for the target and an angle (in radians) that you want the node to be thrown at. This function will then work out the force required to reach the target.
func shootProjectile() {
let velocity = ballisticVelocity(ball, target: target.position, angle: Float(0.4))
ball.physicsBody?.applyForce(velocity, impulse: true)
}
func ballisticVelocity(projectile:SCNNode, target: SCNVector3, angle: Float) -> SCNVector3 {
let origin = projectile.presentationNode.position
var dir = target - origin // get target direction
let h = dir.y // get height difference
dir.y = 0 // retain only the horizontal direction
var dist = dir.length() // get horizontal distance
dir.y = dist * tan(angle) // set dir to the elevation angle
dist += h / tan(angle) // correct for small height differences
// calculate the velocity magnitude
let vel = sqrt(dist * -scene.physicsWorld.gravity.y / sin(2 * angle))
return dir.normalized() * vel * Float(projectile.physicsBody!.mass)
}
It is also important to set the damping of the physicsBody to 0, otherwise it will be affected by air resistance.
Iām not going to pretend to know exactly how this works, but Wikipedia has articles that explain all the maths behind it.
UPDATE
Since using the code above I've noticed it doesn't always work, especially when the heights of the origin and target are different. From the same forum this function seems more reliable.
func calculateBestThrowSpeed(origin: SCNVector3, target: SCNVector3, timeToTarget:Float) -> SCNVector3 {
let gravity:SCNVector3 = sceneView.scene!.physicsWorld.gravity
let toTarget = target - origin
var toTargetXZ = toTarget
toTargetXZ.y = 0
let y = toTarget.y
let xz = toTargetXZ.length()
let t = timeToTarget
let v0y = y / t + 0.5 * gravity.length() * t
let v0xz = xz / t
var result = toTargetXZ.normalized()
result *= v0xz
result.y = v0y
return result
}
I have made a blue ball that can be dragged by the user only on a red circled path:
I want to check how many times the user make a forward or backward lap (the start & end is at the top of the circle path), for example - If he drag the ball in a clockwise way so the laps is +1, and if he drag it to other way the laps is -1.
I tried to do this(This inculdes the dragging of the ball and my try to count laps):
#IBAction func dragBall(recognizer: UIPanGestureRecognizer) {
let point = recognizer.locationInView(self.view);
let earthX = Double(point.x)
let earthY = Double(point.y)
let midViewXDouble = Double(midViewX)
let midViewYDouble = Double(midViewY)
let angleX = (earthX - midViewXDouble)
let angleY = (earthY - midViewYDouble)
let angle = atan2(angleY, angleX)
let earthX2 = midViewXDouble + cos(angle)*100
let earthY2 = midViewYDouble + sin(angle)*100
circlePath2 = UIBezierPath(arcCenter: CGPoint(x: earthX2,y: earthY2), radius: CGFloat(10), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
shapeLayer2.path = circlePath2.CGPath
if degrees == 0 {
laps += 1
print(laps)
}
}
And it worked! but when the user drags the ball very fast it do not calculate, and it do not calculate backwards.
Here is a possible solution, following the approach indicated in the comments. First you need some additional instance variables:
var previousAngle = -M_PI_2 // top position if y-coordinate points down
var totalAngle = 0.0
var laps = 0
In dragBall, you calculate how much the angle has changed.
Since the angle can "jump" from -Ļ to Ļ, or vice versa, the difference
is normalised to the range -Ļ ... Ļ:
var delta = angle - previousAngle
if delta > M_PI {
delta -= 2 * M_PI
} else if delta < -M_PI {
delta += 2 * M_PI
}
previousAngle = angle
Then update the total change in the angle:
totalAngle += delta
and from that you can determine the number of laps:
laps = Int(floor(totalAngle/(2 * M_PI)))
I have a player. He has to jump over some blocks.
However, it seems like the SKPhysicsBody(rectangleOfSize: ... ) isn't aligned properly. When the character hits the upper half of the block it just passes through and he can't pass below it because it collides with an invisible SKPhysicsBody.
Depending on how I put the anchor point it sometimes even happens that the physics body is to the left or right of it's SKSpriteNode.
My code for the blocks:
self.smallBlock.anchorPoint = CGPointMake(0.5, 0.5)
self.smallBlock.position = CGPointMake(CGRectGetMaxX(self.frame) + self.smallBlock.size.width, CGRectGetMinY(self.frame) + self.runningBar.size.height * 2)
self.smallBlock.physicsBody = SKPhysicsBody(rectangleOfSize: self.smallBlock.size)
self.smallBlock.physicsBody?.dynamic = false
self.smallBlock.physicsBody?.categoryBitMask = colliderType.Block.rawValue
self.smallBlock.physicsBody?.contactTestBitMask = colliderType.Character.rawValue
self.smallBlock.physicsBody?.collisionBitMask = colliderType.Character.rawValue
self.smallBlock.physicsBody?.usesPreciseCollisionDetection = true
self.addChild(self.smallBlock)
self.character.anchorPoint = CGPointMake(0, 0.25)
self.character.position = CGPointMake(CGRectGetMinX(self.frame) - self.character.size.width, CGRectGetMinY(self.frame) + self.character.size.height)
self.initPosX = CGRectGetMinX(self.frame) + (self.character.size.width * 1.25)
Code for the character
self.character.anchorPoint = CGPointMake(0, 0.25)
self.character.position = CGPointMake(CGRectGetMinX(self.frame) - self.character.size.width, CGRectGetMinY(self.frame) + self.character.size.height)
self.initPosX = CGRectGetMinX(self.frame) + (self.character.size.width * 1.25)
self.character.physicsBody = SKPhysicsBody(rectangleOfSize: self.character.size)
self.character.physicsBody?.affectedByGravity = true
self.character.physicsBody?.categoryBitMask = colliderType.Character.rawValue
self.character.physicsBody?.contactTestBitMask = colliderType.Block.rawValue
self.character.physicsBody?.collisionBitMask = colliderType.Block.rawValue
self.character.physicsBody?.usesPreciseCollisionDetection = true
self.character.physicsBody?.affectedByGravity = true
self.character.physicsBody?.allowsRotation = false
self.addChild(self.character)
Solution:
I've added skView.showsPhysics = true to my View Controller. When you run the app in the simulator it will outline every object like shown here.
It turns out setting custom anchor points messes up the rectangleOfSize-positions.