Swift - Sprite Kit floating bubbles stuck to corners

Viewed 319

I'm trying to create a floating bubble view on my Watch App. The bubbles can collide & bounce off each other & the sides of the screen. But for some reason the bubbles are appearing out of the view bounds & getting stuck on the sides of the frame instead of bouncing off. This code works as expect on my iOS application but when using the same code in my Watch app, it doesn't.

It doesn't make much sense to me that this exact code works perfectly on my iOS app but not on the Watch App.

I'm passing the below code into a SpriteView in my SwiftUI View

let ballCategory: UInt32 = 0xb0001
let edgeCategory: UInt32 = 0xb0010
var nodeCount = 0

override func sceneDidLoad() {
    //set physicsWorld properties
    physicsWorld.contactDelegate = self
    physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)

    //set edges as PhysicsBody
    let edge = SKPhysicsBody(edgeLoopFrom: self.frame)
    edge.friction = 0
    edge.categoryBitMask = edgeCategory
    self.physicsBody = edge

    makebubble()
    makebubble()
    makebubble()
    makebubble()
}

func makebubble() {

    let bubbleTexture = SKTexture(imageNamed: "bubble")
    let bubble = SKSpriteNode(texture: bubbleTexture)
    let bphysicsBody = SKPhysicsBody(circleOfRadius: bubbleTexture.size().height/2)

    bphysicsBody.isDynamic = true
    bphysicsBody.usesPreciseCollisionDetection = true
    bphysicsBody.restitution = 0.5
    bphysicsBody.friction = 0
    bphysicsBody.angularDamping = 0
    bphysicsBody.linearDamping = 0
    bphysicsBody.categoryBitMask = ballCategory
    bphysicsBody.collisionBitMask = ballCategory | edgeCategory
    bphysicsBody.contactTestBitMask = ballCategory | edgeCategory
    bubble.physicsBody = bphysicsBody
    bubble.name = "bubble"

    // Get a random possition within the width of the scene
    let x = CGFloat(randomize(number: Int(size.width - 40)))
    let y = CGFloat(randomize(number: Int(size.height - 40)))

    // position the bubble
    bubble.position.x = x
    bubble.position.y = y

    // Add the bubble
    addMyChild(node: bubble)
}

func addMyChild(node:SKSpriteNode){
    self.addChild(node)
    node.physicsBody!.applyImpulse(CGVector(dx: 10.0, dy: -2.0))
    nodeCount += 1
}

// function that returns a random int from 0 to n-1
func randomize(number: Int) -> Int{
    return Int(arc4random()) % number
}

bubbleswatch bubbles

1 Answers

This has nothing to to with watchOS and everything to do with the small screen size of Apple Watches. Try running your code on iOS with a frame modifier of width 150 and height 150 and you'll see what I mean; the bubbles will likely stick to the side.

Your bubbles look like they stick to the edges because they slow down over time (due to restitution being 0.5 instead of 1) and it's statistically more probable for a bubble to have its final movement close to the screen edge (since they will eventually move to the edge, bounce off from it, thus slowing down and eventually halting).

Here are 3 things you can do about this:

  • as mentioned, increase restitution to 1 (this is optional, as it won't solve the "sticking to the edge" problem on its own, but it helps making the slowing down issue better)
  • detect when the bubbles stop (you can do this by checking the x and y velocity in the update(_:) function of your SKScene) and make a force that moves them slightly in a random direction. If you are in a fancy mood, you can even make a timer to make random, barely noticable forces that act like small air movements (chances are, it will even make the animation a bit more realistic)
  • create an outside bounding box with slightly non-linear/circular borders and corners to make the bubbles bounce off the walls in a different way
Related