paint-brush
React ve Three.js Stack'ı Kullanarak Kendi 3D Shooter'ınızı Oluşturma - Bölüm 1ile@varlab
2,947 okumalar
2,947 okumalar

React ve Three.js Stack'ı Kullanarak Kendi 3D Shooter'ınızı Oluşturma - Bölüm 1

ile Ivan Zhukov17m2023/10/21
Read on Terminal Reader

Çok uzun; Okumak

Web teknolojilerinin ve etkileşimli uygulamaların aktif olarak geliştiği bir çağda, 3D grafikler giderek daha alakalı ve talep görüyor. Peki web geliştirmenin avantajlarını kaybetmeden 3D uygulama nasıl oluşturulur? Bu makalede, doğrudan tarayıcıda kendi oyununuzu oluşturmak için Three.js'nin gücünü React'ın esnekliğiyle nasıl birleştirebileceğinize bakacağız. Bu makale size React Three Fiber kitaplığını tanıtacak ve etkileşimli 3D oyunların nasıl oluşturulacağını öğretecektir.
featured image - React ve Three.js Stack'ı Kullanarak Kendi 3D Shooter'ınızı Oluşturma - Bölüm 1
Ivan Zhukov HackerNoon profile picture
0-item
1-item

Modern web geliştirmede klasik ve web uygulamaları arasındaki sınırlar her geçen gün bulanıklaşıyor. Bugün yalnızca etkileşimli web siteleri değil, aynı zamanda doğrudan tarayıcıda tam teşekküllü oyunlar da oluşturabiliyoruz. Bunu mümkün kılan araçlardan biri, React teknolojisini kullanarak Three.js tabanlı 3D grafikler oluşturmaya yönelik güçlü bir araç olan React Three Fiber kitaplığıdır.

React Three Fiber yığını hakkında

React Three Fiber, web üzerinde 3D grafikler oluşturmak için React'in yapısını ve ilkelerini kullanan, Three.js üzerinde bir sarmalayıcıdır. Bu yığın, geliştiricilerin Three.js'nin gücünü React'ın rahatlığı ve esnekliğiyle birleştirmesine olanak tanıyarak uygulama oluşturma sürecini daha sezgisel ve organize hale getirir.


React Three Fiber'in temelinde, bir sahnede yarattığınız her şeyin bir React bileşeni olduğu fikri yatmaktadır. Bu, geliştiricilerin tanıdık kalıpları ve metodolojileri uygulamalarına olanak tanır.

React Three Fiber'in temel avantajlarından biri React ekosistemiyle entegrasyon kolaylığıdır. Bu kütüphaneyi kullanırken diğer React araçları hala kolayca entegre edilebilir.

Web-GameDev'in Uygunluğu

Web-GameDev son yıllarda basit 2D Flash oyunlarından masaüstü uygulamalarıyla karşılaştırılabilecek karmaşık 3D projelere doğru evrimleşerek büyük değişiklikler geçirdi. Popülerlik ve yeteneklerdeki bu artış, Web-GameDev'i göz ardı edilemeyecek bir alan haline getiriyor.


Web oyunlarının ana avantajlarından biri erişilebilirliğidir. Oyuncuların herhangi bir ek yazılım indirmesine ve yüklemesine gerek yoktur; tarayıcılarındaki bağlantıya tıklamanız yeterlidir. Bu, oyunların dağıtımını ve tanıtımını basitleştirerek dünya çapında geniş bir kitleye ulaşmasını sağlar.


Son olarak, web oyunu geliştirme, geliştiricilerin tanıdık teknolojileri kullanarak gamedev'de ellerini denemeleri için harika bir yol olabilir. Mevcut araçlar ve kütüphaneler sayesinde, 3D grafiklerde deneyiminiz olmasa bile ilginç ve kaliteli projeler yaratmak mümkün!

Modern tarayıcılarda oyun performansı

Modern tarayıcılar, oldukça basit web tarama araçlarından, karmaşık uygulamaları ve oyunları çalıştırmak için güçlü platformlara dönüşerek uzun bir yol kat etti. Chrome , Firefox , Edge ve diğerleri gibi önemli tarayıcılar, yüksek performans sağlamak için sürekli olarak optimize ediliyor ve geliştiriliyor; bu da onları karmaşık uygulamalar geliştirmek için ideal bir platform haline getiriyor.


