はじめに
前回の記事)では、カウントダウンタイマーに物理演算を用いたスノードーム風の演出を実装しました。
今回は、その「Project Countdown」シリーズの第2弾として、「水面反射とオーロラ」をテーマにしたAqua Timerを制作しました。単に時間を測るだけでなく、デスクトップに静かな没入感を与える「動くインテリア」としてのタイマーを目指しています。
成果物
動画の10秒ぐらいでモードが切り替わります。
通常時はミニマルなデジタルタイマーですが、Sキーを押すと「水面モード」に切り替わります。
- 水面反射: タイマーの文字が水面に映り込み、波紋に合わせてリアルタイムに揺らぎます。
- オーロラグロー: 水平線付近に幻想的な光がゆらめき、時間とともに色彩が変化します。
- インタラクティブな波紋: 水面をクリックすると波紋が広がり、反射した文字が物理的に歪みます。
技術的なポイント
1. サイン波による「水面のゆらぎ」シミュレーション
水面の反射を表現するために、タイマー画像を1ピクセル(1行)ごとにスキャンし、サイン波を用いて水平方向にオフセットをかけています。
手前に行くほど揺れ幅を大きく、周期を遅く設定することで、奥行きのある液体感を演出しました。
# ゆらぎの計算例
wave_amp = 3 + 20 * p_factor # 手前ほど大きく揺れる
wave_freq = 0.2 - 0.1 * p_factor
offset = math.sin(ticks * 0.006 + i * wave_freq) * wave_amp
2. 波紋(Ripple)と反射の干渉
単なる画像の揺らしではなく、マウスクリックで発生した波紋の座標と、反射描画の座標を比較。波紋の伝播に合わせて一時的にオフセットを増幅させることで、「水面を叩いたから文字が歪む」という直感的なフィードバックを実装しました。
3. 高DPI(4Kモニタ等)への対応
デスクトップツールとして「ボケ」を許容したくなかったため、Windows API (ctypes) を用いてプロセスにDPI認識をさせています。
try:
ctypes.windll.shcore.SetProcessDpiAwareness(1) # Process_System_DPI_Aware
except Exception:
pass
主要機能と操作方法
| キー | 動作 |
|---|---|
| S | Mode Switch: 通常モード ↔ 水面モード |
| Space | Theme Change: ミント、赤、青、黄色、緑に切り替え |
| Mouse Click | Water Ripple: 水面に波紋を起こす(水面モード時) |
| Esc | Quit: アプリケーションの終了 |
実装詳細(リバースプロンプト用構成)
A. 描画エンジン
- Pygame: 2Dレンダリングおよびパーティクル制御。
-
7セグメントカスタム描画: フォントファイルを使わず、
pygame.draw.polygonでセグメントを構築。非点灯部分を薄く描画することで実機感を演出。
B. ビジュアル演出
- オーロラ: 複数のサイン波を合成して垂直方向のラインを動的に描画。
- JST/UTC同時表示: エンジニアリング用途を想定し、日本標準時と世界標準時を常時表示。
- 3Dドットグリッド: 奥行きを感じさせる静かな背景。
おわりに
今回は「水」という、スノードーム(雪)とはまた違った物理表現に挑戦しました。
Pygameはゲームだけでなく、こうした「デスクトップを少し豊かにするツール」を作るのにも非常に強力なライブラリだと改めて感じます。
もしソースコードの詳細や、自分のデスクトップにも浮かべてみたいという方がいれば、GitHub等での公開も検討します。コメントをいただけると励みになります!
