Maybe the surface of the water is like a wire: If you pull on some point of the wire, the points next to that point will be pulled down too. All points are also attracted back to a baseline.

I sketched that idea in Lua using [LÖVE][1] and got this:

![rough blue wave, formed of points, with red baseline][2]

It's a plausible result.

I'm sure I've butchered the physics though: I have no idea what I'm doing beyond initial intuitions and lots of [Hooke's Law][3]!

Anyway, here's my `main.lua`. Feel free to read, copy or use as toilet paper.

    -- Resolution of simulation
    NUM_POINTS = 200
    -- Width of simulation
    WIDTH = 700
    -- Spring constant for forces applied by adjacent points
    SPRING_CONSTANT = 0.1
    -- Sprint constant for force applied to baseline
    SPRING_CONSTANT_BASELINE = 0.1
    -- Vertical draw offset of simulation
    Y_OFFSET = 300
    
    -- Make points to go on the wave
    function makeWavePoints(numPoints)
        local t = {}
        for n = 1,numPoints do
            -- This represents a point on the wave
            local newPoint = {
                x    = n / numPoints * WIDTH,
                y    = Y_OFFSET,
                spd = {y=0}, -- speed with vertical component zero
                mass = 1
            }
            t[n] = newPoint
        end
        return t
    end
    
    wavePoints = makeWavePoints(NUM_POINTS)
    
    -- Update the positions of each wave point
    function updateWavePoints(points, dt)
        for n,p in ipairs(points) do
            -- force to apply to this point
            local force = 0
    
            -- forces caused by the point immediately to the left or the right
            local forceFromLeft, forceFromRight
    
            if n == 1 then -- wrap to left-to-right
                local dy = points[# points].y - p.y
                forceFromLeft = SPRING_CONSTANT * dy
            else -- normally
                local dy = points[n-1].y - p.y
                forceFromLeft = SPRING_CONSTANT * dy
            end
            if n == # points then -- wrap to right-to-left
                local dy = points[1].y - p.y
                forceFromRight = SPRING_CONSTANT * dy
            else -- normally
                local dy = points[n+1].y - p.y
                forceFromRight = SPRING_CONSTANT * dy
            end
    
            -- Also apply force toward the baseline
            local dy = Y_OFFSET - p.y
            forceToBaseline = SPRING_CONSTANT_BASELINE * dy
    
            -- Sum up forces
            force = force + forceFromLeft
            force = force + forceFromRight
            force = force + forceToBaseline
    
            -- Calculate acceleration
            local acceleration = force / p.mass
    
            -- Apply acceleration (with damping)
            p.spd.y = 0.89 * p.spd.y + acceleration
    
            -- Apply speed
            p.y = p.y + p.spd.y
        end
    end
    
    -- Callback when updating
    function love.update(dt)
    
        -- On click: Pick nearest point to mouse position
        if love.mouse.isDown("l") then
            local mouseX, mouseY = love.mouse.getPosition()
            local closestPoint = nil
            local closestDistance = nil
            for _,p in ipairs(wavePoints) do
                local distance = math.abs(mouseX-p.x)
                if closestDistance == nil then
                    closestPoint = p
                    closestDistance = distance
                else
                    if distance <= closestDistance then
                        closestPoint = p
                        closestDistance = distance
                    end
                end
            end
    
            closestPoint.y = love.mouse.getY()
        end
    
        -- Update positions of points
        updateWavePoints(wavePoints, dt)
    end
    
    local circle = love.graphics.circle
    local line   = love.graphics.line
    local color  = love.graphics.setColor
    love.graphics.setBackgroundColor(0xff,0xff,0xff)
    
    -- Callback for drawing
    function love.draw(dt)
    
        -- Draw baseline
        color(0xff,0x33,0x33)
        line(0, Y_OFFSET, WIDTH, Y_OFFSET)
    
        -- Draw points and line
        color(0x00,0x33,0xbb)
        for n,p in ipairs(wavePoints) do
            circle("line", p.x, p.y, 3)
            if n == 1 then
            else
                local leftPoint = wavePoints[n-1]
                line(leftPoint.x, leftPoint.y, p.x, p.y)
            end
        end
    end


  [1]: https://love2d.org/
  [2]: https://i.sstatic.net/EjOuh.png
  [3]: http://en.wikipedia.org/wiki/Hooke%27s_law