◉ VR-kurser
▶ Spela webbversionen

12. Hinkar, nycklar och dörrar

Målet

Låt spelaren hitta två nycklar under hinkar, låsa upp två rustika metalldörrar och faktiskt kunna passera genom öppningarna. Samma interaktionsfunktion används för desktop och VR. Öppna main.js.

Den lilla tillståndskedjan

Första nyckeln finns redan i scenen men är osynlig. Hinken är synlig och går att använda. När hinken flyttas ändras key.visible till true; ljus, ring och markör gör den lättare att upptäcka. Nyckeln är ännu inte insamlad. Först collectKey() ändrar state.keys[0]. Motsvarande gäller nyckel 2 och state.keys[1].

hink kvar → hink flyttad → nyckel synlig → nyckel insamlad → dörr öppnad

Testa varje pil i kedjan innan du bygger nästa. Om dörren öppnar sig när nyckeln bara syns, har synlighet och spelstatus blandats ihop.

Första hinken finns nära startplatsen. Den andra finns i banans bakre del, efter den första dörren. När spelaren trycker E på desktop eller grip i VR flyttas hinken åt sidan. Nyckeln visas då ovanför golvet med ett guldljus och en markör. Tryck E/grip en gång till för att ta nyckeln, eller gå riktigt nära efter den korta visningsfördröjningen. Att gå på hinken ska inte kasta upp spelaren i luften.

canOpenDoor() i reglerna kräver motsvarande nyckel och en pågående omgång. Öppningen är ungefär två meter bred, medan den nedladdade dörrmodellen är ungefär en meter bred. Spelet använder därför två dörrblad som möts i mitten. Vart och ett har en egen hinge-grupp och roterar åt motsatt håll. DOOR_WIDTH styr också den stängda dörrens kollision; en väggbit över dörrbladen fyller resten upp till taket. När dörren låses upp slutar öppningen blockera förflyttning och monster-pathfinding. Den synliga dörranimationen och kollisionsregeln är två separata system som måste säga samma sak.

Bygg dörren så den passar öppningen

  1. Öppna level.js. De två väggdelarna slutar vid X = −1 och börjar vid X = 1: öppningen är alltså ungefär 2 meter. DOOR_WIDTH är 2,08 meter så bladens ytterkanter går in lite i väggarna. DOOR_HEIGHT är 2,7 meter. En smal väggbit, en lintel, fyller utrymmet ovanför bladen upp till respektive väggs överkant.
  2. Öppna makeDoor() i main.js. Skapa två hinge-grupper vid öppningens vänstra och högra kant. Varje dörrmodell ligger som barn till sin grupp, med halva bladets bredd mellan modellen och gångjärnet. När GLB-filen har laddats skalas modellens bredd till halva DOOR_WIDTH; höjden ändras inte. Den högra modellen vänds så handtagen hamnar vid mitten.
  3. Vid upplåsning roteras vänster gångjärn med negativ vinkel och höger med positiv vinkel. Den osynliga dörrkollisionen täcker hela öppningen medan dörren är stängd. blocked() använder samma DOOR_WIDTH och slutar blockera när state.doors[number - 1] blir true.
const half = DOOR_WIDTH / 2;
// Två gångjärn: ett vid var sida av öppningen.
const hinges = [-half, half].map((x) => {
  const hinge = new THREE.Group();
  hinge.position.set(x, 0, z);
  scene.add(hinge);
  return hinge;
});
// När dörren öppnas:
hinges[0].rotation.y = -angle;
hinges[1].rotation.y = angle;

Skala inte hela banan för att täcka en glipa vid dörren. Mät först öppningen och dörrmodellen var för sig. Om modellen fortfarande inte fyller öppningen, kontrollera att breddanpassningen körs efter att loadModel() har avslutats.

nearestAction() väljer ett objekt inom 1,6 meter. Tryck E eller grip för att flytta hinken; gör en andra interaktion för att ta nyckeln. Efter en kort paus kan nyckeln också plockas automatiskt när spelaren går mycket nära. Hinken är inte en studsande fysik-kropp: den flyttas med en kontrollerad animation.

CC0-modeller

Testa

Prova både utan och med nyckel vid varje dörr. Båda dörrbladen ska täcka öppningen från sidan och mötas i mitten. Dörren ska bara öppnas med sin egen nyckel. Efter öppning ska passagen vara fri; öppna dörrblad ska inte fungera som en osynlig vägg.

Gör själv

I din kopia: gör nyckelmarkörens guldljus lite starkare eller svagare. Kontrollera att nyckeln fortfarande syns från normal ögonhöjd. Ändra sedan bara hinkens X-position med en halv meter och se om spelaren fortfarande kan nå den utan att öppna första dörren. Återställ om ordningen går sönder.