SKSpriteNode creates a thin coloured line - ios

So I am using 3 SKSpriteNode's in my application. floorSprite, leftWall and rightWall.
This is the code I am currently using:
let floorSprite = SKSpriteNode()//(imageNamed: "floor")
floorSprite.alpha = 0.0
floorSprite.anchorPoint = CGPoint(x: 0.5, y: CGPoint.zero.y)
floorSprite.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.frame.size.width, height: floorSprite.size.height + 12))
floorSprite.physicsBody?.isDynamic = false
floorSprite.physicsBody?.restitution = 0.4
floorSprite.position = CGPoint(x: self.frame.minX, y: self.frame.minY + (floorSprite.size.height / 2))
floorSprite.physicsBody?.contactTestBitMask = 0x1 << 1
floorSprite.physicsBody?.collisionBitMask = 0x1 << 1
floorSprite.zPosition = 4
floorSprite.aspectFillToSize(self.frame.size)
self.addChild(floorSprite)
self.floorSprite = floorSprite
let leftwall = SKSpriteNode()
leftwall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 0.1, height: self.frame.size.height*2))
leftwall.physicsBody?.collisionBitMask = 0x1 << 1
leftwall.physicsBody?.isDynamic = false
leftwall.position = CGPoint(x: 0 , y: self.frame.size.height / 2.0)
leftwall.zPosition = 4
leftwall.physicsBody?.restitution = 1.0
self.addChild(leftwall)
let rightwall = SKSpriteNode()
rightwall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 0.1, height: self.frame.size.height*2))
rightwall.physicsBody?.collisionBitMask = 0x1 << 1
rightwall.physicsBody?.isDynamic = false
rightwall.physicsBody?.restitution = 1.0
rightwall.position = CGPoint(x: self.frame.size.width , y: self.frame.size.height / 2.0)
rightwall.zPosition = 4
self.addChild(rightwall)
Here is a screenshot of the issue I have. You can see the light blue lines that shows. If I remove the self.addChild line, the Sprite is not there, and the light blue color gone.
CLICK HERE FOR IMAGE.
Any ideas what might be wrong here? I have tried adding leftWall.isHidden = true and leftWall.alpha = 0.0 but that has no effect...

This looks like you have SKScene.showPhysics on.. turn this off in your appdelegate (or didmovetoview) or wherever you turned it on, and the lines should go away.
These are caused by your physics bodies :)

Related

Weird Spritekit Collision Bug depending on SKSpriteNode position

