three.js第二波,实现类似反应堆的游戏

Posted by 甘家城 on 2017-07-25 Viewed times

一开始还就迷茫呢碰撞检测比较难,后来发现了physi.js。

也是在看three.js看到的一个库,用了web worker实现各种复杂的计算。

点击这里看效果,手机电脑支持web worker(一般都支持)的都可以运行

初次加载看起来快,实际一个用于计算的ammo.js也有1.2M,只是他在后台加载。所以可能得等一会儿。

这个本应该有个onload的,不过目前还没有发现这个函数,之后有机会在探索。

思路便是:创造一个物理舞台,摄像头和渲染器和之前一样,加一个物理平面(带摩擦和弹性),加一个普通cube并来回运动,监听click事件,click时获取普通cube的位置并创造一个物理cube,物理cube便会往下掉,加一个计分。

下面是具体代码,js文件的话在下面的路径可以找到

http://test.ganjiacheng.cn/3d/learning-threejs/libs/xxx.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>test3d6</title>
    <style type="text/css">
        body{
            margin: 0;
            overflow: hidden;
        }
        #stats{
            position: absolute;
            left: 0;
            top: 0;
        }
        #grade{
            position: absolute;
            left: 50%;
            margin-left: -28px;
            top: 0;
        }
    </style>
</head>
<body>
    <div id="stats"></div>
    <div id="grade">0</div>
    <div id="webgl"></div>
    <script type="text/javascript" src="learning-threejs/libs/three.js"></script>
    <script type="text/javascript" src="learning-threejs/libs/stats.js"></script>
    <script type="text/javascript" src="learning-threejs/libs/physi.js"></script>
    <script type="text/javascript">
        var scene;
        function init(){
            var stats=initStats();

            Physijs.scripts.worker='learning-threejs/libs/physijs_worker.js';

            var scene=new Physijs.Scene();
            scene.setGravity(new THREE.Vector3(0,-50,0));

            var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
            camera.position.set(-30,40,40);
            camera.lookAt(scene.position);
            
            var renderer=new THREE.WebGLRenderer();
            renderer.setClearColor(0xEEEEEE);
            renderer.setSize(window.innerWidth,window.innerHeight);
            renderer.shadowMapEnable=true;
            
            var ground_material=Physijs.createMaterial(new THREE.MeshLambertMaterial({color:0xffffff}),0.9,0.3);
            var planeGeometry=new Physijs.BoxMesh(new THREE.BoxGeometry(10,1,10),ground_material,0)            
            scene.add(planeGeometry);
            
            function addPhyCube(x=0,y=0,z=0){
                var cubeGeometry=new THREE.BoxGeometry(10,2,10);
                var cube=new Physijs.BoxMesh(cubeGeometry,Physijs.createMaterial(new THREE.MeshLambertMaterial({color:0xffffff*Math.random()}),1,0));
                cube.position.set(x,y,z);
                scene.add(cube);
            }

            function addNormalCube(x=0,y=8,z=0){
                var cubeGeometry=new THREE.BoxGeometry(10,2,10);
                var cubeMaterial=new THREE.MeshLambertMaterial({color:0xff0000});
                var cube=new THREE.Mesh(cubeGeometry,cubeMaterial);
                cube.position.set(x,y,z);
                scene.add(cube);
            }
            
            var maxy=0;
            var NorNum=2;
            var time=0
            function refreshGrade(){
                if(time==0 && stats.domElement.textContent[0]==6){
                    document.getElementById("webgl").onmousedown=function(){
                        addPhyCube(scene.children[NorNum].position.x,scene.children[NorNum].position.y,scene.children[NorNum].position.z);
                        time=2;
                    }
                    time=1;
                }else if(time==1){
                    document.getElementById("grade").innerHTML="start";
                }else if(time==2){
                    var len=scene.children.length;
                    var maxy=0;
                    for(var i=NorNum+1;i<len;i++){
                        maxy=scene.children[i].position.y>-2&&Math.abs(scene.children[i].position.z)<15?maxy+1:maxy;
                    }                
                    camera.position.y=maxy*2+40;
                    scene.children[NorNum].position.y=maxy*2+5;
                    document.getElementById("grade").innerHTML="score:"+maxy;
                }else{
                    document.getElementById("grade").innerHTML="waiting......";
                }
            }   

            var spotLight=new THREE.SpotLight(0xffffff);
            spotLight.position.set(-40,60,0);
            scene.add(spotLight);
            spotLight.castShadow=true;
            
            document.getElementById("webgl").appendChild(renderer.domElement);
            addNormalCube(0,8,-20);
            renderer.render(scene,camera);

            var step=0;

            function rendererScene(){
                stats.update();
                refreshGrade();
                last=scene.children.length-1;
                step+=0.05;
                scene.children[NorNum].position.z+=Math.sin(step);
                requestAnimationFrame(rendererScene);
                renderer.render(scene,camera);
                scene.simulate();
            }

            function initStats(){
                var stats=new Stats();
                stats.setMode(0);
                document.getElementById("stats").appendChild(stats.domElement);
                return stats;
            }

            rendererScene();
        }
        window.onload=init;
    </script>
</body>
</html>

效果展示:


版权声明:本文为原创文章,转载请注明出处和作者,不得用于商业用途,请遵守 CC BY-NC-SA 4.0协议。

支付宝打赏 微信打赏

赞赏一下