Procedurella Grottor TNM084 Alexander Steen alest849@student.liu.se 13-01-12 Sammanfattning Denna rapport beskriver en metod för att skapa procedurella grottor. Grottorna består utav sammanlänkade rum som byggs ut från ett startrum med hjälp av en algoritm. Resultatet är två program, ett i 2D och ett i 3D som båda låter användaren gå runt i dessa grottor.
Contents Introduktion... 3 Metod och genomförande... 3 Resultat... 4 Diskussion... 6 2
Introduktion Att skapa nivåer till t.ex. datorspel med procedurella metoder är ett bra alternativ när detaljerna på nivåerna inte är lika viktiga som nivån i helhet. En grotta med en gömd skatt i behöver kanske inte ha en planlösning som är planerad in i minsta detalj. En av fördelarna med procedurellt skapade nivåer är möjligheten att snabbt ändra några variabler och kunna få ett väldigt annorlunda utseende. Metod och genomförande Det finns olika metoder för att skapa dessa sammanlänkade rum som använder mer eller mindre avancerade algoritmer som alla ger olika utseende på grottorna. Den implementerade algoritmen är en relativt intuitiv lösning och kan delas upp i 4 steg. Steg 1 Först skapas ett rum med slumpade dimensioner. Detta rum utgör startpunkten för hela grottan. Steg 2 En av väggarna i ett rum samt en position på denna vägg väljs ut. Genom att bestämma hur algoritmen väljer vilket rum som nästa rum ska byggas ut ifrån går det att få olika utseenden på grottan. Exempel på detta kommer att ges senare. Steg 3 Dimensioner för ett nytt rum slumpas och utrymmet bakom väggen kontrolleras för att se om det finns plats att skapa ett nytt rum. Steg 4 Om det finns plats, placera ut det nya rummet och gå sedan till steg 2. Om det inte finns plats, gå direkt till steg 2. Algoritmen implementerades först i 2D i programmeringsspråket Blitz Basic. Blitz Basic är ett BASICbaserat språk specialiserat för spelprogrammering och tillhandahåller lättanvända funktioner för det mesta relaterat till grafik och interaktion. Programmet har en tvådimensionell array med heltal som beskriver hela grottan(figur 1). Detta gör det lätt att göra t.ex. kollisionskontroller mellan väggar och spelaren. Figur 1. Den tvådimensionella arrayen innehållandes grottan 1 - Vägg 2 - Golv 3
Själva rummen sparas var för sig i en dubbellänkad lista och består utav en bild som skapas i Steg 4. Varje rum har både en position i arrayen och en skärmposition som används vid utritningen av rummet. Efter algoritmen var implementerad i 2D gjordes en implementation i C++ och OpenGL med Vertex Buffer Objects och GLSL. Strukturen på grottan är samma som i 2D-fallet men varje rum har nu sin position i arrayen, sina dimensioner och position och riktning på ingång och utgång sparade. Alla rum sparas som i 2D-fallet i en dubbellänkad lista. Denna lista stegas sedan igenom och varje rums data används för att skapa vertex- och triangellistorna. En enkel shader med simplex noise används för att ge rummen en stenliknande textur. Resultat Både 2D- och 3D-implementationen kommer, när de körs, att försöka gå igenom de fyra stegen ett fördefinerat antal gånger. Det kan hända att algoritmen bygger in sig i ett hörn vilket innebär att det inte finns plats att placera ut något rum på någon sida då det antingen redan finns rum där eller det är i kanten av arrayen. Detta medför att det inte går att definera hur många rum grottan ska ha exakt utan endast ett största värde på antal rum. Figur 2 visar ett exempel på en liten grotta i 2D. Rummet med den blåa rektangeln i är det sista rummet och det går att se hur algoritmen har byggt in sig då den enda riktningen som inte har rum ivägen är uppåt men i detta fallet så tar arrayen slut där. Den röda cirkeln är spelaren och går att flytta runt i grottan. Figur 2. Exempel på grotta i 2D I grottan från figur 2 valdes alltid det senaste rummet i steg två. Detta ger en linjär grotta där varje rum som mest bara har en ingång och en utgång. Att istället låta algoritmen slumpmässigt välja ut ett rum att bygga ut ifrån ger en grotta med sidogånger och återvändsgränder som går att se i figur 3. 4
Figur 3.Grotta med flera möjliga gångvägar Ett alternativ för att få riktigt svårnavigerade grottor är att istället för att bara välja ett slumpmässigt rum att bygga utifrån låta algoritmen försöka bygga ett nytt rum från var och ett av de hittills skapade rummen. Detta kommer att ge en väldigt tät grotta då de flesta rum kommer att ha flera rum intill sig. Ett exempel som använder denna metod går att se i figur 4. Figur 4. Grotta där algoritmen försökt att bygga ett nytt rum för alla redan existerande rum 5
Figur 5 är från implementationen i OpenGL och visar insidan av ett rum med ingången och utgången på samma vägg. Figur 5. Grotta i 3D implementerad i OpenGL 2D-implementationen fungerar bara i Windows då Blitz Basic använder sig av DirectX medan 3Dimplementationen ska fungera i både Windows och Linux. Diskussion Implementationen i 3D skapar alltid ett nytt rum från det senast skapade rummet. Detta på grund av strukturen på programmet. Varje rum består utav 20 punkter(8 för hörnen på rummet, 2x4 punkter för ingång och utgång och 2x2 punkter i taket ovanför punkterna för ingång och utgång. Figur 6). Figur 6. Strukturen för rummen i 3D Detta medför att det inte går att lägga till en extra utgång på samma sätt som i 2D-fallet där det går bra att bara rita om bilden för att få en ny utgång. För att kunna göra det i 3D skulle det behövas antingen fler punkter på varje vägg som används vid behov eller en annan lösning på hur rummen skapas(t.ex. voxlar). 6