Tarayıcı tabanlı oyunların gelişimini hızlandıran temel araçlardan biri WebGL'dir . Bu standart, geliştiricilerin, 3D oyunların performansını önemli ölçüde artıran donanım grafik hızlandırmasını kullanmasına olanak tanıdı. Diğer webAPI'lerle birlikte WebGL , doğrudan tarayıcıda etkileyici web uygulamaları oluşturmaya yönelik yeni olanaklar sunar.


Bununla birlikte, tarayıcı için oyun geliştirirken performansın çeşitli yönlerini dikkate almak çok önemlidir: kaynak optimizasyonu, bellek yönetimi ve farklı cihazlara uyarlama, bir projenin başarısını etkileyebilecek kilit noktalardır.

İşaretin üzerinde!

Bununla birlikte, kelimeler ve teori başka bir şeydir, ancak pratik deneyim tamamen başka bir şeydir. Web oyunu geliştirmenin tüm potansiyelini gerçekten anlamak ve takdir etmek için en iyi yol, kendinizi geliştirme sürecine dahil etmektir. Bu nedenle başarılı web oyunu geliştirme örneği olarak kendi oyunumuzu yaratacağız. Bu süreç, geliştirmenin temel yönlerini öğrenmemize, gerçek sorunlarla yüzleşmemize ve bunlara çözüm bulmamıza ve bir web oyunu geliştirme platformunun ne kadar güçlü ve esnek olabileceğini görmemize olanak tanıyacak.


Bir dizi makalede, bu kütüphanenin özelliklerini kullanarak birinci şahıs nişancı oyununun nasıl oluşturulacağına bakacağız ve web-gamedev'in heyecan verici dünyasına dalacağız!


Son demo


GitHub'daki depo


Şimdi başlayalım!

Projeyi ayarlama ve paketleri yükleme

Öncelikle bir React proje şablonuna ihtiyacımız olacak. Öyleyse onu yükleyerek başlayalım.


 npm create vite@latest


  • React kütüphanesini seçin;
  • JavaScript'i seçin.


Ek npm paketlerini yükleyin.


 npm install three @react-three/fiber @react-three/drei @react three/rapier zustand @tweenjs/tween.js


Daha sonra projemizdeki gereksiz her şeyi silin .


Bölüm kodu

Kanvas görünümünü özelleştirme

Main.jsx dosyasına sayfada kapsam olarak görüntülenecek bir div öğesi ekleyin. Bir Canvas bileşeni ekleyin ve kameranın görüş alanını ayarlayın. Canvas bileşeninin içine Uygulama bileşenini yerleştirin.


main.jsx


Kullanıcı arayüzü öğelerini ekranın tam yüksekliğine kadar genişletmek ve kapsamı ekranın ortasında bir daire olarak görüntülemek için index.css'ye stiller ekleyelim.


index.css


Uygulama bileşenine, oyun sahnemizde arka plan olarak gökyüzü şeklinde görüntülenecek bir Gökyüzü bileşeni ekliyoruz.


Uygulama.jsx


Sahnede gökyüzünün gösterilmesi


Bölüm kodu

Zemin yüzeyi

Bir Ground bileşeni oluşturalım ve onu App bileşenine yerleştirelim.


Uygulama.jsx


Ground'da düz bir yüzey elemanı oluşturun. Y ekseninde, bu düzlem kameranın görüş alanı içinde olacak şekilde onu aşağı doğru hareket ettirin. Ayrıca düzlemi yatay hale getirmek için X ekseninde çevirin.


Ground.jsx


Malzeme rengi olarak griyi belirtmemize rağmen düzlem tamamen siyah görünüyor.


Olay yerinde düz


Bölüm kodu

Temel aydınlatma

Varsayılan olarak sahnede aydınlatma yoktur, bu nedenle nesneyi her taraftan aydınlatan ve yönlendirilmiş bir ışına sahip olmayan ambientLight ışık kaynağını ekleyelim. Bir parametre olarak ışığın yoğunluğunu ayarlayın.


Uygulama.jsx


Işıklı düzlem


Bölüm kodu

Zemin yüzeyi için doku

Zemin yüzeyinin homojen görünmemesi için doku ekleyeceğiz. Zemin yüzeyinin tüm yüzey boyunca tekrarlanan hücreler şeklinde bir desenini yapın.

Varlıklar klasörüne dokulu bir PNG görüntüsü ekleyin.


Doku eklendi