I'm having a weird Spritekit issue where my moving SKSpriteNode is passing through a fixed SKSpriteNode depending on the position of the fixed SKSpriteNode.
UPDATE: Code works in simulator but not on real device.
Example:
Placing my bin SKSpriteNode at position x: -500, y: 100 works fine and my moving SKSpriteNode collides as expected.
Placing my bin SKSpriteNode at position x: -600, y: 100 DOES NOT work and my moving SKSpriteNode DOES NOT collide with the bin.
Using view.showsPhysics = true shows that there is physics bodies in both cases.
x values between -500 and -508 work as expected. All other values I have tried did not work.
Collisions with my other fixed SKSpriteNodes work as expected.
enum CollisionTypes: UInt32 {
case Plane = 1
case FloorAndRoof = 2
case OtherObject = 4
case FinishPoint = 8
}
Code to create levels
func createLevel(level: Int) {
switch level {
case 1:
createFloor()
createRoof()
createTable(position: CGPoint(x: 750, y: 150))
createCeilingFan(position: CGPoint(x: 750, y: 560))
createCeilingFan(position: CGPoint(x: 2000, y: 560))
createWaterDispenser(position: CGPoint(x: 1500, y: 212))
createBin(position: CGPoint(x: -500, y: 100)) // THIS IS THE PROBLEM LOCATION
createFinishPoint(position: CGPoint(x: -500, y: 100))
break
case 2:
createFloor()
createRoof()
createTable(position: CGPoint(x: 250, y: 150))
createCeilingFan(position: CGPoint(x: 750, y: 560))
createCeilingFan(position: CGPoint(x: 2000, y: 560))
createWaterDispenser(position: CGPoint(x: 1500, y: 212))
createBin(position: CGPoint(x: -600, y: 100))
createFinishPoint(position: CGPoint(x: -300, y: 200))
break
default:
break
}
}
Moving SKSpriteNode
func createPlane() {
plane = SKSpriteNode(imageNamed: "plane1")
plane.name = "plane1"
//plane.position = CGPoint(x: -UIScreen.main.bounds.width + plane.size.width , y: 0)
plane.position = CGPoint(x: 0, y: 300)
plane.zPosition = 1
//plane.physicsBody = SKPhysicsBody(texture: plane.texture!, size: plane.texture!.size())
plane.physicsBody = SKPhysicsBody(texture: planeTexture, size: planeTexture.size())
plane.physicsBody?.allowsRotation = true
plane.physicsBody?.categoryBitMask = CollisionTypes.Plane.rawValue
plane.physicsBody?.collisionBitMask = CollisionTypes.FloorAndRoof.rawValue | CollisionTypes.OtherObject.rawValue // dont collide with finish point
plane.physicsBody?.contactTestBitMask = CollisionTypes.FloorAndRoof.rawValue | CollisionTypes.OtherObject.rawValue | CollisionTypes.FinishPoint.rawValue
plane.physicsBody?.usesPreciseCollisionDetection = true
plane.physicsBody?.isDynamic = true
plane.physicsBody?.friction = 1
plane.physicsBody?.restitution = 0
plane.physicsBody?.mass = 0.1 // customise for different planes
plane.physicsBody?.angularDamping = 1
plane.physicsBody?.linearDamping = 0.2 // customise for different planes
liftFactor = 0.1 // customise for different planes
addChild(plane)
flightMode = 4 // dead, should drop to floor and change to mode 0 when at rest
//print(flightMode)
}
Bin SKSpriteNode that moving Plane should collide with.
func createBin(position: CGPoint) {
binFront = SKSpriteNode(imageNamed: "binFront")
binFront.name = "binFront"
binFront.setScale(0.15)
binFront.position = position
binFront.zPosition = 2 // in front of plane
addChild(binFront)
binBack = SKSpriteNode(imageNamed: "binBack")
binBack.name = "binBack"
binBack.setScale(0.15)
binBack.position = position
binBack.zPosition = 0 // behind plane
addChild(binBack)
binPhysicsBody = SKSpriteNode(imageNamed: "binPhysicsBody")
binPhysicsBody.name = "binPhysicsBody"
binPhysicsBody.physicsBody = SKPhysicsBody(texture: binPhysicsBody.texture!, size: binPhysicsBody.texture!.size())
binPhysicsBody.setScale(0.15)
binPhysicsBody.physicsBody?.allowsRotation = false
binPhysicsBody.physicsBody?.categoryBitMask = CollisionTypes.OtherObject.rawValue
binPhysicsBody.physicsBody?.collisionBitMask = CollisionTypes.Plane.rawValue
binPhysicsBody.physicsBody?.contactTestBitMask = CollisionTypes.Plane.rawValue
binPhysicsBody.physicsBody?.usesPreciseCollisionDetection = false
binPhysicsBody.physicsBody?.isDynamic = false
binPhysicsBody.physicsBody?.friction = 1
binPhysicsBody.physicsBody?.restitution = 0
binPhysicsBody.physicsBody?.mass = 50
binPhysicsBody.position = position
binPhysicsBody.zPosition = 0
addChild(binPhysicsBody)
}
I still don't know the cause of my issue but I got around it by changing the image used to create my physics body. I used a slightly thicker 'wall thickness' on the bin.

Spritekit ground not touching bottom of screen

