Create a GameScene Xcode Project and download the emoji files I have or you can use your own image for your nodes.
Import CoreMotion and create a CMMotionManager
property. This will allow us to use the accelerometer to create the physics effect.
Also create an array of [SKSpriteNote]
which will allow us to hold current nodes in our screen for later use.
Setup your physics world in your SKScene.
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
Then after that, start the accelerometer updates
motionManager.startAccelerometerUpdates()
Create a function that will be used within the touchesMoved(:_)
method
func createNode(at position: CGPoint) {
// This is for the emoji names.
// You may not need it if you are using
// a single image
let i = Int.random(in: 1...85)
// create the node
let node = SKSpriteNode(imageNamed: "emoji\(i)")
node.size = CGSize(width: 50, height: 50)
node.position = position
// add the physics body
node.physicsBody = SKPhysicsBody(circleOfRadius: node.size.width / 2)
node.physicsBody?.restitution = 0.5
node.physicsBody?.friction = 0.2
node.physicsBody?.allowsRotation = true
node.physicsBody?.isDynamic = true
scene?.addChild(node)
// add the newly created node to our nodes array.
nodes.append(node)
}
Then call this method in your touches moved by passing in the location of the touch.
We can create our clearScene()
method because, why not :)
func clearScene() {
for node in nodes {
// create the scaling affect
let scale = SKAction.scale(by: 0, duration: 1.25)
// remove the node from the parent
let remove = SKAction.run {
node.removeFromParent()
}
// create the rotation affect
let rotationAngle: CGFloat = 2 * CGFloat.pi
let rotate = SKAction.repeatForever(SKAction.rotate(byAngle: rotationAngle, duration: 0.35))
// create a sequence where we run the scaling and removing affect
let sequence = SKAction.sequence([scale, SKAction.wait(forDuration: 0.25), remove])
// rotate the nodes and run it with the scaling and removing affect/
node.run(rotate)
node.run(sequence)
}
// then remove all references of the nodes
nodes.removeAll()
}
To create the physics affect, we want to use our motionManager
to access the accelerometer data and use that to change the physics world gravity.
We do this inside our update(_:)
method
guard let acc = motionManager.accelerometerData?.acceleration else { return }
let harshness: Double = 75
physicsWorld.gravity = CGVector(dx: acc.x * harshness, dy: acc.y * harshness)
To call the clearScene()
method, I did this inside the GameViewController
class since the motion
method for some reason does not trigger inside the scene
override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
guard motion == .motionShake else { return }
guard let skView = view as? SKView else { return }
guard let scene = skView.scene as? GameScene else { return }
scene.clearScene()
}
That's it, enjoy!