Sahneye bir doku yüklemek için @react- three/drei paketindeki useTexture kancasını kullanalım. Ve kancanın parametresi olarak dosyaya aktarılan doku görüntüsünü aktaracağız. Görüntünün yatay eksenlerdeki tekrarını ayarlayın.


Ground.jsx


Düzlemdeki doku


Bölüm kodu

Kamera hareketi

@react-third/drei paketindeki PointerLockControls bileşenini kullanarak, fareyi hareket ettirdiğinizde hareket etmeyecek, ancak kameranın sahnedeki konumunu değiştirecek şekilde imleci ekrana sabitleyin.


Uygulama.jsx


Kamera hareketi gösterimi


Ground bileşeni için küçük bir düzenleme yapalım.


Ground.jsx


Bölüm kodu

Fizik ekleme

Netlik sağlamak için sahneye basit bir küp ekleyelim.


 <mesh position={[0, 3, -5]}> <boxGeometry /> </mesh> 


Sahnedeki küp


Şu anda sadece boşlukta asılı duruyor.


Sahneye "fizik" eklemek için @react-third/rapier paketindeki Fizik bileşenini kullanın. Parametre olarak, yerçekimi kuvvetlerini eksenler boyunca ayarladığımız yerçekimi alanını yapılandırın.


 <Physics gravity={[0, -20, 0]}> <Ground /> <mesh position={[0, 3, -5]}> <boxGeometry /> </mesh> </Physics>


Ancak küpümüz fizik bileşeninin içinde ama ona hiçbir şey olmuyor. Küpün gerçek bir fiziksel nesne gibi davranmasını sağlamak için onu @react- three/rapier paketindeki RigidBody bileşenine sarmamız gerekiyor.


Uygulama.jsx


Bundan sonra sayfa her yeniden yüklendiğinde küpün yerçekiminin etkisiyle aşağıya düştüğünü hemen göreceğiz.


küp sonbahar


Ancak şimdi başka bir görev daha var - zemini küpün etkileşime girebileceği ve ötesine düşmeyeceği bir nesne haline getirmek gerekiyor.


Bölüm kodu

Fiziksel bir nesne olarak zemin

Ground bileşenine geri dönelim ve zemin yüzeyinin üzerine sarmalayıcı olarak bir RigidBody bileşeni ekleyelim.


Ground.jsx


Artık düşerken küp gerçek bir fiziksel nesne gibi yerde kalıyor.


Uçakta düşen küp


Bölüm kodu

Bir karakteri fizik kanunlarına tabi kılmak

Sahnedeki karakteri kontrol edecek Player bileşeni oluşturalım.


Karakter, eklenen küple aynı fiziksel nesnedir, bu nedenle sahnedeki küpün yanı sıra zemin yüzeyiyle de etkileşime girmelidir. Bu yüzden RigidBody bileşenini ekliyoruz. Ve karakteri kapsül şeklinde yapalım.


Player.jsx


Player bileşenini Fizik bileşeninin içine yerleştirin.


Uygulama.jsx


Artık karakterimiz sahneye çıkmıştır.


Kapsül formunda bir karakter


Bölüm kodu

Bir karakteri taşıma - kanca oluşturma

Karakter WASD tuşları kullanılarak kontrol edilecek ve Ara Çubuğu kullanılarak atlanacaktır.

Kendi reaksiyon kancamızla karakteri hareket ettirme mantığını uyguluyoruz.


Bir hooks.js dosyası oluşturalım ve buraya yeni bir usePersonControls fonksiyonu ekleyelim.


{"keycode": "gerçekleştirilecek eylem"} biçiminde bir nesne tanımlayalım. Daha sonra, klavye tuşlarına basmak ve bırakmak için olay işleyicileri ekleyin. İşleyiciler tetiklendiğinde, gerçekleştirilen mevcut eylemleri belirleyeceğiz ve bunların aktif durumlarını güncelleyeceğiz. Nihai sonuç olarak kanca, {"işlem devam ediyor": "durum"} biçiminde bir nesne döndürecektir.


hooks.js


Bölüm kodu

Bir karakteri taşıma - kanca uygulama

usePersonControls kancasını uyguladıktan sonra, karakteri kontrol ederken kullanılmalıdır. Oyuncu bileşeninde hareket durumu izlemeyi ekleyeceğiz ve karakterin hareket yönünün vektörünü güncelleyeceğiz.


Ayrıca hareket yönlerinin durumlarını saklayacak değişkenleri de tanımlayacağız.


