Javaの「パッケージ ➔ クラス ➔ メソッド ➔ 変数」という入れ子関係を、Processingのクリックアニメーションで直感的に体感する。
どうも上達の研究家のワタタクです。
前回の記事(Javaの正体は「マトリョーシカ構造の本」?パッケージ・クラス・メソッドの入れ子関係を徹底図解!)では、何万行もある難解な長文コードの正体が、実は綺麗に包み込まれた「マトリョーシカ構造」であることを解説しました。
今回はLinked Logカテゴリーとして、「画面をクリックするたびに、人形がパカパカと開いていって最深部のデータに辿り着くオブジェクト指向の世界」をProcessingのコードで表現してみました!
文字だけではイメージしにくかった波カッコ { } の上下関係が、一発で脳にマッピングされるコードと設計図を共有します。
この記事を書いた人


上達の研究家 / アーティスト
「才能」ではなく「発見」で描く。文系・36歳からの上達ハック。
- ゼロから独学でクリエイティブコーディングに挑戦し、以下の実績を達成
- 開始1年8ヶ月目までに公募6つに挑戦し、3つ入選(勝率50%)
- KITTE大阪の18メートルあるAxCROSS大型スクリーン
- 虎ノ門ヒルズステーションタワーB2F TOKYO NODE エントランスサイネージで展示
- UN:O(東京大手町)にある会員限定のサテライトオフィスにて2作品常設展示
- 開始1年8ヶ月目までに公募6つに挑戦し、3つ入選(勝率50%)
- 開始1年9ヶ月目に、虎ノ門ヒルズ49階、地上250mのインフィニティプールへ作品提供・展示
- 実際の展示作品と動画、音楽やSEOでの実績はポートフォリオに載せております→https://my-portfolio-blue-three-63.vercel.app/works
脳内をビジュアライズするための設計思想
Javaの入れ子構造をグラフィックに翻訳するため、以下の3つのギミックを仕込みました。
1. クリックで「パカッと開く」インタラクティブ性
ただ静止画で入れ子を描くのではなく、マウスをクリックするたびに「外側の人形が上にスライドして開き、中から次の人形が現れる」という動的なアニメーション(状態管理:step)を設計しました。
2. サイズとネオンカラーによる階層の差別化
- 1番外側(大):パッケージ(青色) ➔ 全体を包むフォルダ
- 2番目(中):クラス(紫色) ➔ プログラムのファイル
- 3番目(小):メソッド(緑色) ➔ 処理の塊のブロック
- 最深部(コア):変数(黄金の粒子) ➔ 最小のデータ
これらを同心円状のサイバーボックスとして重ねることで、視覚的な上下関係を強調しています。
3. Javaの実際の構文(波カッコ)との完全マッピング
人形が開くと同時に、画面下部には対応する実際のJavaコードが表示されるように連動させました。グラフィックの動きとコードの構造が、脳内でカチッと同期する仕組みです。
Processing実装コード(Javaモード)
実行して画面をクリックするたびに、マトリョーシカが次の段階へパカッと開きます。お気に入りの段階で、キーボードの何かキーを押すか、コンソール裏の機能(本コードではクリックと区別するため、キープレスイベントに割り当て)でデスクトップに実行結果を自動保存できます。
// ==========================================
// 知識を視覚化する:Javaの「マトリョーシカ構造(入れ子)」
// (キーボードのキーを押すとデスクトップに自動保存)
// ==========================================
PFont jpFont;
int step = 0; // 0:閉じている, 1:パッケージ開, 2:クラス開, 3:メソッド開(変数出現)
float[] slideY = new float[4]; // 各レイヤーのアニメーション用y座標
void setup() {
size(1200, 650);
for (int i = 0; i < 4; i++) slideY[i] = 0;
}
void draw() {
jpFont = createFont("Meiryo", 24, true);
textFont(jpFont);
background(18, 22, 32); // 深いサイバーナイト背景
// タイトル共通設定
textSize(24);
textAlign(CENTER, TOP);
fill(245);
text("【マトリョーシカ構造(ネスト)の世界】\nクリックして人形をパカッと開け、Javaの階層をのぞき見よう", width / 2, 30);
// イージングアニメーション処理(人形がスムーズに開く演出)
float target1 = (step >= 1) ? -140 : 0;
float target2 = (step >= 2) ? -90 : 0;
float target3 = (step >= 3) ? -50 : 0;
slideY[1] += (target1 - slideY[1]) * 0.2;
slideY[2] += (target2 - slideY[2]) * 0.2;
slideY[3] += (target3 - slideY[3]) * 0.2;
pushMatrix();
translate(width / 2, height / 2 - 20);
// -------------------------------------------------------------
// レイヤー4(最深部コア):変数(int x = 10;)
// -------------------------------------------------------------
if (step >= 3) {
noStroke();
for (int i = 5; i > 0; i--) {
fill(241, 196, 15, 40 - i * 5);
ellipse(0, 40, i * 10, i * 10);
}
fill(255);
ellipse(0, 40, 8, 8);
fill(241, 196, 15);
textSize(12);
textAlign(CENTER, CENTER);
text("最小コア: 変数 x", 0, 65);
}
// -------------------------------------------------------------
// レイヤー3:メソッド(public void move())
// -------------------------------------------------------------
if (step >= 2) {
// 下半分(固定)
stroke(46, 204, 113, 200); // 緑
strokeWeight(2);
noFill();
arc(0, 40, 100, 70, 0, PI);
line(-50, 40, 50, 40);
// 上半分(スライド)
pushMatrix();
translate(0, slideY[3]);
arc(0, 40, 100, 70, PI, TWO_PI);
line(-50, 40, 50, 40);
fill(46, 204, 113);
textSize(11);
textAlign(CENTER, BOTTOM);
text("③メソッド", 0, 35);
popMatrix();
}
// -------------------------------------------------------------
// レイヤー2:クラス(public class Particle)
// -------------------------------------------------------------
if (step >= 1) {
// 下半分(固定)
stroke(155, 89, 182, 180); // 紫
strokeWeight(2.5);
noFill();
arc(0, 30, 220, 160, 0, PI);
line(-110, 30, 110, 30);
// 上半分(スライド)
pushMatrix();
translate(0, slideY[2]);
arc(0, 30, 220, 160, PI, TWO_PI);
line(-110, 30, 110, 30);
fill(155, 89, 182);
textSize(13);
text("②クラス", 0, 20);
popMatrix();
}
// -------------------------------------------------------------
// レイヤー1(一番外側):パッケージ(package net.watataku.art;)
// -------------------------------------------------------------
// 下半分(固定)
stroke(52, 152, 219, 150); // 青
strokeWeight(3);
noFill();
arc(0, 20, 360, 260, 0, PI);
line(-180, 20, 180, 20);
// 上半分(スライド)
pushMatrix();
translate(0, slideY[1]);
arc(0, 20, 360, 260, PI, TWO_PI);
line(-180, 20, 180, 20);
fill(52, 152, 219);
textSize(15);
textAlign(CENTER, BOTTOM);
text("①パッケージ (全体を包む大きな人形)", 0, 5);
popMatrix();
popMatrix();
// -------------------------------------------------------------
// 下部:Javaコードとのリアルタイム連動マッピング表示
// -------------------------------------------------------------
stroke(50, 60, 80);
fill(25, 30, 45);
rect(250, 450, 700, 140, 10);
textAlign(LEFT, TOP);
textSize(14);
// ステップに応じたコードのハイライト演出
if (step == 0) fill(52, 152, 219); else fill(100);
text("package net.watataku.art; // ①一番外側の人形(フォルダの確定)", 280, 470);
if (step == 1) fill(155, 89, 182); else fill(100);
text("public class Particle { // ②二番目の人形(ファイルの開始 { )", 280, 495);
if (step == 2) fill(46, 204, 113); else fill(100);
text(" public void move() { // ③三番目の人形(処理ブロックの開始 { )", 280, 520);
if (step == 3) fill(241, 196, 15); else fill(100);
text(" int x = 10; // ④これ以上分解できない最小のコア(変数)", 280, 545);
fill(100);
text(" }\n}", 280, 520); // 閉じカッコはグレーで固定
// 操作案内
fill(130);
textSize(12);
textAlign(CENTER, BOTTOM);
text("🖱️ 画面をクリック:マトリョーシカをパカッと開く (現在のステップ: " + step + "/3) | ⌨️ キーボードを押す:画像を保存", width / 2, height - 10);
}
// マウスクリックでマトリョーシカを開くイベント
void mousePressed() {
step = (step + 1) % 4; // 0 -> 1 -> 2 -> 3 -> 0 とループ
}
// キープレスでデスクトップに保存
void keyPressed() {
String desktopPath = System.getProperty("user.home") + "/Desktop/";
String timestamp = nf(hour(), 2) + nf(minute(), 2) + nf(second(), 2);
String fileName = "matryoshka_step_" + step + "_" + timestamp + ".png";
save(desktopPath + fileName);
println("デスクトップに保存しました: " + fileName);
}コード表現に落とし込んでみて気づいたこと
難解な専門書の言葉を追うのをやめて、このマトリョーシカをProcessingの「arc()(円弧)の上半分だけスライドさせるコード」に翻訳した瞬間、オブジェクト指向のカプセル化の思想が完全に頭にマッピングされました。
パッケージが開くからクラスが見える。クラスを開くからメソッドが叩ける。そして一番奥深くに、大切な「変数(データ)」が厳重に守られている。
Javaのコードを書くときに打ち込むたくさんの波カッコ { } は、ただの記号ではなく、「ここから次の小さなマトリョーシカ人形が始まるよ!」というパカッと開くための境界線だったんですね。
皆さんもぜひ、画面をクリックしてこのサイバー人形をパカパカ開けて、Javaの構造の美しさを手元で体感してみてください!
それでは今日もレッツワクワクコーディング。
関連記事



