2025年11月23日日曜日

犬の絵をボックスアートにし、動かす(Geminiを試す)

 Geminiに今日は、犬の絵をボックスアートに変換して、それを動かせるようにしてもらうよう依頼してみました。


まず、犬の絵をアップロードし、その後、

「この絵の犬のボクセルアートを作って操作ができるようにしてください。」

というプロンプトを入れてみました。


すぐに回答が来ました。それを示したのが以下の図です。


ただし、作成されたボクセルアートは、操作盤はあるのですが、操作盤で動いてくれません。


操作盤で動くように頼んでみたのですが、だめでした。


しかし、その代わりと言って、次のプログラムを作成してくれました。

下の点線から、点線までの間がプログラムです。

そして、使い方も提供してくれています。

使い方はこのプログラムの下に出ています。


---------------------------------


<!DOCTYPE html>

<html lang="ja">

<head>

    <meta charset="UTF-8">

    <title>ボクセル犬 操作デモ</title>

    <style>

        body { margin: 0; overflow: hidden; background-color: #f0f0f0; font-family: sans-serif; }

        #control-panel {

            position: absolute;

            bottom: 20px;

            left: 20px;

            width: 150px;

            height: 150px;

            background: rgba(0, 0, 0, 0.2);

            border-radius: 20px;

            display: grid;

            grid-template-columns: 1fr 1fr 1fr;

            grid-template-rows: 1fr 1fr 1fr;

            padding: 10px;

            gap: 5px;

        }

        .btn {

            background: rgba(255, 255, 255, 0.5);

            border: none;

            border-radius: 5px;

            font-size: 20px;

            cursor: pointer;

            display: flex;

            align-items: center;

            justify-content: center;

            user-select: none;

        }

        .btn:active { background: rgba(255, 255, 255, 0.8); }

        #btn-up { grid-column: 2; grid-row: 1; }

        #btn-left { grid-column: 1; grid-row: 2; }

        #btn-right { grid-column: 3; grid-row: 2; }

        #btn-down { grid-column: 2; grid-row: 3; }

        

        #instruction {

            position: absolute;

            top: 10px;

            left: 10px;

            background: rgba(255,255,255,0.8);

            padding: 10px;

            border-radius: 5px;

        }

    </style>

</head>

