آموزش Three.js

saalek110

Well-Known Member
حالا لوازم کامل ساخت بازی را دارید.
از کد دکمه بازی به بعد یعنی کد تکسچر و کد skybox و کد تکرار تکسچر من فایل کامل نگذاشتم. نگران نباشید بعدا اینها اون قدر استفاده میشه که همه چی بدیهی می شود.
 

saalek110

Well-Known Member
All in one
بازی اول

a38.jpg



مجموع همه کدها در این فایل هست:
شامل skybox و تکرار تکسچر در چمن کردن زمین. تکسچر به کار رفته در سنگ. صفحه کلید کار می کند. دکمه بالا و پایین آن.دکمه هایarrow
همچنین در پایین صفحه 4 دکمه برای موبایل هست.




در بازی فوق می توانیم دوربین را عقب جلو ببریم.برای عقب رفتن دو دکمه گذاشتم. با نگاه به عقب و با نگاه به جلو.
با حرکت دوربین می توانیم اشیا صحنه را از تماشاکنیم.

برنامه پیچیده تر بود ولی خیلی چیزها را حذف کردم تا اولین برنامه پیچیده نباشد. چند شی متحرک هم داشت.
کد برنامه:
JavaScript:
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <link type="text/css" rel="stylesheet" href="main.css">
 

    </head>
    <body>
<script src="js/three.js"></script>

         <script>
            var camera, scene, renderer;
            var mesh;
                         //---- control camera ----
                        var my_control_x=0;
                        var my_control_z=0;
                        var rotation=0;
                        //-------------------------

            init();
            animate();
            function init() {
                camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 35000 );
                camera.position.z = 5400;
                scene = new THREE.Scene();
                //========================================================================
             function my_draw(a, b , c , x, y , z ,material_x) {//function

                var geometry_x = new THREE.BoxBufferGeometry(  a, b, c );
                mesh_x = new THREE.Mesh( geometry_x, material_x );

    mesh_x.position.x = x;
    mesh_x.position.y = y;
    mesh_x.position.z = z;
    scene.add( mesh_x );
}//function


//-------------------------- skybox -------------------
var skyGeo = new THREE.SphereGeometry(15000, 25, 25);
//First the geometry. I wanted it big and made it big
             var texture_x = new THREE.TextureLoader().load(  'textures/cube/skyboxsun25deg/nx.jpg' );
                var material_sky = new THREE.MeshBasicMaterial( { map: texture_x } );
//Set everything together and add it to the scene here.

    var sky = new THREE.Mesh(skyGeo, material_sky);
    sky.material.side = THREE.BackSide;
    scene.add(sky);
//--------------------------- grass ------------------------
var loader = new THREE.TextureLoader();
        var texture4 = loader.load( 'textures/terrain/grasslight-big.jpg', function ( texture ) {
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.offset.set( 0, 0 );
    texture.repeat.set( 20, 35 );
    // your code
} );
var material_zz4 = new THREE.MeshBasicMaterial( { map: texture4 } );
    my_draw(8000,10,30000,0,-150,7000,material_zz4);
    //-------------------- stone ------------
                var geometry_stone = new THREE.BoxBufferGeometry(  200, 200, 200 );
                var texture_stone = new THREE.TextureLoader().load(   'textures/terrain/stone.jpg' );
                var material_stone = new THREE.MeshBasicMaterial( { map: texture_stone } );
                mesh_stone = new THREE.Mesh( geometry_stone, material_stone );
      
    mesh_stone.position.x = -650;
    mesh_stone.position.y = -100;
    mesh_stone.position.z = 5500;
    scene.add( mesh_stone );
                //======================================================================
                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                document.body.appendChild( renderer.domElement );
                window.addEventListener( 'resize', onWindowResize, false );
            }//  /init--------------------------------------------------------------------------------------------------
document.addEventListener('keydown',onKeyDown,false);
function onKeyDown(event){//onKeyDown
      var delta =20;

                              //event = event || window.event;
                         var keycode = event.keyCode;
     switch(keycode){
     case 37 : //left arrow

      camera.updateProjectionMatrix();
       break;
     case 38 : // up arrow
     //

camera.position.z = camera.position.z - delta;
camera.updateProjectionMatrix();

      break;
     case 39 : // right arrow

     camera.updateProjectionMatrix();
     break;
    case 40 : //down arrow

camera.position.z = camera.position.z + delta ;
camera.updateProjectionMatrix();
    break;
                 }
}//onKeyDown
            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize( window.innerWidth, window.innerHeight );
            }

            function animate() {

                requestAnimationFrame( animate );

camera.rotation.y=rotation;
camera.position.x =camera.position.x -  my_control_x;
camera.position.z =camera.position.z -  my_control_z;

       camera.updateProjectionMatrix();
                renderer.render( scene, camera );
            }