Player.jsx


Karakterin konumunu güncellemek için @react- three/fiber paketi tarafından sağlanan Frame'i kullanalım. Bu kanca, requestAnimationFrame'e benzer şekilde çalışır ve işlevin gövdesini saniyede yaklaşık 60 kez çalıştırır.


Player.jsx


Kod Açıklaması:

1. const playerRef = useRef(); Oynatıcı nesnesi için bir bağlantı oluşturun. Bu bağlantı, sahnedeki oynatıcı nesnesi ile doğrudan etkileşime izin verecektir.

2. const { ileri, geri, sol, sağ, atlama } = usePersonControls(); Bir kanca kullanıldığında, oynatıcının o anda hangi kontrol düğmelerine basıldığını gösteren boole değerlerine sahip bir nesne döndürülür.

3. useFrame((durum) => { ... }); Kanca, animasyonun her karesinde çağrılır. Bu kancanın içinde oyuncunun konumu ve doğrusal hızı güncellenir.

4. if (!playerRef.current) geri dönerse; Bir oynatıcı nesnesinin varlığını kontrol eder. Oynatıcı nesnesi yoksa işlev, hataları önlemek için yürütmeyi durduracaktır.

5. sabit hız = playerRef.current.linvel(); Oyuncunun mevcut doğrusal hızını alın.

6. frontVector.set(0, 0, geri - ileri); Basılan düğmelere göre ileri/geri hareket vektörünü ayarlayın.

7. sideVector.set(sol - sağ, 0, 0); Sol/sağ hareket vektörünü ayarlayın.

8. Direction.subVectors(frontVector, sideVector).normalize().multiplyScalar(MOVE_SPEED); Oyuncu hareketinin son vektörünü, hareket vektörlerini çıkararak, sonucu normalleştirerek (vektör uzunluğu 1 olacak şekilde) ve hareket hızı sabitiyle çarparak hesaplayın.

9. playerRef.current.wakeUp(); Değişikliklere tepki verdiğinden emin olmak için oynatıcı nesnesini "uyandırır". Bu yöntemi kullanmazsanız, bir süre sonra nesne "uykuya" girecek ve konum değişikliklerine tepki vermeyecektir.

10. playerRef.current.setLinvel({ x: yön.x, y: hız.y, z: yön.z }); Hesaplanan hareket yönüne göre oyuncunun yeni doğrusal hızını ayarlayın ve mevcut dikey hızı koruyun (atlamaları veya düşmeleri etkilemeyecek şekilde).


Sonuç olarak WASD tuşlarına basıldığında karakter sahnede hareket etmeye başladı. Ayrıca küple de etkileşime girebilir çünkü her ikisi de fiziksel nesnelerdir.


Karakter hareketi


Bölüm kodu

Bir karakteri taşıma - atlama

Atlamayı uygulamak için @dimforge/rapier3d-compat ve @react-third/rapier paketlerindeki işlevselliği kullanalım. Bu örnekte karakterin yerde olduğunu ve atlama tuşuna basıldığını kontrol edelim. Bu durumda karakterin yönünü ve ivme kuvvetini Y eksenine ayarlıyoruz.


Oyuncu için kütle ekleyeceğiz ve tüm eksenlerde dönüşü engelleyeceğiz, böylece sahnedeki diğer nesnelerle çarpıştığında farklı yönlere düşmeyecek.


Player.jsx


Kod Açıklaması:

  1. const dünyası = rapier.world; Rapier fizik motoru sahnesine erişim elde ediliyor. Tüm fiziksel nesneleri içerir ve etkileşimlerini yönetir.
  1. const ray = world.castRay(new RAPIER.Ray(playerRef.current.translation(), { x: 0, y: -1, z: 0 })); Burası "raycasting"in (raycasting) gerçekleştiği yerdir. Oyuncunun mevcut konumundan başlayan ve y ekseninin aşağısını gösteren bir ışın oluşturulur. Bu ışın, sahnedeki herhangi bir nesneyle kesişip kesişmediğini belirlemek için sahneye "dökülür".
  1. const grounded = ray && ray.collider && Math.abs(ray.toi) <= 1.5; Oyuncunun yerde olup olmadığı kontrol edilir:
  • ışın - ışının yaratılıp yaratılmadığı;
  • ray.collider - ışının olay yerindeki herhangi bir nesneyle çarpışıp çarpışmadığı;
  • Math.abs(ray.toi) - ışının "maruz kalma süresi". Bu değerin verilen değerden küçük veya ona eşit olması, oyuncunun "yerde" sayılacak kadar yüzeye yakın olduğunu gösterebilir.


