4
4

明るいカラフルな チョコボールがバウンドする ゲームです。

Last updated at Posted at 2024-09-08

明るいカラフルな チョコボールがバウンドする ゲームです。

スペースキーを押すとチョコボールが出ます。

image.png

スクリーンショット 2024-09-09 042147.png

スクリーンショット 2024-09-09 042132.png

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

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>明るいカラフルなバウンドボール</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <!-- three.jsのCDNを読み込み -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

    <script>
        let scene, camera, renderer;
        let balls = [];
        const gravity = -9.8; // 重力の定数
        const floorY = -5;  // 床のY軸位置

        // シーンの初期化関数
        function init() {
            // シーンの作成
            scene = new THREE.Scene();

            // カメラの作成
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.z = 20; // カメラをZ軸に配置

            // レンダラーの作成(アンチエイリアス有効)
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight); // ウィンドウサイズに合わせる
            document.body.appendChild(renderer.domElement); // レンダラーをHTMLに追加

            // 床(不可視)を作成
            const floorGeometry = new THREE.PlaneGeometry(200, 200); // 床の大きさ
            const floorMaterial = new THREE.MeshBasicMaterial({ visible: false }); // 床は不可視
            const floor = new THREE.Mesh(floorGeometry, floorMaterial);
            floor.rotation.x = -Math.PI / 2; // 床を横に倒す
            floor.position.y = floorY; // Y軸上で床を配置
            scene.add(floor);

            // メタリックなエフェクトを付けるための光源を作成
            const light1 = new THREE.DirectionalLight(0xffffff, 1); // 白色の方向光
            light1.position.set(5, 10, 7.5).normalize(); // 光の方向
            scene.add(light1);

            const light2 = new THREE.AmbientLight(0x404040);  // 環境光
            scene.add(light2);

            // 最初に20個のボールを作成
            for (let i = 0; i < 20; i++) {
                createRandomBall(); // ランダムなボールを作成
            }

            // スペースキーが押されたときにボールを追加
            window.addEventListener('keydown', (event) => {
                if (event.code === 'Space') {
                    createRandomBall();  // スペースキーで新しいボールを追加
                }
            });

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

        // ランダムな色、位置、速度、質量を持つボールを作成する関数
        function createRandomBall() {
            const radius = Math.random() * 0.5 + 0.5; // ボールの半径をランダムに設定(0.5〜1.0)
            
            // ボールの色を明るくカラフルに設定
            const brightColor = Math.random() * 0x80ffff + 0x80ff80; // 明るい色の生成
            const ballGeometry = new THREE.SphereGeometry(radius, 32, 32); // 球体のジオメトリ作成
            const ballMaterial = new THREE.MeshStandardMaterial({
                color: brightColor, // 明るい色を指定
                metalness: 0.7, // メタリック感
                roughness: 0.2 // 滑らかさ
            });
            const ball = new THREE.Mesh(ballGeometry, ballMaterial); // 球体メッシュを作成

            // ランダムな初期位置、速度、質量、バウンド係数
            ball.position.set((Math.random() - 0.5) * 20, Math.random() * 10 + 5, (Math.random() - 0.5) * 20); // 位置をランダムに設定
            ball.velocity = new THREE.Vector3(Math.random() * 2 - 1, Math.random() * -5, Math.random() * 2 - 1); // ランダムな速度
            ball.mass = Math.random() * 2 + 1; // 質量をランダムに設定
            ball.bounceFactor = Math.random() * 0.5 + 0.3;  // バウンド係数(0.3〜0.8)
            balls.push(ball); // 配列にボールを追加
            scene.add(ball); // シーンにボールを追加
        }

        // ボールの位置と速度を更新する関数
        function updateBall(ball, deltaTime) {
            // 重力を適用
            ball.velocity.y += gravity * deltaTime;

            // 速度に基づいて位置を更新
            ball.position.add(ball.velocity.clone().multiplyScalar(deltaTime));

            // 床との衝突判定
            if (ball.position.y - ball.geometry.parameters.radius <= floorY) {
                ball.velocity.y *= -ball.bounceFactor;  // バウンド係数で速度を反転
                ball.position.y = floorY + ball.geometry.parameters.radius;  // 床を貫通しないように位置を補正
            }
        }

        // シーンをアニメーションする関数
        function animate() {
            requestAnimationFrame(animate); // 次のフレームをリクエスト

            const deltaTime = 0.016;  // 60fpsに相当するフレーム間隔

            // すべてのボールを更新
            for (let i = 0; i < balls.length; i++) {
                updateBall(balls[i], deltaTime); // 各ボールを更新
            }

            renderer.render(scene, camera); // シーンを描画
        }

        // ウィンドウサイズ変更時にリサイズを処理
        window.addEventListener('resize', () => {
            renderer.setSize(window.innerWidth, window.innerHeight); // レンダラーのサイズを更新
            camera.aspect = window.innerWidth / window.innerHeight; // カメラのアスペクト比を更新
            camera.updateProjectionMatrix(); // プロジェクションマトリックスを更新
        });

        // 初期化関数を実行
        init();
    </script>
</body>
</html>

4
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
4
4