Stavební Karton Dungeon S A-rámem

Cardboard Dungeon je webové prostředí pro procházení dungeonů navržené pro použití s ​​Google Cardboard a napsané pomocí rámce virtuální reality společnosti Mozilla, A-Frame.

V této případové studii budu diskutovat o klíčových výzvách, kterým jsem čelil při vývoji Cardboard Dungeon , mé zkušenosti s A-Frame a některé lekce, které jsem se naučil, když jsem poprvé přistupoval k virtuální realitě.

Začínáme s A-Frame

Narazil jsem na A-Frame a hledal jsem snadný způsob, jak začít s vývojem VR. A-Frame mě zaujal, protože tak přirozeně zapadá do konceptů vývoje webu, na které jsem zvyklý. Schopnost umístit entity do scény pomocí čistého značkování je extrémně výkonná a nabízí velmi nízkou bariéru vstupu. Pomáhá také, že dokumentace k A-Frame je čistá a stručná – něco, co je pro mě jako vývojáře, který se rozhodl používat kód/knihovny třetích stran, tak důležité.

Upřímně mě překvapilo, jak robustní A-Frame je. Většina překážek, kterým jsem čelil, souvisela se zvládáním výzev specifických pro VR.

Stavba podzemí

Cardboard Dungeon začalo jako rychlý způsob, jak otestovat některé funkce A-Frame. Spíše než vytvořit celý dungeon předem, můj koncept byl mít pevný počet místností definujících vykreslovatelnou oblast kolem přehrávače. Tyto místnosti by byly vykresleny na základě dat ze souboru JSON. To by snížilo počet entit v rámci DOM a umožnilo by extrémně velký dungeon, pokud bych si to přál, s malým nebo žádným dopadem na výkon.

Místnost je jednoduchá a skládá se vždy až ze čtyř stěn, podlahy a stropu. Data JSON definují, která z nich by měla být vykreslena pro každou místnost. Také jsem se rozhodl pro jednoduchý mřížkový systém pro definování virtuální polohy místnosti – pomocí (0,0,0) být výchozím bodem hráče.

Zpočátku jsem injektoval nové entity A-Frame pokaždé, když hráč spustil pohyb. Nicméně při rozhovoru s týmem A-Frame jsem byl upozorněn na „viditelnou“ složku. Rozhodl jsem se inicializovat každý vykreslený prostor předem a poté přepnout „viditelnou“ komponentu pro každou místnost, když hráč vstoupí.

// Called once during scene initialization.
Container.prototype.init = function () {
  var entity = document.createElement('a-entity');
  entity.className = 'top';
  entity.setAttribute('mixin','wall top');
  entity.setAttribute('visible', 'false');
  entity.setAttribute('position', {
    x: this.position_multipliers.x,
    y: (4 + this.position_multipliers.y),
    z: this.position_multipliers.z
  });
  document.getElementById(this.target).appendChild(entity);
  // …
};

// Called whenever the player triggers movement.
Container.prototype.render = function () {
  // Set the `visible` component on the entities for this container.
  var container = document.getElementById(this.target);
  if (this.room) {
    setAttributeForClass(container, 'top', 'visible', (this.room.data.top ? this.room.data.top : 'false'));
    setAttributeForClass(container, 'bottom', 'visible', (this.room.data.bottom ? this.room.data.bottom : 'false'));
    setAttributeForClass(container, 'left', 'visible', (this.room.data.left ? this.room.data.left : 'false'));
    setAttributeForClass(container, 'right', 'visible', (this.room.data.right ? this.room.data.right : 'false'));
    setAttributeForClass(container, 'back', 'visible', (this.room.data.back ? this.room.data.back : 'false'));
    setAttributeForClass(container, 'front', 'visible', (this.room.data.front ? this.room.data.front : 'false'));
  }
  // …
};

function setAttributeForClass (parent, class_name, attribute, value) {
  var elements = parent.getElementsByClassName(class_name);
  for (var i = 0; i < elements.length; i++) {
    elements[i].setAttribute(attribute, value);
  }
}

Nejprve jsem vykresloval oblast 3×3 kolem přehrávače, ale zvýšil jsem ji na 3×3×3, abych umožnil vertikální procházení. Také jsem to rozšířil na 2 čtverce na sever, jih, východ a západ, abych pomohl s iluzí vzdálenosti.

Lekce VR č. 1:Měřítko

Měřítko na obrazovce se v náhlavní soupravě dobře nepřevádí do měřítka. Na obrazovce mohou výšky vypadat dobře, ale připevnění náhlavní soupravy může drasticky změnit hráčovo vnímání měřítka. Toto je stále nenápadně přítomno v Cardboard Dungeon , zejména při vertikálním přecházení tak, že se stěny mohou zdát vyšší, než bylo zamýšleno. Bylo důležité často testovat zkušenosti s náhlavní soupravou.

Procházení

Procházení map bylo jednou z prvních věcí, které jsem potřeboval vyřešit. Jako všechno ve VR to vyžadovalo podstatnou iteraci.

Zpočátku jsem používal čtverce na zemi (S, E, S, W) ke spuštění pohybu hráče. To fungovalo dobře a tak jsem to iteroval, abych poskytl další ovládací prvky pro vertikální procházení. Udělal jsem tyto kontextově citlivé, takže možnost vertikálního procházení se objevila pouze v případě potřeby. To však vedlo ke spoustě rozhlížení a spoléhání se na to, že hráč rozpozná ovládací prvky.

