2
4

もっともっとダイナミック ジュリア集合 が描かれた空間内を飛び回るゲーム。

Posted at

スクリーンショット 2024-08-25 044719.png

スクリーンショット 2024-08-25 044618.png

image.png

ジュリア集合をプロットし、その点に沿ってカメラが移動するアニメーションのゲームです。

コードをメモ帳などのテキストエディタに貼り付け、ファイルを「index.html」などの拡張子が.htmlのファイルとして保存します。その後、保存したファイルをブラウザで開けば、コードが実行されます。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Julia Set in 3D</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script>
        // シーン、カメラ、レンダラーの設定
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // ジュリア集合のパラメータ
        const cRe = -0.7, cIm = 0.27015;
        const maxIterations = 300;
        const points = [];  // 点の配列
        const colors = [];  // カラフルな色の配列

        // ジュリア集合の点を生成
        for (let x = -1.5; x <= 1.5; x += 0.01) {
            for (let y = -1.5; y <= 1.5; y += 0.01) {
                let zx = x;
                let zy = y;
                let i = 0;

                while (zx * zx + zy * zy < 4 && i < maxIterations) {
                    let tmp = zx * zx - zy * zy + cRe;
                    zy = 2.0 * zx * zy + cIm;
                    zx = tmp;
                    i++;
                }

                if (i < maxIterations) {
                    const hue = (i / maxIterations);
                    const color = new THREE.Color("hsl(" + hue * 360 + ", 100%, 50%)");
                    points.push(new THREE.Vector3(zx, zy, i * 0.05));
                    colors.push(color);
                }
            }
        }

        // ジオメトリとマテリアルを作成し、点群を作成
        const geometry = new THREE.BufferGeometry().setFromPoints(points);
        geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors.map(c => [c.r, c.g, c.b]).flat(), 3));
        const material = new THREE.PointsMaterial({ vertexColors: true, size: 0.1 });
        const juliaSet = new THREE.Points(geometry, material);
        scene.add(juliaSet);  // シーンに追加

        // カメラの初期位置とアニメーションの設定
        camera.position.set(0, 0, 5);  // カメラの初期位置
        const cameraSpeed = 0.02;  // カメラの移動速度

        // アニメーションループ
        function animate() {
            requestAnimationFrame(animate);

            // ジュリア集合の経路に沿ってカメラを移動
            const pointIndex = Math.floor((performance.now() * cameraSpeed) % points.length);
            const point = points[pointIndex];

            camera.position.x = point.x;  // カメラのX座標を更新
            camera.position.y = point.y;  // カメラのY座標を更新
            camera.position.z = point.z + 2;  // カメラのZ座標を更新(オフセットを追加)

            // カメラが常に集合の中心を見るように設定
            camera.lookAt(new THREE.Vector3(0, 0, 0));

            renderer.render(scene, camera);  // シーンをレンダリング
        }

        animate();  // アニメーションを開始

        // ウィンドウリサイズ時の処理
        window.addEventListener('resize', function () {
            renderer.setSize(window.innerWidth, window.innerHeight);  // レンダラーのサイズを更新
            camera.aspect = window.innerWidth / window.innerHeight;  // カメラのアスペクト比を更新
            camera.updateProjectionMatrix();  // カメラの投影行列を更新
        });
    </script>
</body>
</html>

説明
ジュリア集合をプロットし、その点に沿ってカメラが移動するアニメーションを作成しました。
各点は色相 (hue) に基づいてカラフルにプロットされます。
カメラはジュリア集合の中心を常に見るようにし、少しずつ集合の中を移動するようにしています。
このコードを実行すると、ジュリア集合がカラフルに描画され、カメラがその中を飛び回る様子が3Dで表示されます。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4