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, teknolojisini kullanarak tabanlı 3D grafikler oluşturmaya yönelik güçlü bir araç olan kitaplığıdır. React Three.js React Three Fiber React Three Fiber yığını hakkında web üzerinde 3D grafikler oluşturmak için yapısını ve ilkelerini kullanan, üzerinde bir sarmalayıcıdır. Bu yığın, geliştiricilerin gücünü rahatlığı ve esnekliğiyle birleştirmesine olanak tanıyarak uygulama oluşturma sürecini daha sezgisel ve organize hale getirir. React Three Fiber, React'in Three.js Three.js'nin React'ın temelinde, bir sahnede yarattığınız her şeyin bir 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 React temel avantajlarından biri ekosistemiyle entegrasyon kolaylığıdır. Bu kütüphaneyi kullanırken diğer araçları hala kolayca entegre edilebilir. React Three Fiber'in React React Web-GameDev'in Uygunluğu son yıllarda basit 2D 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-GameDev Flash 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. , , ve 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. Chrome Firefox Edge diğerleri Tarayıcı tabanlı oyunların gelişimini hızlandıran temel araçlardan biri . 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 , doğrudan tarayıcıda etkileyici web uygulamaları oluşturmaya yönelik yeni olanaklar sunar. WebGL'dir WebGL 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 https://codesandbox.io/p/github/JI0PATA/fps-game?embedable=true depo GitHub'daki Şimdi başlayalım! Projeyi ayarlama ve paketleri yükleme Öncelikle bir proje şablonuna ihtiyacımız olacak. Öyleyse onu yükleyerek başlayalım. React npm create vite@latest kütüphanesini seçin; React seçin. JavaScript'i 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 dosyasına sayfada kapsam olarak görüntülenecek bir div öğesi ekleyin. Bir bileşeni ekleyin ve kameranın görüş alanını ayarlayın. bileşeninin içine bileşenini yerleştirin. Main.jsx Canvas Canvas Uygulama 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 stiller ekleyelim. index.css'ye bileşenine, oyun sahnemizde arka plan olarak gökyüzü şeklinde görüntülenecek bir bileşeni ekliyoruz. Uygulama Gökyüzü Bölüm kodu Zemin yüzeyi Bir bileşeni oluşturalım ve onu bileşenine yerleştirelim. Ground App 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'da Malzeme rengi olarak griyi belirtmemize rağmen düzlem tamamen siyah görünüyor. 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 ışık kaynağını ekleyelim. Bir parametre olarak ışığın yoğunluğunu ayarlayın. ambientLight 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. klasörüne dokulu bir PNG görüntüsü ekleyin. Varlıklar Sahneye bir doku yüklemek için paketindeki 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. @react- three/drei useTexture Bölüm kodu Kamera hareketi paketindeki bileşenini kullanarak, fareyi hareket ettirdiğinizde hareket etmeyecek, ancak kameranın sahnedeki konumunu değiştirecek şekilde imleci ekrana sabitleyin. @react-third/drei PointerLockControls bileşeni için küçük bir düzenleme yapalım. Ground Bölüm kodu Fizik ekleme Netlik sağlamak için sahneye basit bir küp ekleyelim. <mesh position={[0, 3, -5]}> <boxGeometry /> </mesh> Şu anda sadece boşlukta asılı duruyor. Sahneye "fizik" eklemek için paketindeki bileşenini kullanın. Parametre olarak, yerçekimi kuvvetlerini eksenler boyunca ayarladığımız yerçekimi alanını yapılandırın. @react-third/rapier Fizik <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 paketindeki bileşenine sarmamız gerekiyor. @react- three/rapier RigidBody Bundan sonra sayfa her yeniden yüklendiğinde küpün yerçekiminin etkisiyle aşağıya düştüğünü hemen göreceğiz. 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 bileşenine geri dönelim ve zemin yüzeyinin üzerine sarmalayıcı olarak bir bileşeni ekleyelim. Ground RigidBody Artık düşerken küp gerçek bir fiziksel nesne gibi yerde kalıyor. Bölüm kodu Bir karakteri fizik kanunlarına tabi kılmak Sahnedeki karakteri kontrol edecek bileşeni oluşturalım. Player 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 bileşenini ekliyoruz. Ve karakteri kapsül şeklinde yapalım. RigidBody bileşenini Fizik bileşeninin içine yerleştirin. Player Artık karakterimiz sahneye çıkmıştır. Bölüm kodu Bir karakteri taşıma - kanca oluşturma Karakter tuşları kullanılarak kontrol edilecek ve kullanılarak atlanacaktır. WASD Ara Çubuğu Kendi reaksiyon kancamızla karakteri hareket ettirme mantığını uyguluyoruz. Bir dosyası oluşturalım ve buraya yeni bir fonksiyonu ekleyelim. hooks.js usePersonControls {"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. Bölüm kodu Bir karakteri taşıma - kanca uygulama kancasını uyguladıktan sonra, karakteri kontrol ederken kullanılmalıdır. bileşeninde hareket durumu izlemeyi ekleyeceğiz ve karakterin hareket yönünün vektörünü güncelleyeceğiz. usePersonControls Oyuncu Ayrıca hareket yönlerinin durumlarını saklayacak değişkenleri de tanımlayacağız. Karakterin konumunu güncellemek için paketi tarafından sağlanan kullanalım. Bu kanca, benzer şekilde çalışır ve işlevin gövdesini saniyede yaklaşık 60 kez çalıştırır. @react- three/fiber Frame'i requestAnimationFrame'e Kod Açıklaması: Oynatıcı nesnesi için bir bağlantı oluşturun. Bu bağlantı, sahnedeki oynatıcı nesnesi ile doğrudan etkileşime izin verecektir. 1. const playerRef = useRef(); 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. 2. const { ileri, geri, sol, sağ, atlama } = usePersonControls(); Kanca, animasyonun her karesinde çağrılır. Bu kancanın içinde oyuncunun konumu ve doğrusal hızı güncellenir. 3. useFrame((durum) => { ... }); Bir oynatıcı nesnesinin varlığını kontrol eder. Oynatıcı nesnesi yoksa işlev, hataları önlemek için yürütmeyi durduracaktır. 4. if (!playerRef.current) geri dönerse; Oyuncunun mevcut doğrusal hızını alın. 5. sabit hız = playerRef.current.linvel(); Basılan düğmelere göre ileri/geri hareket vektörünü ayarlayın. 6. frontVector.set(0, 0, geri - ileri); Sol/sağ hareket vektörünü ayarlayın. 7. sideVector.set(sol - sağ, 0, 0); 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. 8. Direction.subVectors(frontVector, sideVector).normalize().multiplyScalar(MOVE_SPEED); 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. 9. playerRef.current.wakeUp(); 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). 10. playerRef.current.setLinvel({ x: yön.x, y: hız.y, z: yön.z }); Sonuç olarak 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. WASD Bölüm kodu Bir karakteri taşıma - atlama Atlamayı uygulamak için ve 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. @dimforge/rapier3d-compat @react-third/rapier 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. Oyuncu Kod Açıklaması: fizik motoru sahnesine erişim elde ediliyor. Tüm fiziksel nesneleri içerir ve etkileşimlerini yönetir. const dünyası = rapier.world; Rapier 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". const ray = world.castRay(new RAPIER.Ray(playerRef.current.translation(), { x: 0, y: -1, z: 0 })); Oyuncunun yerde olup olmadığı kontrol edilir: const grounded = ray && ray.collider && Math.abs(ray.toi) <= 1.5; - yaratılıp yaratılmadığı; ışın ışının - ışının olay yerindeki herhangi bir nesneyle çarpışıp çarpışmadığı; ray.collider - ışı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. Math.abs(ray.toi) 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 bileşenini değiştirmeniz gerekir. Zemin Sahneyi daha iyi görebilmek için kamerayı biraz daha yukarı kaldıralım. Bölüm kodu İlk taahhüt İkinci taahhüt 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 eklememiz gerekiyor. applicationEuler'ı Kod Açıklaması: yöntemi, belirtilen Euler açılarına dayalı olarak bir vektöre rotasyon uygular. Bu durumda kamera döndürme 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. ApplyEuler yön boyutunu biraz ayarlayalım ve küpe göre daha uzun hale getirelim, boyutunu artıralım ve "atlama" mantığını düzeltelim. Player'ın CapsuleCollider'ın Bölüm kodu İlk taahhüt İkinci taahhüt 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 dosyasını oluşturun. cubes.json [ [0, 0, -7], [2, 0, -7], [4, 0, -7], [6, 0, -7], [8, 0, -7], [10, 0, -7] ] dosyasında, döngü halinde küpler oluşturacak bir bileşeni oluşturun. Ve bileşeni doğrudan oluşturulan nesne olacaktır. Cube.jsx Küpler Cube 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 bileşenini önceki tek küpü silerek bileşenine ekleyelim. Küpler Uygulama 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 alalım. şunu ele 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 eklenti paketini kurmamız gerekecek. gltf-pipeline npm i -D gltf-pipeline paketini kullanarak modeli 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 klasörü belirtiyoruz. gltf-pipeline GLTF formatından GLB formatına ortak 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. geliştiricilerinin kullanalım. @react- three/fiber resmi kaynağını Dönüştürücüye gitmek, dönüştürülen dosyasını yüklemenizi gerektirecektir. silah.glb Sürükle ve bırak veya Explorer aramasını kullanarak bu dosyayı bulun ve indirin. Dönüştürücüde, kodunu projemize yeni bir dosyasına aktaracağımız, bileşenin adını dosyayla aynı adla değiştireceğimiz, oluşturulan reaksiyon bileşenini göreceğiz. WeaponModel.jsx Bölüm kodu Silah modelinin sahnede sergilenmesi Şimdi oluşturulan modeli sahneye aktaralım. dosyasına bileşenini ekleyin. App.jsx WeaponModel Bölüm kodu Gölgeler ekleme Sahnemizin bu noktasında nesnelerin hiçbiri gölge düşürmüyor. Sahnede etkinleştirmek için bileşenine niteliğini eklemeniz gerekir. gölgeleri Canvas gölgeler Daha sonra yeni bir ışık kaynağı eklememiz gerekiyor. Sahnede zaten olmasına rağmen, yönlü bir ışık huzmesine sahip olmadığından nesneler için gölge oluşturamaz. O halde adında yeni bir ışık kaynağı ekleyelim ve onu yapılandıralım. " " gölge modunu etkinleştirme özelliği . Bu nesnenin diğer nesnelere gölge düşürebileceğini belirten bu parametrenin eklenmesidir. ambientLight directionLight Yayınlama castShadow'dur Daha sonra bileşenine bir başka özellik olan ekleyelim, bu da sahnedeki bileşenin gölgeleri kendi üzerinde alıp görüntüleyebilmesi anlamına gelir. Ground takeShadow'u Sahnedeki diğer nesnelere de benzer özellikler eklenmelidir: küpler ve oynatıcı. Küpler için ve ekleyeceğiz, çünkü hem gölge oluşturabilir hem de gölge alabilirler ve oyuncu için yalnızca ekleyeceğiz. castShadow getShadow'u castShadow'u için ekleyelim. Player castShadow'u için ve ekleyin. Cube castShadow'u getShadow'u 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. Bunun nedeni, varsayılan olarak kameranın, 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 niteliklerini ekleyerek bileşenini kullanabiliriz. Bu nitelikleri ekledikten sonra gölge biraz bulanıklaşacaktır. Kaliteyi artırmak için özelliğini ekleyeceğiz. DirectionLight'tan gölge-kamera-(üst, alt, sol, sağ) directionLight shadow-mapSize 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 bileşeni oluşturun. Silah import {WeaponModel} from "./WeaponModel.jsx"; export const Weapon = (props) => { return ( <group {...props}> <WeaponModel /> </group> ); } Bu bileşeni karakterin ile aynı seviyeye yerleştirelim ve kancasında kameradan gelen değerlerin konumuna göre konumu ve dönüş açısını ayarlayacağız. RigidBody'si useFrame 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 kütüphanesini kullanacağız. tween.js bileşeni, kancası aracılığıyla ona bir referans ekleyebilmeniz için bir grup etiketine sarılacaktır. Silah useRef Animasyonu kaydetmek için biraz ekleyelim. useState Animasyonu başlatmak için bir fonksiyon oluşturalım. Kod Açıklaması: Geçerli konumundan yeni bir konuma "sallanan" bir nesnenin animasyonunu oluşturma. const twSwayingAnimation = new TWEEN.Tween(currentPosition) ... İlk animasyon tamamlandıktan sonra nesnenin başlangıç konumuna geri dönmesini içeren bir animasyon oluşturma. const twSwayingBackAnimation = new TWEEN.Tween(currentPosition) ... İki animasyonu birbirine bağlayarak ilk animasyon tamamlandığında ikinci animasyonun otomatik olarak başlamasını sağlar. twSwayingAnimation.chain(twSwayingBackAnimation); animasyon başlatma fonksiyonunu çağırıyoruz. UseEffect'te Ş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. Kod Açıklaması: 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. const isMoving = yön.uzunluk() > 0; Bu durum, nesne hareket ediyorsa ve "sallanma" animasyonu bitmişse yürütülür. if (isMoving && isSwayingAnimationFinished) { ... } bileşeninde ara animasyonunu güncelleyeceğimiz bir ekleyelim. App useFrame 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. TWEEN.update(), TWEEN.js Bölüm kodu: İlk taahhüt İkinci taahhüt Geri tepme animasyonu Atışın yapıldığı anı, yani fare tuşuna basıldığı anı tanımlamamız gerekiyor. Bu durumu depolamak için , silah nesnesine bir referansı depolamak için ve fare düğmesine basıp bırakmak için iki olay işleyicisini ekleyelim. useState'i useRef'i Fare tuşuna basıldığında geri tepme animasyonu uygulayalım. Bu amaçla kütüphanesini kullanacağız. tween.js Geri tepme kuvveti ve animasyon süresi için sabitler tanımlayalım. 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. Rastgele bir geri tepme animasyonu vektörü elde etmek için işlevler oluşturalım - ve . createdRecoilOffset createdNewPositionOfRecoil 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 de ekleyeceğiz. useEffect'i Ve , 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. useFrame'e 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 aracılığıyla bazı yeni durumlar ekleyelim. useState 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. Çö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. da yayınlandı. Burada