Ayrıca, sahnedeki diğer nesnelerle etkileşime girecek fiziksel bir nesne ekleyerek "iniş" durumunu belirlemek için kullanılan ışın izlemeli algoritmanın doğru çalışması için Zemin bileşenini değiştirmeniz gerekir.


Ground.jsx


Sahneyi daha iyi görebilmek için kamerayı biraz daha yukarı kaldıralım.


main.jsx


Karakter atlayışları


Bölüm kodu

Kamerayı karakterin arkasına taşıma

Kamerayı hareket ettirmek için oyuncunun mevcut konumunu alacağız ve çerçeve her yenilendiğinde kameranın konumunu değiştireceğiz. Ve karakterin kameranın yönlendirildiği yörünge boyunca tam olarak hareket etmesi için applicationEuler'ı eklememiz gerekiyor.


Player.jsx


Kod Açıklaması:

ApplyEuler yöntemi, belirtilen Euler açılarına dayalı olarak bir vektöre rotasyon uygular. Bu durumda kamera döndürme yön vektörüne uygulanır. Bu, oyuncunun kameranın döndürüldüğü yönde hareket etmesi için hareketi kamera yönüne göre eşleştirmek için kullanılır.


Player'ın boyutunu biraz ayarlayalım ve küpe göre daha uzun hale getirelim, CapsuleCollider'ın boyutunu artıralım ve "atlama" mantığını düzeltelim.


Player.jsx


Kamerayı hareket ettirme


Bölüm kodu

Küplerin üretilmesi

Sahnenin tamamen boş hissettirmemesi için küp oluşturmayı ekleyelim. Json dosyasında küplerin her birinin koordinatlarını listeleyin ve ardından bunları sahnede görüntüleyin. Bunu yapmak için, içinde bir koordinat dizisini listeleyeceğimiz cubes.json dosyasını oluşturun.


 [ [0, 0, -7], [2, 0, -7], [4, 0, -7], [6, 0, -7], [8, 0, -7], [10, 0, -7] ]


Cube.jsx dosyasında, döngü halinde küpler oluşturacak bir Küpler bileşeni oluşturun. Ve Cube bileşeni doğrudan oluşturulan nesne olacaktır.


 import {RigidBody} from "@react-three/rapier"; import cubes from "./cubes.json"; export const Cubes = () => { return cubes.map((coords, index) => <Cube key={index} position={coords} />); } const Cube = (props) => { return ( <RigidBody {...props}> <mesh castShadow receiveShadow> <meshStandardMaterial color="white" /> <boxGeometry /> </mesh> </RigidBody> ); }


Oluşturduğumuz Küpler bileşenini önceki tek küpü silerek Uygulama bileşenine ekleyelim.


Uygulama.jsx


Küplerin üretilmesi


Bölüm kodu

Modelin projeye aktarılması

Şimdi sahneye bir 3D model ekleyelim. Karakter için bir silah modeli ekleyelim. Bir 3D model arayarak başlayalım. Mesela şunu ele alalım.


Modeli GLTF formatında indirin ve projenin kökündeki arşivi açın.

Modeli sahneye aktarmak için ihtiyacımız olan formatı elde etmek için gltf-pipeline eklenti paketini kurmamız gerekecek.


npm i -D gltf-pipeline


gltf-pipeline paketini kullanarak modeli GLTF formatından GLB formatına yeniden dönüştürün, çünkü bu formatta tüm model verileri tek bir dosyaya yerleştirilir. Oluşturulan dosyanın çıktı dizini olarak ortak klasörü belirtiyoruz.


gltf-pipeline -i weapon/scene.gltf -o public/weapon.glb


Daha sonra sahneye eklemek için bu modelin işaretlemesini içerecek bir reaksiyon bileşeni oluşturmamız gerekiyor. @react- three/fiber geliştiricilerinin resmi kaynağını kullanalım.


Dönüştürücüye gitmek, dönüştürülen silah.glb dosyasını yüklemenizi gerektirecektir.


Sürükle ve bırak veya Explorer aramasını kullanarak bu dosyayı bulun ve indirin.


Dönüştürülen model