lekce VR č. 2:Napětí

Umístění běžných interakcí mimo zorné pole hráče vytváří nepříjemný zážitek. Musíte se dívat na zem, abyste vyvolali pohyb, znamená neustále naklánět hlavu dopředu a dozadu. Umístění této interakce do blízkosti přirozené klidové polohy pohledu hráče umožňuje mnohem pohodlnější zážitek.

Mým konečným řešením proto bylo využít teleportačního mechanika. Hráč se jednoduše podívá na jakoukoli modrou kouli, aby se přesunul na toto místo, bez ohledu na to, zda je místnost v nižším nebo vyšším patře. Rozhodl jsem se to omezit na jeden čtverec dungeonu kolem hráče, abych si zachoval pocit z průzkumu.

function move (dom_element) {
  // Fetch the current and target room ids.
  var current_room_key_array = containers.center.room_id.split(',');
  var container_key = dom_element.parentElement.getAttribute('id');
  var target_room_key_array = containers[container_key].room_id.split(',');

  // Calculate the offsets.
  var offset_x = parseInt(target_room_key_array[0], 10) - parseInt(current_room_key_array[0], 10);
  var offset_y = parseInt(target_room_key_array[1], 10) - parseInt(current_room_key_array[1], 10);
  var offset_z = parseInt(target_room_key_array[2], 10) - parseInt(current_room_key_array[2], 10);

  // Apply to each room.
  Object.keys(containers).forEach(function (key) {
    var container = containers[key];
    var room_key_array = container.room_id.split(',');
    room_key_array[0] = parseInt(room_key_array[0], 10) + offset_x;
    room_key_array[1] = parseInt(room_key_array[1], 10) + offset_y;
    room_key_array[2] = parseInt(room_key_array[2], 10) + offset_z;
    var new_room_key = room_key_array.join(',');

    if (map[new_room_key]) {
      container.room = new Room(map[new_room_key].data);
      container.room_id = new_room_key;

      // Remove any existing item data.
      container.removeItems();

      // Add item if it exists in the new room data.
      if (map[new_room_key].item) {
        container.addItem(map[new_room_key].item);
      }

      container.render();
    } else {
      container.room = null;
      container.room_id = new_room_key;

      // Remove any existing item data.
      container.removeItems();
      container.render();
    }
  });
}

Inventář a interakce

Inventář a interakce si vyžádaly největší úsilí a iteraci k vytvoření něčeho funkčního. Experimentoval jsem s mnoha divokými nápady, jako je zmenšení hráče do krabice s inventářem u jeho nohou nebo jeho teleportace do samostatné místnosti s inventářem.

I když byly tyto prototypy zábavné, zdůraznily problém pohodlí ve VR. Prozkoumávání konceptů může být zábavné jako první zkušenost, ale neznámá mechanika se nakonec může stát nepohodlnou a nakonec i otravnou.

Lekce VR č. 3:Automatizovaný pohyb

Převzetí kontroly nad hráčem vytváří špatný zážitek. V případě Cardboard Dungeon , výše zmíněný zmenšující se mechanik měl animaci, která změnila měřítko kamery a přesunula ji do krabice u nohou hráče. To rychle vyvolalo pocit nevolnosti, protože hráč nemá žádnou kontrolu nad animací; je to nepřirozené jednání.

Nakonec jsem se rozhodl pro nejpohodlnější způsob interakce pro hráče. Byla to prostě mřížka položek u nohou hráče. Sbírání předmětů v dungeonu je umístilo do mřížky, ze které bylo možné předměty snadno vybírat. Někdy poskytuje nejlepší řešení nejjednodušší řešení.

Závěr

Velmi mě bavilo používat A-Frame k vytvoření své hry. Je to výkonný rámec a myslím, že je to vynikající nástroj pro rychlé prototypování, kromě toho, že je to užitečný produkční nástroj sám o sobě.

Bál jsem se, že webová VR bude skutečně trpět problémy s výkonem, ale potěšilo mě, když jsem zjistil, že tomu tak není. Velikosti textur byly největším zabijákem výkonu, protože zavádějí chvění a mají znatelný dopad na latenci.

Na A-Frame je skvělé, že je možné vytvářet vlastní komponenty, které rozšiřují stávající entity a komponenty. S konceptem jsem neměl možnost moc experimentovat, ale toto je zřejmý další krok ke zlepšení Cardboard Dungeon zkušenosti.

Na závěr, tým A-Frame a komunita jsou potěšením. Jejich skupina Slack je velmi aktivní a členové týmu jsou mimořádně pohotoví.

Doufám, že vám to dá nějaký přehled o výzvách, kterým jsem čelil při stavbě Cardboard Dungeon . Virtuální realita je novou hranicí a jako taková je jen málo odpovědí a stále je třeba se naučit mnoho lekcí. Je to vzrušující prostor k prozkoumání a rámce, jako je A-Frame, pomáhají zpřístupnit VR webovým vývojářům, kteří chtějí prozkoumat tuto novou hranici.

Můžete hrát Cardboard Dungeon zde (doporučeno Google Cardboard) a úplný zdrojový kód je k dispozici na GitHubu.

Děkuji za přečtení.