はじめに
※ 以下はgeminiで作成した内容になります。自らのメモのように書いております。
作品;https://openprocessing.org/sketch/2684456
皆さんは「ジェネラティブ・アート」や「モーショングラフィックス」に興味はありますか? 本記事では、p5.jsというJavaScriptライブラリとAIの力を借りて、毎回異なる表情を見せる「飽きさせない」抽象的なモーショングラフィックスをどのように構築していくかを解説します。
単にランダムな動きを作るだけでなく、「秩序(グリッドや規則的な動き)」と「カオス(ランダムな選択や速度)」のバランスを意識することで、より魅力的で奥深い表現を目指します。AIとの対話を通じて、複雑な概念を段階的に実装していくプロセスを、具体的なプロンプトと共に紹介します。
このプロンプト群で何が作れるのか?
この一連のプロンプトをAIに与えることで、以下のような特徴を持つジェネラティブ・モーショングラフィックスを構築できます。
- 動的に変化するグリッド: 画面上に配置された円形のオブジェクトが、列数・行数・全体スケールがランダムに変化するグリッドを形成します。
- BPMに同期したシーンチェンジ: 音楽のテンポ(BPM)に合わせて、一定の拍数ごとに画面の色、グリッドの構成、アニメーションパターンが切り替わります。
- 多様な円の出現アニメーション: 円がグリッド上に一度に現れるのではなく、ランダムな順序、左から右へ、あるいは中心から外側へといった、様々なアニメーションパターンで順番に出現します。
- 個別かつ秩序だったオブジェクトの動き: グリッド内の各円が、独立して、または同期して、回転、グリッド内での移動、拡大縮小といったアニメーションを実行します。これらの動きは、完全にランダムではなく、サイン波のような「イージング」を伴う滑らかな周期運動が中心となり、グリッドの秩序を保ちつつ変化します。
- 秩序とカオスのバランス: アニメーションパターンや各パラメータの値はランダムに選ばれますが、例えば「静止」や「規則的な動き」といった秩序だったパターンが一定の確率で選ばれやすく設定されています。これにより、常に動き回るカオスな状態だけでなく、穏やかで美しい瞬間も生まれ、視覚的なメリハリが生まれます。
このプロセスを通じて、コードはモジュール化されたクリーンな構造となり、各機能が抽象的な概念(パターン)として扱われるため、将来的な拡張や改変が容易になります。
開発ロードマップ:AIと創る4つのステップ
それでは、実際にAIに与えるプロンプトと、各ステップで目指す内容を見ていきましょう。
ステップ 1: 基本構造の構築とグリッドの静的描画
目的: p5.jsの基本設定を行い、CircleクラスとGridManagerクラスの骨組みを構築して、固定されたグリッドに静止した円を描画できるようにします。
AIへの指示のポイント:
-
CircleクラスとGridManagerクラスの明確な役割分担。 - グリッド状の円の初期配置。
- メインスケッチとの接続。
AIに渡すプロンプト:
p5.jsで、キャンバスサイズ800x800、`angleMode`は`DEGREES`に設定した基本スケッチを作成してください。
次に、以下の2つのクラスを実装してください:
1. **`Circle`クラス**: コンストラクタで`x, y`座標、`r`(半径)、`fillColor`、そしてグリッド位置を示す`col, row`を受け取ります。`display()`メソッドで円を画面に描画します。
2. **`GridManager`クラス**: コンストラクタで`cols`(列数)、`rows`(行数)を受け取ります。このクラス内に`Circle`オブジェクトの配列を保持し、グリッド状に円を初期化して格納する`initCircles()`メソッドと、それら全ての円を描画する`display()`メソッドを実装してください。
メインの`setup()`関数で`GridManager`をインスタンス化し(例: 8列8行)、`draw()`関数でその`GridManager`の`display()`メソッドを呼び出して、グリッドに円が表示されるように接続してください。背景色は青系のRGB配列(例: `[100, 100, 255]`)、オブジェクト色は赤系のRGB配列(例: `[255, 100, 100]`)を直接指定して描画してください。
ステップ 2: シーンの動的初期化と時間同期
目的: シーン全体の背景色・オブジェクト色、グリッドのサイズ、全体スケールがランダムに変化し、それがBPMに同期して切り替わるようにします。
AIへの指示のポイント:
-
initializeScene()関数で、ランダムな設定値を生成・適用。 - BPMからの時間間隔計算。
-
draw()ループ内での定期的なシーン切り替え。 - P5.jsのカラー処理におけるエラー回避 (
color()関数の利用)。
AIに渡すプロンプト:
ステップ1のコードに以下の機能を追加してください。
1. シーン全体の初期化とリセットを行う`initializeScene()`関数を作成してください。この関数内で、事前に定義された`colorPalette`配列から**ランダムに異なる2色**を選び、それぞれを`backgroundColor`と`objectColor`として設定してください。
2. `initializeScene()`内で、グリッドの`cols`と`rows`を**ランダムな範囲(例: 3〜9)で決定**し、`GridManager`に渡すようにしてください。
3. シーン全体の`initialScale`(表示スケール)を**ランダムな範囲(例: 0.5〜1.5)で決定**し、`GridManager`が`draw()`内で`scale()`として適用できるようにしてください。
4. BPM(`bpm = 120`)と`beatsPerChange`(例: `4`)に基づいて、シーンが切り替わるミリ秒間隔`changeInterval`を計算してください。
5. `draw()`関数内で、`changeInterval`に基づいて**一定時間ごとに`initializeScene()`が呼び出される**ように実装してください。
6. `background()`と`fill()`にRGB配列のカラー変数を渡す際に、P5.jsの`color()`関数でラップして渡すように修正し、カラーエラーが発生しないようにしてください。
ステップ 3: 円の出現アニメーションとパターン選択
目的: グリッド上の円が一度に現れるのではなく、順番にアニメーションして現れるようにし、その出現方法を多様なパターンからランダムに選択できるようにします。
AIへの指示のポイント:
-
GridManagerでの円の表示数管理。 -
sortCirclesForAppearance()メソッドによる出現順序のソート。 -
APPEARANCE_PATTERNSによる抽象化。 - 配列シャッフルヘルパー関数の利用と命名規則。
AIに渡すプロンプト:
ステップ2のコードに以下の機能を追加してください。
1. `GridManager`に、`maxCircles`(表示する円の最大数)と`circlesDisplayed`(現在表示されている円の数)プロパティを追加してください。`GridManager`の`display()`メソッドは、`circlesDisplayed`の数だけ円を描画し、`appearanceSpeed`(例: 60ms)で徐々に`circlesDisplayed`を増やしていくロジックを実装してください。
2. 円の出現順序を決定する`sortCirclesForAppearance()`メソッドを`GridManager`に実装してください。このメソッドは、以下の**`APPEARANCE_PATTERNS`**定数で定義されたパターン名を受け取り、`Circle`オブジェクトの配列をソートできるようにしてください。
* `RANDOM` (ランダムな順序)
* `LEFT_TO_RIGHT_TOP_TO_BOTTOM` (左上から右下へ順序)
* `CENTER_OUT` (中心から外側へ順序)
3. `initializeScene()`関数で、`APPEARANCE_PATTERNS`から**ランダムに1つのパターンを選択**し、`GridManager`に渡すようにしてください。`maxCircles`は、約40%の確率でグリッドの総数の一部(例: 5〜80%)に、60%の確率で全てになるようにランダムに決定してください。
4. 配列の要素をシャッフルするためのグローバルなヘルパー関数`arrayShuffle(array)`を実装し、P5.jsの既存関数と名前が衝突しないようにしてください。この関数を適切な場所で使用してください。
ステップ 4: オブジェクトの動的アニメーション(回転、動き、拡大)
目的: 各円が独自の回転、グリッド内での動き、拡大縮小のアニメーションを付与し、これらのアニメーションパターンもランダムに選択できるようにすることで、秩序とカオスを両立させます。
AIへの指示のポイント:
-
ROTATION_PATTERNS,MOVEMENT_PATTERNS,SCALING_PATTERNSによるパターン定義。 -
Circleクラスのupdate()メソッドでの時間(frameCount)と数学関数を用いたアニメーション計算。 - 各パターンにおけるランダムな初期パラメータの設定(振幅、速度など)。
- 出現フェーズ中の特定アニメーションの抑制。
- パターン選択ロジックでの「静的/秩序的」なパターンの出現確率調整。
AIに渡すプロンプト:
ステップ3のコードに以下の機能を追加してください。
1. 以下の新しいアニメーションパターン定数を定義してください。
* **`ROTATION_PATTERNS`**: `NO_ROTATION`, `CONSTANT_SPEED_ONE_DIRECTION`, `RANDOM_DIRECTION_RANDOM_SPEED`, `PULSATING_ROTATION`
* **`MOVEMENT_PATTERNS`**: `NO_MOVEMENT`, `LINEAR_OSCILLATION_HORIZONTAL`, `CIRCULAR_MOTION`, `ROW_WAVE_MOVEMENT`
* **`SCALING_PATTERNS`**: `FIXED_SIZE`, `SYNCHRONIZED_PULSATE`, `RANDOM_PULSATE`, `GRID_DEPENDENT_GRADIENT`
2. `Circle`クラスに`update(rotationPattern, movementPattern, scalingPattern, isAppearancePhase)`メソッドを追加してください。このメソッド内で、渡されたパターンと`frameCount`を使用して、円の`currentRotation`, `currentX`, `currentY`, `currentR`を計算するようにしてください。
* `Circle`のコンストラクタで、各アニメーションパターンに必要な**ランダムな初期パラメータ**(例: `rotationSpeed`, `oscillationAmplitude`, `pulsateAmplitude`など)を初期化してください。これらのパラメータは、動きがグリッドセル内に収まるように、また秩序とランダム性のメリハリがつくように調整された範囲(例: 振幅は小さめに)で設定してください。
* **`isAppearancePhase`が`true`の場合、拡大アニメーションを適用しない**ように`update()`メソッドを修正してください。
* `Circle`の`display()`メソッドで`push()`, `translate()`, `rotate()`, `pop()`を使用して、各円が自身の中心を基準にアニメーションするようにしてください。
3. `initializeScene()`関数で、これら3つのアニメーションパターンから**ランダムに1つずつ選択**し、`GridManager`に渡すようにしてください。
4. `initializeScene()`内のパターン選択ロジックを修正し、各アニメーションタイプにおいて**「静止」や「規則的な」パターン(上記の定数リストの最初の項目)が約30%の確率で選ばれる**ように調整してください。
おわりに
このロードマップとプロンプト群を活用することで、あなたはAIと共に、複雑なジェネラティブ・モーショングラフィックスを段階的かつ効率的に構築することができます。各ステップでAIからのコードを受け取り、それを統合していくことで、コードが長くなりすぎずに、非常に多様で「飽きさせない」視覚表現が実現できるでしょう。ぜひ、このプロセスを楽しんで、あなただけのクリエイティブな作品を生み出してください!