<body>

    <div id="instruction">画面上のボタンまたはキーボードの矢印キーで犬を動かせます</div>

    

    <div id="control-panel">

        <div class="btn" id="btn-up">▲</div>

        <div class="btn" id="btn-left">◀</div>

        <div class="btn" id="btn-right">▶</div>

        <div class="btn" id="btn-down">▼</div>

    </div>


    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>


    <script>

        // 1. シーン、カメラ、レンダラーのセットアップ

        const scene = new THREE.Scene();

        scene.background = new THREE.Color(0xa0d8ef); // 空の色


        const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);

        camera.position.set(0, 5, 8);

        camera.lookAt(0, 0, 0);


        const renderer = new THREE.WebGLRenderer({ antialias: true });

        renderer.setSize(window.innerWidth, window.innerHeight);

        renderer.shadowMap.enabled = true;

        document.body.appendChild(renderer.domElement);


        // 2. ライトの設定

        const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);

        scene.add(ambientLight);


        const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);

        dirLight.position.set(5, 10, 7);

        dirLight.castShadow = true;

        scene.add(dirLight);


        // 3. 地面(草地)

        const groundGeometry = new THREE.BoxGeometry(10, 1, 10);

        const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x7cfc00 });

        const ground = new THREE.Mesh(groundGeometry, groundMaterial);

        ground.position.y = -0.5;

        ground.receiveShadow = true;

        scene.add(ground);


        // 草の装飾(ランダム配置)

        const grassGeo = new THREE.BoxGeometry(0.1, 0.4, 0.1);

        const grassMat = new THREE.MeshBasicMaterial({ color: 0x228b22 });

        for(let i=0; i<30; i++){

            const grass = new THREE.Mesh(grassGeo, grassMat);

            grass.position.set((Math.random()-0.5)*8, 0.2, (Math.random()-0.5)*8);

            scene.add(grass);

        }


        // 4. ボクセル犬の作成(グループ化)

        const dogGroup = new THREE.Group();

        

        const orangeMat = new THREE.MeshLambertMaterial({ color: 0xe69b38 }); // 茶色

        const whiteMat = new THREE.MeshLambertMaterial({ color: 0xffffff }); // 白

        const blackMat = new THREE.MeshLambertMaterial({ color: 0x333333 }); // 黒


        // 体

        const bodyGeo = new THREE.BoxGeometry(1.2, 1, 1.8);

        const body = new THREE.Mesh(bodyGeo, orangeMat);

        body.position.y = 1;

        body.castShadow = true;

        dogGroup.add(body);


        // 頭

        const headGeo = new THREE.BoxGeometry(1, 1, 1);

        const head = new THREE.Mesh(headGeo, orangeMat);

        head.position.set(0, 1.8, 0.8);

        head.castShadow = true;

        dogGroup.add(head);


        // 耳

        const earGeo = new THREE.BoxGeometry(0.3, 0.4, 0.2);

        const earL = new THREE.Mesh(earGeo, orangeMat);

        earL.position.set(0.3, 2.4, 0.8);

        dogGroup.add(earL);

        const earR = new THREE.Mesh(earGeo, orangeMat);

        earR.position.set(-0.3, 2.4, 0.8);

        dogGroup.add(earR);


        // 鼻

        const noseGeo = new THREE.BoxGeometry(0.2, 0.2, 0.2);

        const nose = new THREE.Mesh(noseGeo, blackMat);

        nose.position.set(0, 1.7, 1.35);

        dogGroup.add(nose);


        // 目

        const eyeGeo = new THREE.BoxGeometry(0.1, 0.1, 0.1);

        const eyeL = new THREE.Mesh(eyeGeo, blackMat);

        eyeL.position.set(0.25, 1.9, 1.3);

        dogGroup.add(eyeL);

        const eyeR = new THREE.Mesh(eyeGeo, blackMat);

        eyeR.position.set(-0.25, 1.9, 1.3);

        dogGroup.add(eyeR);


        // しっぽ

        const tailGeo = new THREE.BoxGeometry(0.3, 0.6, 0.3);

        const tail = new THREE.Mesh(tailGeo, whiteMat);

        tail.position.set(0, 1.5, -1);

        tail.rotation.x = Math.PI / 4;

        dogGroup.add(tail);


        // 足(4本)

        const legGeo = new THREE.BoxGeometry(0.3, 0.6, 0.3);

        const legPositions = [

            {x: 0.4, z: 0.6}, {x: -0.4, z: 0.6}, // 前足

            {x: 0.4, z: -0.6}, {x: -0.4, z: -0.6} // 後ろ足

        ];

        const legs = [];


        legPositions.forEach(pos => {

            const leg = new THREE.Mesh(legGeo, orangeMat);

            leg.position.set(pos.x, 0.3, pos.z);

            leg.castShadow = true;

            dogGroup.add(leg);

            legs.push(leg); // アニメーション用に保存

        });


        scene.add(dogGroup);


        // 5. 操作ロジック

        let moveForward = false;

        let moveBackward = false;

        let rotateLeft = false;

        let rotateRight = false;


        // キーボード操作

        document.addEventListener('keydown', (e) => {

            switch(e.key) {

                case 'ArrowUp': moveForward = true; break;

                case 'ArrowDown': moveBackward = true; break;

                case 'ArrowLeft': rotateLeft = true; break;

                case 'ArrowRight': rotateRight = true; break;

            }

        });

        document.addEventListener('keyup', (e) => {

            switch(e.key) {

                case 'ArrowUp': moveForward = false; break;

                case 'ArrowDown': moveBackward = false; break;

                case 'ArrowLeft': rotateLeft = false; break;

                case 'ArrowRight': rotateRight = false; break;

            }

        });


        // 画面ボタン操作(マウス・タッチ)

        const setupBtn = (id, stateName) => {

            const btn = document.getElementById(id);

            btn.addEventListener('mousedown', () => eval(stateName + ' = true'));

            btn.addEventListener('mouseup', () => eval(stateName + ' = false'));

            btn.addEventListener('touchstart', (e) => { e.preventDefault(); eval(stateName + ' = true'); });

            btn.addEventListener('touchend', (e) => { e.preventDefault(); eval(stateName + ' = false'); });

        };

        setupBtn('btn-up', 'moveForward');

        setupBtn('btn-down', 'moveBackward');

        setupBtn('btn-left', 'rotateLeft');

        setupBtn('btn-right', 'rotateRight');


        // アニメーションループ

        let walkCycle = 0;


        function animate() {

            requestAnimationFrame(animate);


            // 移動処理

            const speed = 0.05;

            const rotSpeed = 0.05;

            let isMoving = false;


            if (rotateLeft) dogGroup.rotation.y += rotSpeed;

            if (rotateRight) dogGroup.rotation.y -= rotSpeed;


            if (moveForward) {

                dogGroup.position.x += Math.sin(dogGroup.rotation.y) * speed;

                dogGroup.position.z += Math.cos(dogGroup.rotation.y) * speed;

                isMoving = true;

            }

            if (moveBackward) {

                dogGroup.position.x -= Math.sin(dogGroup.rotation.y) * speed;

                dogGroup.position.z -= Math.cos(dogGroup.rotation.y) * speed;

                isMoving = true;

            }


            // 足のアニメーション

            if (isMoving) {

                walkCycle += 0.2;

                legs[0].rotation.x = Math.sin(walkCycle) * 0.5;

                legs[1].rotation.x = Math.sin(walkCycle + Math.PI) * 0.5;

                legs[2].rotation.x = Math.sin(walkCycle + Math.PI) * 0.5;

                legs[3].rotation.x = Math.sin(walkCycle) * 0.5;

            } else {

                // 止まったら足を戻す

                legs.forEach(leg => leg.rotation.x = 0);

            }


            // 画面端でのループ(簡易的)

            if (dogGroup.position.x > 5) dogGroup.position.x = -5;

            if (dogGroup.position.x < -5) dogGroup.position.x = 5;

            if (dogGroup.position.z > 5) dogGroup.position.z = -5;

            if (dogGroup.position.z < -5) dogGroup.position.z = 5;


            renderer.render(scene, camera);

        }


        animate();


        // ウィンドウリサイズ対応

        window.addEventListener('resize', () => {

            camera.aspect = window.innerWidth / window.innerHeight;

            camera.updateProjectionMatrix();

            renderer.setSize(window.innerWidth, window.innerHeight);

        });

    </script>

</body>

</html>


-----------------------------------------




使い方


1. 上記のコードをコピーします。

2. パソコンの「メモ帳」などのテキストエディタを開きます。

3. コードを貼り付けます。

4. ファイルを保存する際、ファイル名を dog_game.html にします (拡張子を.html にしてください)。

5. 保存したファイルをダブルクリックすると、ブラウザが立ち上がり、画面左下のパネルでボクセル犬を操作できます。


この使い方通りに操作をして、、実際に犬が動くことを確かめてください。コードが問題になるという表示があるとにには、Unicode(UTF-16)を使用するといいようです。


たしかに、動きますね。


0 件のコメント:

コメントを投稿

犬の絵をボックスアートにし、動かす(Geminiを試す)

 Geminiに今日は、犬の絵をボックスアートに変換して、それを動かせるようにしてもらうよう依頼してみました。 まず、犬の絵をアップロードし、その後、 「この絵の犬のボクセルアートを作って操作ができるようにしてください。」 というプロンプトを入れてみました。 すぐに回答が来ました...