//======================================================================
function myFunction(x) {
   if (x==1) {my_control_z=20;    my_control_x=0;    rotation=0; }
   if (x==2) {my_control_z=-20;    rotation=3.14159; }
   if (x==3) {my_control_z=0;  my_control_x=0;   }
   if (x==9) {my_control_z=-20;   my_control_x=0;  rotation=0;    }
}
        </script>
             <center>
             <img src="textures/buttons/up.png" height="120" size="120" alt="Img" onclick="myFunction('1')">
             <img src="textures/buttons/stop.jpg" height="120" size="120" alt="Img" onclick="myFunction('3')">
             <img src="textures/buttons/down.png" height="120" size="120" alt="Img" onclick="myFunction('9')">
             <img src="textures/buttons/down.png" height="120" size="120" alt="Img" onclick="myFunction('2')">
            </center>
    </body>
</html>
 
آخرین ویرایش:

saalek110

Well-Known Member
شرح کد بازی اول:

در صفحه قبل با تابع ساختن در جاوا اسکریپت شما آشنا شدید.
در کد بالا من تابع my_draw را ساختم تا در ساخت اشیا پر تعداد در مقدار کد صرفه جویی شود.
ورودی های این تابع ابعاد شی و مختصات محل قرار گیری شی و متریال است.
یعنی پس از ایجاد متریال آن را به همراه 6 عدد به این تابع ارسال می کنیم تا شکل ساخته شود.

----------------------
قسمت skybox را مشخص کرده ام. و قسمت grass که چمن کاری تکراری زمین است.
شی stone توسط تابع my_draw ساخته نشد. چون می خواستم این شی متحرک بشود. اون یک سنگ بزرگ مکعب مستطیلی شکل است که روی زمین است.

بعد اشیا دریافت ورودی کیبورد را می بینید.

در تابع animate کدهای

JavaScript:
camera.rotation.y=rotation;
camera.position.x =camera.position.x -  my_control_x;
camera.position.z =camera.position.z -  my_control_z;
برای کار کردن با زاویه و محل دوربین است. متغیرهای مورد استفاده اول برنامه تعریف شده و با تابع ساختگی من یعنی myFunction
که در انتهای برنامه است این اعداد دست کاری می شود.
خود تابع myFunction با دکمه های واقع در قسمت html انتهای صفحه صدا زده می شود.
 
آخرین ویرایش:

saalek110

Well-Known Member
شرح کلی برنامه three js : در تابع init مقدار دهی هاست . بعد تابع animate را داریم باید از این تابع استفاده کنیم. یعنی متغیرهای خود را در تابع animate تغییر می دهیم یا مورد استفاده قرار می دهیم یعنی به چیزی نسبت می دهیم. مثلا به مختصات دوربین یا چرخش دوربین در برنامه بالا.

stone.jpg
تکسچر سنگی برای شی داخل بازی.
 
آخرین ویرایش:

saalek110

Well-Known Member
بازی اول شامل یک زمین چمن شده و یک آسمان و یک بلوک سنگی است. دوربین هم با کیبورد و هم با دکمه های لمسی حرکت به جلو و عقب دارد.
برای حرکت به چپ و راست خودتان بنویسید. با camera.position.x کار کنید. در برنامه فوق می بینید متغیری که به camera.position.x افزوده می شود همیشه صفر است. چون دکمه های حرکت به چپ و راست را من حذف کردم تا برنامه ساده تر بشود.
می توانید دکمه هایی برای نگاه به اطراف بسازید یا اینکه کاری کنید به هر طرف نگاه می کند به همان طرف هم برود که با توابع سینوس و کسینوس است.
 
آخرین ویرایش:

saalek110

Well-Known Member
حرکت اجسام هم مثل حرکت دوربین است .
برای به حرکت درآوردن سنگ از کد زیر در تابع animate استفاده کنید:
JavaScript:
mesh_stone.position.z +=  2;

یا قبلا برنامه یک شکل به نام mesh داشته که با کد زیر:
JavaScript:
                mesh.rotation.x += 0.05;
                mesh.rotation.y += 0.09;
                mesh.position.z +=  2;
چرخش در دو جهت و حرکت داشته. کد فوق در تابع animate درج می شود. ولی اول باید شی mesh در برنامه وجود داشته باشد.
 

saalek110

Well-Known Member
پس حالا شما اشیای دارای تکسچر دارید. و می توانید محیط بزرگی از اشیای تکسچر دار بسازید. مثل خیابان و دیوار و ....
همچنین اشیای متحرک می توانید داشته باشید.
ولی برخورد را ندارید. یعنی کد بررسی برخورد را ندارید.

پایان قسمت اول آموزش. 19 خرداد 1400.

a.jpg
 

saalek110

Well-Known Member
a2.jpg
 

saalek110

Well-Known Member
اشکال

با استفاده از کدهاای این صفحه من استوانه ساختم:
JavaScript:
 var cylinderGeometry = new THREE.CylinderGeometry(30, 30, 100, 9, 2);