Dönüştürücüde, kodunu projemize yeni bir WeaponModel.jsx dosyasına aktaracağımız, bileşenin adını dosyayla aynı adla değiştireceğimiz, oluşturulan reaksiyon bileşenini göreceğiz.


Bölüm kodu

Silah modelinin sahnede sergilenmesi

Şimdi oluşturulan modeli sahneye aktaralım. App.jsx dosyasına WeaponModel bileşenini ekleyin.


Uygulama.jsx


İçe aktarılan modelin gösterimi


Bölüm kodu

Gölgeler ekleme

Sahnemizin bu noktasında nesnelerin hiçbiri gölge düşürmüyor.

Sahnede gölgeleri etkinleştirmek için Canvas bileşenine gölgeler niteliğini eklemeniz gerekir.


main.jsx


Daha sonra yeni bir ışık kaynağı eklememiz gerekiyor. Sahnede zaten ambientLight olmasına rağmen, yönlü bir ışık huzmesine sahip olmadığından nesneler için gölge oluşturamaz. O halde directionLight adında yeni bir ışık kaynağı ekleyelim ve onu yapılandıralım. " Yayınlama " gölge modunu etkinleştirme özelliği castShadow'dur . Bu nesnenin diğer nesnelere gölge düşürebileceğini belirten bu parametrenin eklenmesidir.


Uygulama.jsx


Daha sonra Ground bileşenine bir başka özellik olan takeShadow'u ekleyelim, bu da sahnedeki bileşenin gölgeleri kendi üzerinde alıp görüntüleyebilmesi anlamına gelir.


Ground.jsx


Model gölge düşürüyor


Sahnedeki diğer nesnelere de benzer özellikler eklenmelidir: küpler ve oynatıcı. Küpler için castShadow ve getShadow'u ekleyeceğiz, çünkü hem gölge oluşturabilir hem de gölge alabilirler ve oyuncu için yalnızca castShadow'u ekleyeceğiz.


Player için castShadow'u ekleyelim.


Player.jsx


Cube için castShadow'u ve getShadow'u ekleyin.


Cube.jsx


Sahnedeki tüm nesnelerin gölgesi vardır


Bölüm kodu

Gölge ekleme - gölge kırpmayı düzeltme

Şimdi yakından bakarsanız, gölgenin düştüğü yüzey alanının oldukça küçük olduğunu göreceksiniz. Ve bu alanın ötesine geçerken gölge basitçe kesiliyor.


Gölge kırpma


Bunun nedeni, varsayılan olarak kameranın, DirectionLight'tan görüntülenen gölgelerin yalnızca küçük bir alanını yakalamasıdır. Bu görünürlük alanını genişletmek için ilave gölge-kamera-(üst, alt, sol, sağ) niteliklerini ekleyerek directionLight bileşenini kullanabiliriz. Bu nitelikleri ekledikten sonra gölge biraz bulanıklaşacaktır. Kaliteyi artırmak için shadow-mapSize özelliğini ekleyeceğiz.


Uygulama.jsx


Bölüm kodu

Silahları bir karaktere bağlama

Şimdi birinci şahıs silah gösterimini ekleyelim. Silah davranışı mantığını ve 3D modelin kendisini içerecek yeni bir Silah bileşeni oluşturun.


 import {WeaponModel} from "./WeaponModel.jsx"; export const Weapon = (props) => { return ( <group {...props}> <WeaponModel /> </group> ); }


Bu bileşeni karakterin RigidBody'si ile aynı seviyeye yerleştirelim ve useFrame kancasında kameradan gelen değerlerin konumuna göre konumu ve dönüş açısını ayarlayacağız.


Player.jsx


Birinci şahıs silah modeli gösterimi


Bölüm kodu

Yürürken sallanan silahın animasyonu

Karakterin yürüyüşünü daha doğal hale getirmek için hareket ederken silaha hafif bir hareket ekleyeceğiz. Animasyonu oluşturmak için kurulu tween.js kütüphanesini kullanacağız.


Silah bileşeni, useRef kancası aracılığıyla ona bir referans ekleyebilmeniz için bir grup etiketine sarılacaktır.


Player.jsx


Animasyonu kaydetmek için biraz useState ekleyelim.


Player.jsx


Animasyonu başlatmak için bir fonksiyon oluşturalım.


Player.jsx


