Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create the effect of a circular object entering and separating from a thick substance

Based on the image below (I used different colours for circle and flat surface so they can be seen, but in the end the colours will be the same), using Swift and Spritekit, I am trying to create the effect of a circular object entering a thick substance (not necessarily sticky) and separating from the thick substance. Basically, when the circular object is separating, it will pull away from the flat surface as it forms into a circle. I wanted to use image animation frames, but since the objects are SKSpriteNodes with physics bodies this will make timing the collision of objects with animation quite difficult. Another approach would be using CAAnimation, but I don't know how this can be combined with SKSpriteNodes with physics bodies. How can I create this separation effect using any of the above stated approaches or a different one?

enter image description here

UPDATE

The image below shows the change in the surface of the thick substance as the circular object enters the thick substance till it's submerged.

enter image description here

like image 305
NSologistic Avatar asked Feb 15 '16 09:02

NSologistic


1 Answers

You are looking for a fluid simulator

This is indeed possible with modern hardware. Let's have a look at what we are going to build here.

enter image description here

Components

In order to achieve that we'll need to

  • create several molecules having a physics body and a blurred image
  • use a Shader to apply a common color to every pixel having alpha > 0

Molecule

Here's the Molecule class

import SpriteKit  class Molecule: SKSpriteNode {      init() {         let texture = SKTexture(imageNamed: "molecule")         super.init(texture: texture, color: .clear, size: texture.size())          let physicsBody = SKPhysicsBody(circleOfRadius: 8)         physicsBody.restitution = 0.2         physicsBody.affectedByGravity = true         physicsBody.friction = 0         physicsBody.linearDamping = 0.01         physicsBody.angularDamping = 0.01         physicsBody.density = 0.13         self.physicsBody = physicsBody      }      required init?(coder aDecoder: NSCoder) {         fatalError("init(coder:) has not been implemented")     } } 

Shader

Next we need a Fragment Shader, let's create a file with name Water.fsh

void main() {      vec4 current_color = texture2D(u_texture, v_tex_coord);      if (current_color.a > 0) {         current_color.r = 0.0;         current_color.g = 0.57;         current_color.b = 0.95;         current_color.a = 1.0;     } else {         current_color.a = 0.0;     }      gl_FragColor = current_color; } 

Scene

And finally we can define the scene

import SpriteKit  class GameScene: SKScene {      lazy var label: SKLabelNode = {         return childNode(withName: "label") as! SKLabelNode     }()      let effectNode = SKEffectNode()      override func didMove(to view: SKView) {         physicsBody = SKPhysicsBody(edgeLoopFrom: frame)         effectNode.shouldEnableEffects = true         effectNode.shader = SKShader(fileNamed: "Water")         addChild(effectNode)     }      var touchLocation: CGPoint?      override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {         guard let touch = touches.first else { return }         let touchLocation = touch.location(in: self)         if label.contains(touchLocation) {             addRedCircle(location: touchLocation)         } else {             self.touchLocation = touchLocation         }     }      override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {         touchLocation = nil     }       override func update(_ currentTime: TimeInterval) {         if let touchLocation = touchLocation {             let randomizeX = CGFloat(arc4random_uniform(20)) - 10             let randomizedLocation = CGPoint(x: touchLocation.x + randomizeX, y: touchLocation.y)             addMolecule(location: randomizedLocation)         }     }      private func addMolecule(location: CGPoint) {         let molecule = Molecule()         molecule.position = location         effectNode.addChild(molecule)     }      private func addRedCircle(location: CGPoint) {         let texture = SKTexture(imageNamed: "circle")         let sprite = SKSpriteNode(texture: texture)         let physicsBody = SKPhysicsBody(circleOfRadius: texture.size().width / 2)         physicsBody.restitution = 0.2         physicsBody.affectedByGravity = true         physicsBody.friction = 0.1         physicsBody.linearDamping = 0.1         physicsBody.angularDamping = 0.1         physicsBody.density = 1         sprite.physicsBody = physicsBody         sprite.position = location         addChild(sprite)     }  } 

The full project is available on my GitHub account https://github.com/lucaangeletti/SpriteKitAqua

like image 86
Luca Angeletti Avatar answered Oct 12 '22 09:10

Luca Angeletti