Newer
Older
about-Leaflet / VirtualShop-test.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>VirtualShop-test</title>
    <link rel="stylesheet" href="button.css"> <!-- CSSファイルをリンク -->
    <link rel="icon" href="favicon.ico">
</head>

<body>
    <div id="WebGL-output"></div>
    <div id="overlay"><!-- 透明なオーバーレイ -->
        <button id="smile-button">⸜(*ˊᗜˋ*)⸝ smile</button>
        <button id="sad-button">( ̄口 ̄∥) sad</button>
        <button id="surprised-button">…!?∑(OωO; ) surprised</button>
    </div>
    
    <script type="module">
        import * as THREE from "https://unpkg.com/three@0.126.1/build/three.module.js";
        import { PointerLockControls } from "https://unpkg.com/three@0.126.1/examples/jsm/controls/PointerLockControls.js";
        import { GLTFLoader } from "https://unpkg.com/three@0.126.1/examples/jsm/loaders/GLTFLoader.js";

        let camera;
        let scene;
        let renderer;
        let controls;
        let moveForward = false;
        let moveBackward = false;
        let moveLeft = false;
        let moveRight = false;
        let bChanLoaded = false; // B-chan.glbがロードされたかどうかを示すフラグ
        let VirtualShop, WorldStick, bchanModel, mixer;

        function init() {
            // シーンの作成
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0xffffff); // 背景色

            // カメラの作成
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(1, 5, 5);
            camera.lookAt(new THREE.Vector3(0, 0, 0));

            // ライトの作成
            //const light = new THREE.SpotLight(0xffffff, 1.0); デフォルト
            //const light = new THREE.AmbientLight(0xffffff, 1.0); 白飛びしやすい
            const light = new THREE.DirectionalLight(0xffffff, 1.0);
            light.position.set(100, 500, 500);
            scene.add(light);
            light.castShadow = true;

            // モデルの読み込み
            const loader = new GLTFLoader();

            loader.load(
                'VirtualShop-final.glb',
                function (gltf) {
                    VirtualShop = gltf.scene;
                    scene.add(VirtualShop);
                }
            );

            loader.load(
                'worldstick.glb',
                function (gltf) {
                    WorldStick = gltf.scene;
                    scene.add(WorldStick);
                }
            );

            // B-chanモデルの読み込み
            loader.load(
            'B-chan_plus_feel.glb',
            //'B-chan_plus.glb',
            function (gltf) {
            bchanModel = gltf.scene;
            scene.add(bchanModel);
            bChanLoaded = true;
            if (gltf.animations && gltf.animations.length) {
            mixer = new THREE.AnimationMixer(bchanModel);
            gltf.animations.forEach((clip) => mixer.clipAction(clip).play());
            } else {
            console.log("アニメーションがありません");
            }
    },
    function (xhr) {
        const progress = (xhr.loaded / xhr.total) * 100;
        console.log(`読み込み進捗: ${Math.round(progress)}%`);
    },
    function (error) {
        console.error('読み込みエラー', error);
        console.log('読み込みエラー');
        if (error && error.target) {
            console.error('エラーが発生したURL:', error.target.responseURL);
        }
    }
);


            // カメラコントロールの作成
            controls = new PointerLockControls(camera, document.body);
            const outputDiv = document.getElementById("WebGL-output");
            outputDiv.addEventListener("click", function () {
                controls.lock();
            });

            // 透明オーバーレイのクリックイベントを無効化
            const overlay = document.getElementById("overlay");
            overlay.addEventListener("click", function (event) {
                event.preventDefault();
                event.stopPropagation(); // イベントの伝播を止める
            });

            // キーボードのキー操作
            document.addEventListener("keydown", handleKeyDown);
            document.addEventListener("keyup", handleKeyUp);

            // レンダラーの作成
            renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
            renderer.setSize(window.innerWidth * 0.8, window.innerHeight * 0.8);
            document.getElementById("WebGL-output").appendChild(renderer.domElement);

            // リサイズイベントの追加
            window.addEventListener("resize", function () {
                renderer.setSize(window.innerWidth * 0.8, window.innerHeight * 0.8);
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
            });
        }

        function handleKeyDown(event) {
            switch (event.key) {
                case "w":
                case "ArrowUp":
                    moveForward = true;
                    break;
                case "s":
                case "ArrowDown":
                    moveBackward = true;
                    break;
                case "a":
                case "ArrowLeft":
                    moveLeft = true;
                    break;
                case "d":
                case "ArrowRight":
                    moveRight = true;
                    break;
                case "g": // 前へ進む
                    if (bChanLoaded) {
                        bchanModel.position.z -= 0.5; // 動かす方向を調整
                    }
                    break;
                case "b": // 後ろへ進む
                    if (bChanLoaded) {
                        bchanModel.position.z += 0.5; // 動かす方向を調整
                    }
                    break;
                case "f": // 左へ進む
                    if (bChanLoaded) {
                        bchanModel.position.x -= 0.5; // 動かす方向を調整
                    }
                    break;
                case "h": // 右へ進む
                    if (bChanLoaded) {
                        bchanModel.position.x += 0.5; // 動かす方向を調整
                    }
                    break;
                case "r": // Y軸固定で回転
                    if (bChanLoaded) {
                        bchanModel.rotation.y += Math.PI / 16; // 回転角度を指定(ここでは 22.5度)
                    }
                    break;
            }
        }

        function handleKeyUp(event) {
            switch (event.key) {
                case "w":
                case "ArrowUp":
                    moveForward = false;
                    break;
                case "s":
                case "ArrowDown":
                    moveBackward = false;
                    break;
                case "a":
                case "ArrowLeft":
                    moveLeft = false;
                    break;
                case "d":
                case "ArrowRight":
                    moveRight = false;
                    break;
            }
        }

        function updateCameraPosition() {
            const speed = 10;
            const direction = new THREE.Vector3();
            const { x, y, z } = controls.getObject().position;
            direction.x = Number(moveRight) - Number(moveLeft);
            direction.z = Number(moveBackward) - Number(moveForward);
            direction.normalize();
            const delta = speed * 0.1;
            controls.getObject().translateX(direction.x * delta);
            controls.getObject().translateZ(direction.z * delta);
        }

        // クリック時の処理
        document.addEventListener("dblclick", function (event) {
            event.preventDefault();
            const raycaster = new THREE.Raycaster();
            const mouse = new THREE.Vector2();
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObjects(scene.children, true);
            if (intersects.length > 0) {
                if (intersects[0].object.name == "ICO球") {
                    window.open("buy.html");
                }
                console.log(intersects[0]);
            }
        });

        // 円ボタンのクリックイベント
        document.getElementById("smile-button").addEventListener("click", function() {
            console.log("smile ⸜(*ˊᗜˋ*)⸝ボタンがクリックされました!");
            // "smile"のアニメーションを再生する
            playAnimation("smile");
        });

        // 2番目のボタンのクリックイベント
        document.getElementById("sad-button").addEventListener("click", function() {
            console.log("sad ( ̄口 ̄∥)ボタンがクリックされました!");
            // "sad"のアニメーションを再生する
            playAnimation("sad");
        });

        // 3番目のボタンのクリックイベント
        document.getElementById("surprised-button").addEventListener("click", function() {
            console.log("surprised …!?∑(OωO; )ボタンがクリックされました!");
            // "surprised"のアニメーションを再生する
            playAnimation("surprised");
        });

        // アニメーションを再生する関数
        function playAnimation(type) {
            if (!bChanLoaded || !mixer) return;
            
            const animation = bchanModel.animations.find(anim => anim.name === type);
            if (animation) {
                const action = mixer.clipAction(animation);
                action.reset().play();
            } else {
                console.log(`${type}のアニメーションが見つかりません`);
            }
        }

        // アニメーションを更新
        function animate() {
            requestAnimationFrame(animate);
            if (mixer) mixer.update(0.01);
            updateCameraPosition(); // カメラの移動更新
            renderer.render(scene, camera);
        }

        init();
        animate();
    </script>
</body>
</html>