Gerçek Zamanlı Çok Oyunculu Sanal Gerçeklik Oyunu Nasıl Oluşturulur (Bölüm 1)

Yayınlanan: 2022-03-10
Kısa özet ↬ Sanal gerçeklik, içeriğin bir film ( Life of Pi ), bir oyun ( Beat Sabre ) veya bir sosyal deneyim ( Ready Player One'da gösterildiği gibi) olup olmadığını keşfetmek için yeni ve sürükleyici bir ortamdır. Yeniliğine rağmen, VR, tasarlamak için büyük ölçüde farklı bir araç seti gerektirmez - web oyunu geliştirme, 3D modelleme ve diğerleri için kullandığımız aynı araçların tümü hala uygulanabilir. Bu eğitim, VR geliştirmeye başlamak için web geliştirme konusundaki bilginizden yararlanır.

Bu eğitim serisinde, oyuncuların bir bulmacayı çözmek için işbirliği yapması gereken web tabanlı çok oyunculu bir sanal gerçeklik oyunu oluşturacağız. VR modelleme için A-Frame, cihazlar arası gerçek zamanlı senkronizasyon için MirrorVR ve düşük poli estetik için A-Frame Low Poly kullanacağız. Bu eğitimin sonunda, herkesin oynayabileceği, tamamen işlevsel bir çevrimiçi demoya sahip olacaksınız.

Her oyuncu çiftine bir küre halkası verilir. Amaç, yükseltilmiş ve parlaksa bir kürenin “açık” olduğu tüm küreleri “açmaktır”. Bir küre daha alçak ve loşsa "kapalı"dır. Bununla birlikte, belirli "baskın" küreler komşularını etkiler: durum değiştirirse, komşuları da durum değiştirir. Sadece oyuncu 2 baskın küreleri kontrol edebilirken, sadece oyuncu 1 baskın olmayan küreleri kontrol edebilir. Bu, her iki oyuncuyu da bulmacayı çözmek için işbirliği yapmaya zorlar. Eğitimin bu ilk bölümünde, VR oyunumuz için çevreyi oluşturacak ve tasarım öğelerini ekleyeceğiz.

Bu öğreticideki yedi adım, üç bölüme ayrılmıştır:

  1. Sahneyi Ayarlama (1–2. Adımlar)
  2. Küreler Oluşturma (3–5. Adımlar)
  3. Küreleri Etkileşimli Hale Getirme (6-7. Adımlar)
Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Bu ilk bölüm, açılıp kapanan tıklanabilir bir küre ile sonuçlanacaktır (aşağıda gösterildiği gibi). A-Frame VR ve birkaç A-Frame uzantısı kullanacaksınız.

(Büyük önizleme)

Sahneyi Ayarlama

1. Basit Bir Sahneyle Başlayalım

Başlamak için, basit bir sahneyi bir zeminle nasıl kurabileceğimize bir göz atalım:

Basit bir sahne oluşturma
Basit bir sahne oluşturma (Büyük önizleme)

Aşağıdaki ilk üç talimat önceki makalemden alıntılanmıştır. Tek bir statik HTML sayfası olan bir web sitesi kurarak başlayacaksınız. Bu, masaüstünüzden kod yazmanıza ve otomatik olarak web'e dağıtmanıza olanak tanır. Dağıtılan web sitesi daha sonra cep telefonunuza yüklenebilir ve bir VR kulaklığının içine yerleştirilebilir. Alternatif olarak, dağıtılan web sitesi bağımsız bir VR başlığı ile yüklenebilir.

glitch.com'a giderek başlayın. Ardından, aşağıdakileri yapın:

  1. Sağ üstteki “Yeni Proje”ye tıklayın,
  2. Açılır menüden "merhaba-web sayfası"na tıklayın,
  3. Ardından, sol kenar çubuğundaki index.html'ye tıklayın. Bunu “editörünüz” olarak anacağız.

Şimdi, varsayılan bir HTML dosyasıyla aşağıdaki Glitch ekranını görmelisiniz.

Glitch projesi: index.html dosyası
Glitch projesi: index.html dosyası (Büyük önizleme)

Yukarıdaki bağlantılı eğitimde olduğu gibi, mevcut index.html dosyasındaki mevcut tüm kodu silerek başlayın. Ardından, A-Frame VR kullanarak temel bir webVR projesi için aşağıdakini yazın. Bu, A-Frame'in varsayılan aydınlatmasını ve kamerasını kullanarak boş bir sahne oluşturur.

 <!DOCTYPE html> <html> <head> <title>Lightful</title> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> </a-scene> </body> </html>

Kamerayı ayakta duran yüksekliğe kaldırın. A-Frame VR önerilerine göre (Github sorunu), kamerayı yeni bir varlıkla sarın ve doğrudan kamera yerine ana varlığı taşıyın. 8. ve 9. satırlardaki a-scene etiketlerinizin arasına aşağıdakileri ekleyin.

 <!-- Camera! --> <a-entity position="0 3 0"> <a-camera wasd-controls look-controls></a-camera> </a-entity>

Ardından, a-box kullanarak zemini belirtmek için büyük bir kutu ekleyin. Bunu, önceki talimattaki gibi doğrudan kameranızın altına yerleştirin.

 <!-- Action! --> <a-box shadow width="75" height="0.1" depth="75" position="0 -1 0" color="#222"></a-box>

index.html dosyanız şimdi aşağıdakiyle tam olarak eşleşmelidir. Tam kaynak kodunu Github'da burada bulabilirsiniz.

 <html> <head> <title>Lightful</title> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> <!-- Camera! --> <a-entity position="0 3 0"> <a-camera wasd-controls look-controls></a-camera> </a-entity> <!-- Action! --> <a-box shadow width="75" height="0.1" depth="75" position="0 -1 0" color="#222"></a-box> </a-scene> </body> </html>

Bu, kurulumu tamamlar. Ardından, daha gizemli bir atmosfer için aydınlatmayı özelleştireceğiz.

2. Atmosfer Ekleyin

Bu adımda sis ve özel aydınlatma ayarlayacağız.

Karanlık bir ruh hali ile basit bir sahnenin önizlemesi
Karanlık bir ruh hali olan basit bir sahnenin önizlemesi (Büyük önizleme)

Uzaktaki nesneleri bizim için gizleyecek bir sis ekleyin. 8. satırdaki a-scene etiketini değiştirin. Burada, uzak bir ufuk efekti vererek zeminin kenarlarını hızla gizleyen karanlık bir sis ekleyeceğiz.

 <a-scene fog="type: linear; color: #111; near:10; far:15"></a-scene>

Koyu gri #111 , 10'luk bir mesafeden 15'lik bir mesafeye doğrusal olarak kaybolur. 15 birimden daha uzak tüm nesneler tamamen gizlenir ve 10 birimden daha az mesafedeki tüm nesneler tamamen görülebilir. Aradaki herhangi bir nesne kısmen gizlenmiştir.

Oyun içindeki nesneleri aydınlatmak için bir ortam ışığı ve daha sonra ekleyeceğiniz yansıtıcı yüzeyleri vurgulamak için tek yönlü ışık ekleyin. Bunu, önceki talimatta değiştirdiğiniz a-scene etiketinin hemen sonrasına yerleştirin.

 <!-- Lights! --> <a-light type="directional" castshadow="true" intensity="0.5" color="#FFF" position="2 5 0"></a-light> <a-light intensity="0.1" type="ambient" position="1 1 1" color="#FFF"></a-light>

Önceki talimattaki ışıkların hemen altına karanlık bir gökyüzü ekleyin. Koyu gri #111 uzaktaki sisinkiyle eşleştiğine dikkat edin.

 <a-sky color="#111"></a-sky>

Bu, ruh halindeki temel değişiklikleri ve daha geniş anlamda sahne düzenini tamamlar. Kodunuzun Github'daki 2. Adımın kaynak koduyla tam olarak eşleşip eşleşmediğini kontrol edin. Ardından, bir düşük poli küre ekleyeceğiz ve kürenin estetiğini özelleştirmeye başlayacağız.

Küreler Yaratmak

3. Düşük Poli Küre Oluşturun

Bu adımda aşağıdaki resimdeki gibi dönen, yansıtıcı bir küre oluşturacağız. Küre, yansıtıcı malzeme önermek için birkaç hile ile iki stilize düşük poli küreden oluşur.

Dönen, yansıtıcı küre
(Büyük önizleme)

Düşük poli kitaplığı head etiketinize içe aktararak başlayın. Aşağıdakileri 4. ve 5. satırlar arasına yerleştirin.

 <script src="https://cdn.jsdelivr.net/gh/alvinwan/[email protected]/dist/aframe-low-poly.min.js"></script>

Bir atlıkarınca, sarmalayıcı ve küre kapsayıcı oluşturun. Döngü birden fazla küre içerecek, wrapper her küreyi ayrı ayrı döndürmeden tüm küreleri bir merkez carousel etrafında döndürmemize izin verecek ve container - adından da anlaşılacağı gibi - tüm küre bileşenlerini içerecek.

 <a-entity> <a-entity rotation="0 90 0" class="wrapper" position="0 0 0"> <a-entity class="container" position="8 3 0" scale="1 1 1"> <!-- place orb here --> </a-entity> </a-entity> </a-entity>

Küre kabının içine kürenin kendisini ekleyin: bir küre biraz yarı saydam ve kayıktır ve diğeri tamamen katıdır. Birleştirilmiş iki yansıtıcı yüzeyleri taklit eder.

 <a-entity class="orb" data-> <lp-sphere seed="0" shadow max-amplitude="1 1 1" position="-0.5 0 -0.5"></lp-sphere> <lp-sphere seed="0" shadow max-amplitude="1 1 1" rotation="0 45 45" opacity="0.5" position="-0.5 0 -0.5"></lp-sphere> </a-entity>

Son olarak, son .orb öğesinin içindeki lp-sphere hemen sonrasına aşağıdaki a-animation etiketini ekleyerek küreyi süresiz olarak döndürün.

 <a-animation attribute="rotation" repeat="indefinite" from="0 0 0" to="0 360 0" dur="5000"></a-animation>

Küre sarmalayıcılar ve kürenin kendisi için kaynak kodunuz aşağıdakilerle tam olarak eşleşmelidir.

 <a-entity> <a-entity rotation="0 90 0" class="wrapper" position="0 0 0"> <a-entity class="container" position="8 3 0" scale="1 1 1"> <a-entity class="orb" data-> <lp-sphere seed="0" shadow max-amplitude="1 1 1" position="-0.5 0 -0.5"></lp-sphere> <lp-sphere seed="0" shadow max-amplitude="1 1 1" rotation="0 45 45" opacity="0.5" position="-0.5 0 -0.5"></lp-sphere> <a-animation attribute="rotation" repeat="indefinite" from="0 0 0" to="0 360 0" dur="5000"></a-animation> </a-entity> </a-entity> </a-entity> </a-entity>

Kaynak kodunuzun Github'daki 3. adım için tam kaynak koduyla eşleştiğini kontrol edin. Önizlemeniz şimdi aşağıdakilerle eşleşmelidir.

Dönen, yansıtıcı küre
(Büyük önizleme)

Ardından, altın rengi bir ton için küreye daha fazla aydınlatma ekleyeceğiz.

4. Küreyi Aydınlatın

Bu adımda bir renkli ve bir beyaz olmak üzere iki ışık ekleyeceğiz. Bu, aşağıdaki etkiyi üretir.

Nokta ışıklarıyla aydınlatılan küre
(Büyük önizleme)

Nesneyi aşağıdan aydınlatmak için beyaz ışık ekleyerek başlayın. Nokta ışık kullanacağız. #orb0 hemen önce, ancak #container-orb0 içinde, aşağıdaki ofset nokta ışığını ekleyin.

 <a-entity position="-2 -1 0"> <a-light distance="8" type="point" color="#FFF" intensity="0.8"></a-light> </a-entity>

Önizlemenizde aşağıdakileri göreceksiniz.

Küre beyaz nokta ışığıyla aydınlatıldı
(Büyük önizleme)

Varsayılan olarak, ışıklar mesafe ile azalmaz. distance="8" ekleyerek, nokta ışığının tüm sahneyi aydınlatmasını önlemek için ışığın 8 birimlik bir mesafe ile tamamen azalmasını sağlıyoruz. Ardından, altın ışığı ekleyin. Aşağıdakini doğrudan son ışığın üzerine ekleyin.

 <a-light class="light-orb" distance="8" type="point" color="#f90" intensity="1"></a-light>

Kodunuzun, 4. adımın kaynak koduyla tam olarak eşleşip eşleşmediğini kontrol edin. Önizlemeniz şimdi aşağıdakilerle eşleşecek.

Nokta ışıklarıyla aydınlatılan küre
(Büyük önizleme)

Ardından, küre üzerinde son estetik değişikliğinizi yapacak ve dönen halkalar ekleyeceksiniz.

5. Yüzük Ekle

Bu adımda, aşağıda gösterildiği gibi son küreyi üreteceksiniz.

Birden çok halkalı altın küre
(Büyük önizleme)

#container-orb0 , #orb0 orb0'dan hemen önce bir halka ekleyin.

 <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="1.9" radius-outer="2" opacity="0.25"></a-ring>

Halkanın kendisinin renk içermediğine dikkat edin, çünkü renk, önceki adımda nokta ışığı tarafından emilecektir. Ayrıca, material="side:double" önemlidir, çünkü onsuz yüzüğün arka tarafı işlenmeyecektir; bu, halkanın dönüşünün yarısı boyunca kaybolacağı anlamına gelir.

Ancak, yalnızca yukarıdaki kodu içeren önizleme farklı görünmeyecektir. Bunun nedeni, halkanın şu anda ekrana dik olmasıdır. Böylece halkanın sadece (0 kalınlığa sahip olan) "yan"ı görünür. Aşağıdaki animasyonu önceki talimattaki a-ring etiketleri arasına yerleştirin.

 <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 0 0" to="0 360 0" dur="8000"></a-animation>

Önizlemeniz şimdi aşağıdakilerle eşleşmelidir:

Yüzük ile altın küre
(Büyük önizleme)

Farklı dönüş eksenleri, hızları ve boyutları ile değişken sayıda halka oluşturun. Aşağıdaki örnek halkaları kullanabilirsiniz. Herhangi bir yeni halka, son a-ring altına yerleştirilmelidir.

 <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="2.4" radius-outer="2.5" opacity="0.25"> <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 45 0" to="360 45 0" dur="8000"></a-animation> </a-ring> <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="1.4" radius-outer="1.5" opacity="0.25"> <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 -60 0" to="-360 -60 0" dur="3000"></a-animation> </a-ring>

Önizlemeniz şimdi aşağıdakilerle eşleşecek.

Birden çok halkalı altın küre
(Büyük önizleme)

Kodunuzun Github'daki 5. adımdaki kaynak kodla eşleşip eşleşmediğini kontrol edin. Bu, küre için dekoru tamamlar. Küre bittiğinde, küreye etkileşim ekleyeceğiz. Bir sonraki adımda, tıklanabilir nesnelere işaret edildiğinde tıklama animasyonu ile özellikle görünür bir imleç ekleyeceğiz.

Küreleri Etkileşimli Hale Getirmek

6. İmleç Ekle

Bu adımda, tıklanabilir nesneleri tetikleyebilecek beyaz bir imleç ekleyeceğiz. İmleç aşağıda resmedilmiştir.

küreye tıklamak
(Büyük önizleme)

a-camera etiketinizde aşağıdaki varlığı ekleyin. fuse özelliği, bu varlığın tıklama olaylarını tetikleyebilmesini sağlar. raycaster niteliği, tıklanabilir nesnelerin ne sıklıkta ve ne kadar kontrol edileceğini belirler. objects özelliği, hangi varlıkların tıklanabilir olduğunu belirlemek için bir seçiciyi kabul eder. Bu durumda, clickable sınıfın tüm nesneleri tıklanabilir.

 <a-entity cursor="fuse: true; fuseTimeout: 250" position="0 0 -1" geometry="primitive: ring; radiusInner: 0.03; radiusOuter: 0.04" material="color: white; shader: flat; opacity: 0.5" scale="0.5 0.5 0.5" raycaster="far: 20; interval: 1000; objects: .clickable"> <!-- Place cursor animation here --> </a-entity>

Ardından, estetik için imleç animasyonu ve ekstra bir halka ekleyin. Aşağıdakileri yukarıdaki varlık imleci nesnesinin içine yerleştirin. Bu, tıklamaların görünür olması için imleç nesnesine animasyon ekler.

 <a-circle radius="0.01" color="#FFF" opacity="0.5" material="shader: flat"></a-circle> <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="backwards" from="1 1 1" to="0.2 0.2 0.2" dur="250"></a-animation>

Ardından, aşağıdakiyle eşleşmesi için clickable sınıfı #orb0 ekleyin.

 <a-entity class="orb clickable" data->

Kodunuzun Github'daki 6. Adımın kaynak koduyla eşleşip eşleşmediğini kontrol edin. Önizlemenizde, tıklama animasyonunu çalışırken görmek için imlecinizi kürenin üzerine sürükleyin. Bu aşağıda resmedilmiştir.

küreye tıklamak
(Büyük önizleme)

Küre kabına değil, kürenin kendisine tıklanabilir özniteliğin eklendiğini unutmayın. Bu, halkaların tıklanabilir nesneler haline gelmesini önlemek içindir. Bu şekilde, kullanıcının küreyi oluşturan kürelere tıklaması gerekir.

Bu bölümün son adımında, kürenin açık ve kapalı durumlarını kontrol etmek için animasyon ekleyeceksiniz.

7. Küre Durumları Ekle

Bu adımda, küreyi tıklamayla kapalı duruma girip çıkaracaksınız. Bu aşağıda resmedilmiştir.

Tıklamalara yanıt veren etkileşimli küre
(Büyük önizleme)

Başlamak için, küreyi küçültecek ve yere indireceksiniz. #orb0'dan hemen sonra #orb0 #container-orb0 a-animation etiketleri ekleyin. Her iki animasyon da bir tıklama ile tetiklenir ve aynı hareket hızı işlevini paylaşır ease-elastic .

 <a-animation class="animation-scale" easing="ease-elastic" begin="click" attribute="scale" from="0.5 0.5 0.5" to="1 1 1" direction="alternate" dur="2000"></a-animation> <a-animation class="animation-position" easing="ease-elastic" begin="click" attribute="position" from="8 0.5 0" to="8 3 0" direction="alternate" dur="2000"></a-animation>

Kapalı durumu daha da vurgulamak için, küre kapalıyken altın nokta ışığını kaldıracağız. Ancak, kürenin ışıkları küre nesnesinin dışına yerleştirilir. Böylece küre tıklandığında ışıklara tıklama olayı geçmez. Bu sorunu aşmak için, click olayını ışığa geçirmek için biraz hafif Javascript kullanacağız. Aşağıdaki animasyon etiketini #light-orb0 . Işık, özel bir switch olayı tarafından tetiklenir.

 <a-animation class="animation-intensity" begin="switch" attribute="intensity" from="0" to="1" direction="alternate"></a-animation>

Ardından, #container-orb0 öğesine aşağıdaki tıklama olay dinleyicisini ekleyin. Bu, tıklamaları küre ışıklarına iletecektir.

 <a-entity ...>

Kodunuzun Github'daki 7. Adımın kaynak koduyla eşleşip eşleşmediğini kontrol edin. Son olarak, önizlemenizi yukarı çekin ve kapalı ve açık durumlar arasında geçiş yapmak için imleci kürenin üzerinde ve dışında hareket ettirin. Bu aşağıda resmedilmiştir.

Tıklamalara yanıt veren etkileşimli küre
(Büyük önizleme)

Bu, kürenin etkileşimini sona erdirir. Oyuncu artık kendi kendini açıklayan açık ve kapalı durumlarla küreleri istediği zaman açıp kapatabilir.

Çözüm

Bu öğreticide, açık ve kapalı durumları olan ve VR kulaklık dostu bir imleç tıklamasıyla değiştirilebilen basit bir küre oluşturdunuz. Bir dizi farklı aydınlatma tekniği ve animasyonla iki durumu ayırt edebildiniz. Bu, küreler için sanal gerçeklik tasarım öğelerini tamamlar. Eğitimin bir sonraki bölümünde, küreleri dinamik olarak dolduracağız, oyun mekanikleri ekleyeceğiz ve bir çift oyuncu arasında bir iletişim protokolü kuracağız.