create a bubbly relaxing interactive fluid to play with on swiftui in swift in swift

To create a bubbly relaxing interactive fluid in SwiftUI, we can use fluid dynamics and a particle system. Here are the steps to create the fluid:

  1. Create a Particle struct to hold the particle's position, velocity, and acceleration.
main.swift
struct Particle {
    var x: CGFloat
    var y: CGFloat
    var vx: CGFloat
    var vy: CGFloat
    var ax: CGFloat
    var ay: CGFloat
}
138 chars
9 lines
  1. Create a Fluid struct to hold the properties of the fluid, including the particles.
main.swift
struct Fluid {
    var particles: [Particle]
    var viscosity: CGFloat
    var drag: CGFloat
    var gravity: CGFloat
}
121 chars
7 lines
  1. Initialize the particles with random positions, velocities, and accelerations.

  2. Update the position, velocity, and acceleration of each particle based on the fluid's properties and any user input.

main.swift
func updateParticles(_ fluid: inout Fluid, _ touchLocation: CGPoint?) {
    for i in 0..<fluid.particles.count {
        let p = fluid.particles[i]
        
        // Calculate forces
        var fx = -fluid.viscosity * p.vx
        var fy = -fluid.viscosity * p.vy + fluid.gravity
        
        if let touch = touchLocation {
            // Apply attraction force towards the user's touch location
            let dx = touch.x - p.x
            let dy = touch.y - p.y
            let distanceSq = dx*dx + dy*dy
            let distance = sqrt(distanceSq)
            let strength = min(200 / distanceSq, 2)
            fx += strength * dx / distance
            fy += strength * dy / distance
        }
        
        // Update velocity
        let ax = (fx + fluid.drag * -p.vx) / 1.2
        let ay = (fy + fluid.drag * -p.vy) / 1.2
        let vx = p.vx + ax
        let vy = p.vy + ay
        
        // Update position
        let x = p.x + vx
        let y = p.y + vy
        
        fluid.particles[i] = Particle(x: x, y: y, vx: vx, vy: vy, ax: ax, ay: ay)
    }
}
1081 chars
33 lines
  1. Render the particles using SwiftUI's Path and Circle shapes.
main.swift
struct ContentView: View {
    @State var fluid = createFluid()
    @State var touchLocation: CGPoint?
    
    var body: some View {
        GeometryReader { geometry in
            Path { path in
                for p in fluid.particles {
                    path.addPath(Circle(center: CGPoint(x: p.x, y: p.y), radius: 10))
                }
            }
            .fill(Color.blue.opacity(0.5))
            .gesture(
                DragGesture()
                    .onChanged { value in
                        touchLocation = value.location
                    }
                    .onEnded { _ in
                        touchLocation = nil
                    }
            )
            .onAppear {
                let timer = Timer.scheduledTimer(withTimeInterval: 1/60, repeats: true) { timer in
                    updateParticles(&fluid, touchLocation)
                }
                RunLoop.current.add(timer, forMode: .common)
            }
        }
    }
}
982 chars
31 lines

This will create a fluid that can be interacted with using touch input, with particles that move and react to external forces like gravity and viscosity.

gistlibby LogSnag