I am working on a spritekit game and it all is working correctly, yet my ground is in the middle of the simulators screen. I have tried everything to make it be at the bottom of the screen. one function.
let groundTexture = SKTexture(imageNamed: "Ground")
groundTexture.filteringMode = .nearest
for i in stride(from: 0, to: 2 + self.frame.size.width / groundTexture.size().width, by: 1) {
let ground = SKSpriteNode(texture: groundTexture)
ground.zPosition = 1.0 //-10
//ground.position = CGPoint(x: (groundTexture.size().width / 2.0 + (groundTexture.size().width * CGFloat(i))), y: groundTexture.size().height / 4.0) //original position
ground.position = CGPoint(x: 0, y: groundTexture.size().height / +0) //tried this from a tutorial
ground.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.frame.size.width * 2.0, height: groundTexture.size().height / 4.0)) //erase * 4 test
ground.setScale(1.2)
ground.physicsBody?.isDynamic = false
ground.physicsBody?.allowsRotation = false
ground.physicsBody?.affectedByGravity = false
ground.physicsBody?.categoryBitMask = groundCategory
//contact and collision bitmask
ground.physicsBody?.contactTestBitMask = playerCategory | enemy1Category | enemy2Category | enemy3Category | enemy4Category | obstacleCategory | coinCatergory
ground.physicsBody?.collisionBitMask = playerCategory | enemy1Category | enemy2Category | enemy3Category | enemy4Category | obstacleCategory | coinCatergory
ground.physicsBody?.restitution = 0.0
self.addChild(ground)
let moveLeft = SKAction.moveBy(x: -groundTexture.size().width, y: 0, duration: 5)
let moveReset = SKAction.moveBy(x: groundTexture.size().width, y: 0, duration: 0)
let moveLoop = SKAction.sequence([moveLeft, moveReset])
let moveForever = SKAction.repeatForever(moveLoop)
ground.run(moveForever)
}
By default a scene's anchorPoint coordinates are 0, 0 unless otherwise specified. anchorPoint(x: 0, y: 0) is the center of the screen. You are not specifying a position for your ground so it gets automatically added to the scenes anchorPoint (which is the middle of the screen).
You need to either change the scenes anchorPoints to the bottom of the screen or adjust the ground position accordingly such as...
ground.position = CGPoint(x: 0 - self.size.width / 2 + ground.size.width / 2, y: 0 - self.size.height / 2 + ground.size.height / 2)
(the above example assumes you are adding the ground in the scene and self = scene)
for your reference...

SpriteKit - Collision detection not working

i've got a problem with the collisions.
adding physicbody depending on tilemap:
guard let tilemap = childNode(withName: "LevelGround") as? SKTileMapNode else { return }
let tileSize = tilemap.tileSize
let halfWidth = CGFloat(tilemap.numberOfColumns) / 2.0 * tileSize.width
let halfHeight = CGFloat(tilemap.numberOfRows) / 2.0 * tileSize.height
for row in 0..<tilemap.numberOfRows {
for col in 0..<tilemap.numberOfColumns {
if tilemap.tileDefinition(atColumn: col, row: row) != nil {
let x = CGFloat(col) * tileSize.width - halfWidth
let y = CGFloat(row) * tileSize.height - halfHeight
let rect = CGRect(x: 0, y: 0, width: tileSize.width, height: tileSize.height)
let tileNode = SKShapeNode(rect: rect)
tileNode.position = CGPoint(x: x, y: y)
tileNode.physicsBody = SKPhysicsBody(rectangleOf: tileSize, center: CGPoint(x: tileSize.width / 2.0, y: tileSize.height / 2.0))
tileNode.physicsBody?.isDynamic = false
tileNode.physicsBody?.affectedByGravity = false
tileNode.physicsBody?.collisionBitMask = Physics().player | Physics().bullet
tileNode.physicsBody?.categoryBitMask = Physics().ground
tileNode.physicsBody?.contactTestBitMask = Physics().ground | Physics().player
tileNode.physicsBody?.friction = 0.1
tileNode.physicsBody?.restitution = 0
tileNode.strokeColor = .white
tileNode.name = "Ground"
self.world.addChild(tileNode)
}
}
}
Let the bullet spawn on tapping the action2 button:
if self.ctrlAction2.contains(touch.location(in: cam)) {
let bullet = SKShapeNode(ellipseOf: CGSize(width: 5, height: 4))
bullet.fillColor = .orange
bullet.physicsBody = SKPhysicsBody(edgeLoopFrom: bullet.path!)
bullet.physicsBody?.affectedByGravity = true
bullet.physicsBody?.categoryBitMask = Physics().bullet
bullet.physicsBody?.collisionBitMask = Physics().enemy | Physics().ground
bullet.physicsBody?.contactTestBitMask = Physics().bullet | Physics().enemy | Physics().ground
bullet.position.y = charakter.position.y + charakter.size.height / 7
bullet.physicsBody?.isDynamic = true
bullet.name = "bullet"
if facing == "right" {
bullet.position.x = charakter.position.x + charakter.size.width / 1.9
self.world.addChild(bullet)
bullet.run(SKAction.moveBy(x: 2000, y: 0, duration: 4))
} else if facing == "left" {
bullet.position.x = charakter.position.x - charakter.size.width / 1.9
self.world.addChild(bullet)
bullet.run(SKAction.moveBy(x: -2000, y: 0, duration: 4))
}
}
The bullet collides with enemies, the enemies collides with the player and the player collides with the ground - everything works, except the collision between bullet and ground.
Thank you for your help in advance
Pascal