دو عدد اول اندازه بالا و پایین و عدد سوم ارتفاع و دو عدد بعدی تعداد تقسیمات که می توانید حذف کنید.
 
آخرین ویرایش:

saalek110

Well-Known Member

ساختن گروهی از اشیا.
JavaScript:
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );

const cubeA = new THREE.Mesh( geometry, material );
cubeA.position.set( 100, 100, 0 );

const cubeB = new THREE.Mesh( geometry, material );
cubeB.position.set( -100, -100, 0 );

//create a group and add the two cubes
//These cubes can now be rotated / scaled etc as a group
const group = new THREE.Group();
group.add( cubeA );
group.add( cubeB );

scene.add( group );

در کد بالا در ابتدا دو شی ساخته ایم ولی به scene اضافه نکردیم.
بعد گروه را ساختیم و دو شی را به گروه اضافه کردیم و بعد گروه را به scene اضافه کردیم.
 

saalek110

Well-Known Member
با عکسهای شفاف می توان درخت ساخت.(یا بوته) کلا هر عکس png دور شطرنجی را می توانید استفاده کنید.
از عکس زیر استفاده کنید:

tree11.png
نتیجه:

tree.png

کد:
JavaScript:
const map = new THREE.TextureLoader().load( 'textures/tree11.png' );
const material = new THREE.SpriteMaterial( { map: map, color: 0xffffff } );

const sprite = new THREE.Sprite( material );
sprite.scale.set(1000,1000, 1)
    sprite.position.x = 100;
    sprite.position.y =200;
    sprite.position.z = 100;
scene.add( sprite );

چه از روبرو به آن نگاه کنی یا از کنار به همین شکل است.





a1.png
 
آخرین ویرایش:

saalek110

Well-Known Member
ساخت شیشه:

glass.jpg

صفت opacity را کم کنید.
JavaScript:
const geometry = new THREE.PlaneGeometry( 300, 300 );
var texture = new THREE.TextureLoader().load( 'textures/glass.png' );

const material = new THREE.MeshBasicMaterial({
    // color: 0xffffff,
    map: texture,
    transparent: true,
    opacity: 0.5

})
const plane = new THREE.Mesh( geometry, material );
    plane.position.x = -2100;
    plane.position.y =50;
    plane.position.z = 5000;
scene.add( plane );

اون خط:
JavaScript:
transparent: true

شاید کاری انجام نمی دهد ولی من تست نکردم. خودتان تست کنید.

glass2.jpg
 
آخرین ویرایش:

saalek110

Well-Known Member
صفحه رنگی:
JavaScript:
const geometry = new THREE.PlaneGeometry( 300, 300 );
const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
const plane = new THREE.Mesh( geometry, material );
    plane.position.x = -1300;
    plane.position.y =50;
    plane.position.z = 5000;
scene.add( plane );


a4.jpg
 
آخرین ویرایش:

saalek110

Well-Known Member
a14.jpg

یک متغیر اول برنامه تنظیم کنید:
JavaScript:
 var counter=0;
داخل تابع animate آن را افزایش دهید.
JavaScript:
counter+=1;
و بعد میشه این کد را در تابع animate افزود:
JavaScript:
if (counter==100)  { mesh_stone.position.z +=  20;  counter=0;}
من تست کردم کار می کند.
یعنی هر 100 تیک یک بار تخته سنگ را تکان می دهد.
مثلا اگر به برنامه خود خورشید اضافه کنید در هر مثلا هزار تیک خورشید را کمی می چرخانید.
کارهای دیگه ای هم احتمالا بشود با این سیستم کرد خودتان فکر کنید. مثلا بعضی چک کردن ها را لازم نیست در هر تیک انجام داد. میشه در هر 10 تیک یا هر 100 تیک انجام داد.

در بازیها هم حرکات هر از چند گاهی می تواند مفید باشد.
 
آخرین ویرایش:

saalek110

Well-Known Member
من فیزیک ammo را دانلود کردم و روی هاستم آپلود کردم. از نمونه برنامه هایش خوشم اومد.
 
آخرین ویرایش:

saalek110

Well-Known Member
مخصوصا بازی ماشین آن:

a5.jpg

a7.jpg

در تصویر دوم ماشین در حال پرش و عبور از دیواره بلوک هاست.
 
آخرین ویرایش:

saalek110

Well-Known Member
برای حرکت کاربر یا دوربین بحثی اینجا شد:
و خلاصه اش به این فرمول زسیدیم:
JavaScript:
rotation += 0.05;
camera.position.x = Math.sin(rotation) * distance;
camera.position.z = Math.cos(rotation) * distance;

یعنی وقتی نگاه بازیکن یا دوربین زاویه دار باشه چقدر در راستای x و z باید حرکت کند.

یعنی شما زاویه و سرعت حرکت را تعین می کنید و کد بالا محل دوربین یا کاربر را تغییر می دهد.
 

جدیدترین ارسال ها

بالا