IRO UTSUSHI
一款不會要你替心情命名的應用程式。把顏色滴進水面、用手指攪動,當下的手勢就這樣留成一張畫。
已在 App Store 上架可以做什麼
- 滴下顏色,用手指攪動 … 從六色調色盤中最多選五色滴進水面,用手指攪成一張畫。「沉靜色」與「鮮豔色」兩組調色盤,在滴下顏色之後仍可切換。
- 不用文字分類 … 沒有讓你挑選心情的選項,也沒有事後補上的標籤。留下的只有顏色與手指動作的痕跡。
- 單次記錄最長 60 秒 … 快結束時以波紋、光暈與聲音提醒,不會用震動催促你。
- 把動作化為四項指標 … 速度(瞬時速度的中位數)、廣度(與重心的平均距離)、變化(轉向的頻率與速度的離散程度)與緩急。結果畫面預設隱藏這些數字:一款不做分類的應用程式,不該先端出分數。
- 事後重播 … 依據儲存的觸控序列重建水面並播放,支援 1×/2× 與前後拖曳。也可以把手指的軌跡與點按的位置疊在水面上顯示。
- 輸出與分享 … 可輸出含聲音的 30 fps MP4 與 PNG。記錄可上下滑動翻閱,也能一次刪除多筆。
- 聲音在應用程式內合成 … 點按的位置化為五聲音階中的一個音,動作的快慢化為音量與泛音的明亮度。音色有五種:柔和鍵盤、拇指琴、豎琴、弦樂鋪底與玻璃琴。
- 無障礙與十種語言 … 以弱視使用者為主要設想,支援動態字級、旁白(VoiceOver)、「提高對比」、「降低透明度」與「減少動態效果」。提供日文、英文、西班牙文、法文、韓文、繁體中文、葡萄牙文(巴西)、德文、義大利文與越南文。
怎麼做的
| 應用程式 | Swift + SwiftUI,以 Swift Playgrounds 的 App Package 撰寫,完全不依賴外部套件。 |
|---|---|
| 水面 | 以 Metal 撰寫的流體模擬。速度場、壓力投影、對流、渦度強化與顏料混合全部交由 GPU 處理。 |
| 顏料 | 以拉格朗日粒子保存,依 Beer–Lambert 定律做減法混色。因為是粒子,經過一段時間也不會因擴散而糊掉。 |
| 外觀 | 由水面高度場解析求得法線,據以繪製折射與高光,再疊上顆粒雜訊,以及用來避免色帶的抖色處理。 |
| 輸入 | 取自 UIKit 的原始事件,把同一影格內的 coalesced touches 全數交給流體。最多五指同時觸控,會以每根手指各自獨立的筆觸來記錄、播放與計算。 |
| 記錄的儲存 | 清單用的 JSON 只放輕量資訊,影像是一張 PNG,觸控序列則以固定寬度的二進位資料經 LZFSE 壓縮,各自存放在每筆記錄專屬的目錄中。 |
| 播放與輸出 | 依儲存的 step 重新跑一次模擬來重建水面。MP4 並非螢幕錄影,而是從那些 step 重新合成影格後以 30 fps 寫出。 |
| 聲音 | 音效在應用程式內合成,五聲音階、最多 16 個聲部同時發聲,不放任何音檔。 |
| 自我檢查 | 由於環境無法使用 XCTest,改以自行撰寫、在除錯啟動時執行的檢查(SelfChecks.swift)來代替。 |
| 加密 | 完全未使用(並隨附 export compliance 的回覆)。 |
技術上有意思的地方
手指走過之後,尾流仍在捲動
對流加上了 MacCormack 修正,單純的半拉格朗日對流會抹掉的細小渦漩,因此得以留存。 手指不是「推」水,而是沿著拖曳方向落下一對反向旋轉的渦,所以手指離開後,水仍會繼續捲上一陣子。 衰減與跟隨的係數一律以「每秒」表示,因此在 60 Hz 與 120 Hz 的裝置上動態一致。
把「看得見的波」和「會推東西的波」分開
波紋的可見強度與它對顏料的作用是兩個不同的參數。而且波紋直接改變顏料的位置,而不是速度。 顏料的速度每一影格都會被拉回水流的速度,在濃處的時間常數約為 0.36 秒,而波紋的壽命比這更短, 實測顯示:以加速度的寫法,波紋幾乎推不動顏料。如此一來,調整外觀與調整手感就不會互相破壞。
刻意不讓顏料互相吸引
過去曾加入讓顏料聚攏的「凝聚」力,但它唯一的安定狀態只有圓形團塊;時間一久,水面就被不透明的圓填滿,再也化不開。 現在改以不移動任何顏料的方式重現水彩的邊緣沉積:濃度場維持原樣,只是從中取出邊緣,當作水面路徑上的陰影來繪製,因此畫面不會就此凝固。
同一筆記錄,重播多少次都是同一張畫
模擬固定為每秒 60 個 step,並將消耗 UIKit 輸入的實際 step 編號、前導(lead-in)step 數,以及 Float32 時刻搭配 UInt16 座標的附屬檔一併保存。
播放時以這些儲存的 step 為準,而非系統時鐘的時間戳。速度則以 UITouch.timestamp 為基準(同一影格內的動作,用系統時鐘無法區分)。
預測觸控只用於估計速度,不會影響顏料落下的位置。
在此之上,SimulationEngineRegistry 會把記錄中的 simulationVersion 明確導向對應的引擎。
version 6 連常數、時鐘與墨水傳遞率都已凍結,且不會把未知的未來 version 悄悄交給最新的模擬處理。
為的是讓舊記錄的畫面,不會因為應用程式更新而被重建成另一張畫。
不把分數擺在最前面
四項指標不以上限截斷,而是放在漸近於 100 的曲線上,快速動一次並不會拿到滿分。 即便如此,結果畫面仍預設隱藏它們。一款不用文字為情緒分類的應用程式,若先端出數字, 那些數字終究會變成新的標籤。
隱私權與聯絡方式
IRO UTSUSHI 只把記錄保存在你的裝置中,沒有帳號註冊、沒有廣告、沒有流量分析,也沒有追蹤使用者的功能。 詳情請見 IRO UTSUSHI 隱私權政策。
意見與問題回報,也可以透過 Sizu dev 的聯絡頁面與我們聯繫。