Rotate object under gravity force

I'm trying to create a scenario where there's a radial gravity field. In this scene, there's also an object built by two physics bodies with a different mass.
When I run this code, the radial gravity field is created correctly and the body goes to gravityCenter.
I'm expecting that the body rotates too because the head is heavier than the tail but this doesn't happend.
Why?
class GameScene: SKScene {
let object = SKSpriteNode(imageNamed: "myobj")
let myCategory : UInt32 = 0x1 << 0
override func didMove(to view: SKView) {
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
let gravityCenter = SKFieldNode.radialGravityField()
gravityCenter.isEnabled = true
gravityCenter.position = CGPoint(x: size.width, y: size.height * 0.5)
gravityCenter.strength = 0.5
addChild(gravityCenter)
object.position = CGPoint(x: size.width * 0.1, y: size.height * 0.9)
object.scale(to: CGSize(width: 100, height: 25))
let head = SKPhysicsBody(circleOfRadius: object.size.width/5, center: CGPoint(x: object.size.width/2, y: 0))
let tail = SKPhysicsBody(circleOfRadius: object.size.width/50, center: CGPoint(x: -object.size.width/2, y: 0))
head.mass = 500
head.categoryBitMask = myCategory
head.allowsRotation = true
head.isDynamic = true
head.angularDamping = 0
head.affectedByGravity = true
tail.mass = 2
tail.categoryBitMask = myCategory
tail.allowsRotation = true
tail.isDynamic = true
tail.angularDamping = 0
tail.affectedByGravity = true
object.physicsBody = SKPhysicsBody(bodies: [head, tail])
object.physicsBody?.categoryBitMask = myCategory
object.physicsBody?.allowsRotation = true
object.physicsBody?.isDynamic = true
object.physicsBody?.angularDamping = 0
object.physicsBody?.affectedByGravity = true
addChild(object)
}
}
Well, from a physics standpoint SpriteKit is behaving correctly. If you think about it, more mass does mean more gravitational force, but it also means more inertia, which exactly cancels out the increased force. Perhaps introduce a little bit of linearDamping into the tail? That would get the body to rotate by making the head drag the tail a little bit.

Why doesnt my top and bottom physics body resize for the iPad?

I have a physicsBody for the bottom of my screen and for the top. It fits perfectly for my iPhone but when i go to the iPad simulator its a couple inches away from the top of the screen and bottom of the screen. It doesnt fit on the edge of the screens for the iPad for some reason. Can someone help me with this? Thanks! Heres the code im using:
let wall1 = SKSpriteNode(color: SKColor.clearColor(), size: CGSize(width: 2000, height: 5))
let wall2 = SKSpriteNode(color: SKColor.clearColor(), size: CGSize(width: 2000, height: 5))
func wall() {
//top wall border
wall1.position = CGPointMake(self.frame.width / 2, self.size.height / 1.1)
wall1.physicsBody = SKPhysicsBody(rectangleOfSize: wall1.size)
wall1.physicsBody!.dynamic = false
wall1.physicsBody!.categoryBitMask = SideBlockCategory
wall1.physicsBody!.restitution = 0
wall1.physicsBody?.contactTestBitMask = HeroCategory
wall1.physicsBody?.collisionBitMask = 0
wall1.physicsBody?.usesPreciseCollisionDetection = true
//bottom wall border
wall2.position = CGPointMake(self.frame.width / 2, self.size.height / 8.0)
wall2.physicsBody = SKPhysicsBody(rectangleOfSize: wall2.size)
wall2.physicsBody!.dynamic = false
wall2.physicsBody!.categoryBitMask = SideBlockCategory
wall2.physicsBody!.restitution = 0
wall2.physicsBody?.contactTestBitMask = HeroCategory
wall2.physicsBody?.collisionBitMask = 0
wall2.physicsBody?.usesPreciseCollisionDetection = true
}
Try this;
//top wall border
wall1.position = CGPointMake(self.frame.width / 2, self.frame.height - 2.5)
//bottom wall border
wall2.position = CGPointMake(self.frame.width / 2, 2.5)

Resources