Kod Açıklaması:

  1. const twSwayingAnimation = new TWEEN.Tween(currentPosition) ... Geçerli konumundan yeni bir konuma "sallanan" bir nesnenin animasyonunu oluşturma.
  1. const twSwayingBackAnimation = new TWEEN.Tween(currentPosition) ... İlk animasyon tamamlandıktan sonra nesnenin başlangıç konumuna geri dönmesini içeren bir animasyon oluşturma.
  1. twSwayingAnimation.chain(twSwayingBackAnimation); İki animasyonu birbirine bağlayarak ilk animasyon tamamlandığında ikinci animasyonun otomatik olarak başlamasını sağlar.


UseEffect'te animasyon başlatma fonksiyonunu çağırıyoruz.


Player.jsx


Şimdi hareketin gerçekleştiği anı belirlemek gerekiyor. Bu, karakterin yönünün geçerli vektörünü belirleyerek yapılabilir.


Karakter hareketi meydana gelirse animasyonu yenileyeceğiz ve bittiğinde tekrar çalıştıracağız.


Player.jsx


Kod Açıklaması:

  1. const isMoving = yön.uzunluk() > 0; Burada nesnenin hareket durumu kontrol edilir. Yön vektörünün uzunluğu 0'dan büyükse bu, nesnenin bir hareket yönüne sahip olduğu anlamına gelir.
  1. if (isMoving && isSwayingAnimationFinished) { ... } Bu durum, nesne hareket ediyorsa ve "sallanma" animasyonu bitmişse yürütülür.


App bileşeninde ara animasyonunu güncelleyeceğimiz bir useFrame ekleyelim.


Uygulama.jsx


TWEEN.update(), TWEEN.js kitaplığındaki tüm etkin animasyonları günceller. Bu yöntem, tüm animasyonların sorunsuz çalışmasını sağlamak için her animasyon karesinde çağrılır.


Bölüm kodu:

Geri tepme animasyonu

Atışın yapıldığı anı, yani fare tuşuna basıldığı anı tanımlamamız gerekiyor. Bu durumu depolamak için useState'i , silah nesnesine bir referansı depolamak için useRef'i ve fare düğmesine basıp bırakmak için iki olay işleyicisini ekleyelim.


Silah.jsx


Silah.jsx


Silah.jsx


Fare tuşuna basıldığında geri tepme animasyonu uygulayalım. Bu amaçla tween.js kütüphanesini kullanacağız.


Geri tepme kuvveti ve animasyon süresi için sabitler tanımlayalım.


Silah.jsx


Silah kıpırdatma animasyonunda olduğu gibi, geri tepme ve başlangıç pozisyonuna dönüş animasyonu için iki kullanım Durumu durumu ve animasyon bitiş durumu olan bir durum ekliyoruz.


Silah.jsx


Rastgele bir geri tepme animasyonu vektörü elde etmek için işlevler oluşturalım - createdRecoilOffset ve createdNewPositionOfRecoil .


Silah.jsx


Geri tepme animasyonunu başlatmak için bir işlev oluşturun. Ayrıca, her çekimde animasyonun yeniden başlatılması ve yeni bitiş koordinatlarının oluşturulması için "çekim" durumunu bağımlılık olarak belirleyeceğimiz useEffect'i de ekleyeceğiz.


Silah.jsx


Silah.jsx


Ve useFrame'e , ateş etmek için fare tuşunu "basılı tutmak" için bir kontrol ekleyelim, böylece ateşleme animasyonu, tuş bırakılana kadar durmaz.


Silah.jsx


Geri tepme animasyonu


Bölüm kodu

Hareketsizlik sırasında animasyon

Karakter için "hareketsizlik" animasyonunu gerçekleştirin, böylece oyunun "asılı" olduğu hissi oluşmaz.


Bunu yapmak için useState aracılığıyla bazı yeni durumlar ekleyelim.


Player.jsx


Durumdan gelen değerleri kullanmak için "kıpırdatma" animasyonunun başlatılmasını düzeltelim. Buradaki fikir, farklı durumların (yürüme veya durma) animasyon için farklı değerler kullanması ve her seferinde animasyonun ilk olarak başlatılmasıdır.


Player.jsx


Boşta kalma animasyonu


Çözüm

Bu bölümde sahne oluşturma ve karakter hareketlerini uyguladık. Ayrıca bir silah modeli, ateş ederken ve boştayken geri tepme animasyonu ekledik. Bir sonraki bölümde yeni işlevler ekleyerek oyunumuzu geliştirmeye devam edeceğiz.


Burada da yayınlandı.