woensdag 15 januari 2014

VoxelJS in acht zorgen

Na wat surfen op YouTube kwam ik een talk tegen van Max Ogden met de de titel "Minecraft.js". Geen idee wie de gast is, maar hij heeft een Baard als Josef en draagt een bril. (Geloof me, als je zijn baard ziet, zou je het ook een hoofdletter geven.) Mijn Geek-sense deed tinglee, dus ik kijken.

Zijn talk begint over het onstaan VoxelJS, een javascript library om zelf minecraft-achtige games te maken in de browser. Puur Javascript en WebGL. Me likey-likey. Als begin van zijn project besloot hij alles te downloaden van Github wat ook maar iets met Minecraft en Javascript te maken had, want dat is wat je doet als je begint met een project: Github fetchen, right? Riiight. Wat hij vond was een hele hoop troep. (Wat raar.)

Maar gelukkig vond-ie ook de repository van Mikola Lysenko die een algoritme heeft bedacht om uit Minecraft-achtige voxel-data een efficiente 3d mesh te generen: De basis van elke voxel-engine. Als hij gewoon gegoogled had op "minecraft meshing" dan was het zijn eerste hit geweest. Tsja, hij besloot te Githubben. Hier onstond de eerste zorgen.

Dat filmpje duurt 43 minuten, duurt wel lang denk ik. Ik besluit een nieuw tabje te openen, want zijn baard had al genoeg bewondering van me gehad en op geluid alleen kon ik het prima volgen. Ik ga naar voxeljs.com. Op alinea 2 lees ik het volgende: "It was written by @maxogden and @substack, two non-game developers that want to make voxel games easy, fun and modular." Ik denk, amagawd .. Non-game developers and they tweet! Zorgen twee en drie.

Zijn verhaal gaat verder over de verschillende manieren om een Minecraft wereld te genereren. Je kan voor elke voxel keihard een box plaatsen met 6 zijden, 12 faces en tot 24 vertices maar dat zou gigantisch veel geheugen eten omdat Minecraft-achtige spellen vaak miljoenen voxels bevatten. Je kan bijvoorbeeld ook alleen de boxen plaatsen op de buitenste laag voxels, de speler zal het verschil niet zien. Op dit punt praat hij alleen nog maar Mikola na. Mikola's blogpost hierover is zeker meer de moeite waard.

Ik scroll verder op de website en zie een hele hoop modules, klaar voor gebruik. Ik denk, dit zou wel eens kunnen werken. En met Mikola's meshing engine in de basis van VoxelJS besloot ik toch maar eens te kijken. Ik ga naar de Github pagina en lees een beetje wat er is. Een typische documentatie pagina die je regelmatig vind op Github, niets mis mee. Alle duiveltjes van een voxel engine zijn aanwezig: Events bij het plaatsen/weghakken van blokken, Api's om blokken te plaatsen, raycasting etc etc. Maar dan kom ik bij de Style guide terecht:
basically https://github.com/felixge/node-style-guide#nodejs-style-guide with a couple of minor changes:
  • no semicolons
  • single line ifs/fors when appropriate for terseness
  • no hard to understand for n00bs 'tricks' unless they are faster


Wat?! Geen puntkomma's!? If- en For blokken op enkele regel is never appropriate! Daarnaast predikt de "node-style-guide" als gebod nummer 1 om twee spaties te gebruiken voor indentatie. Er is een reden waarom we het tab-tekentje gebruiken voor indentatie meneer Geisendörfer! Wanneer je een regel code uitcommentarieerd met "//", dan blijft de indentatie afstand op die regel gelijk. Ik snap dat je de wereld wilt redden van code waar tabs en spaties gemixed zijn, maar ik denk niet dat genocide op het tab-tekentje de oplossing is. Zorgen vier.

VoxelJS is helemaal de NPM-way gebouwd, dus wanneer je iets daarmee wilt moet je ook helemaal de NPM-way gaan. Ik maak een NPM-module directory compleet met package.json. Installeer alle nodige VoxelJS modules als dependencies. Ik start met de voxel-hello-world module, draai browserify en run het in de browser.

Het werkt! Ik sta op een bal van 20 bij 20 blokjes. Ik kan hakken en blokjes plaatsen. Nice! Ik val van de bal af.. Crash! Niet zo nice. Ik reload mijn tab en spring deze keer direct van de bal af. Weer crasht mijn tab. Na een aantal reloads is het zeker: Het vallen uit de wereld is letterlijk fataal voor mijn tabs. Een van de modules bij VoxelJS heet "voxel-rescue". De module transporteert de speler naar het startpunt wanneer het een bepaalde (lage) y-positie bereikt, dus wanneer je uit de bodem van de wereld valt. Ik vond het al een typische naam "voxel-rescure", zoiets noem je toch eerder "voxel-respawn"? Maar gezien deze bug, begreep ik de naam beter. Want het red je browsertab van een crash omdat je dan niet meer tegen de bug aan loopt. Zorgen vijf.

Max gaat verder over hoe hij met zijn maat Substack moeite had om de meshes te texturen. Want Mikola's algoritmen spuugde geen UV-coordinaten uit. Really?! Re-he-he-eally? In een Minecraft wereld is elke vlak axis-aligned en bevat slechts 1 uit 6 normals. Met andere woorden: je hebt geen UV-coordinaten nodig! Je hebt alleen maar 6 matrices nodig voor de 6 kanten van de box. Elke matrix transformeert de 3d-wereld coordinaten naar 2d coordinaten in "vlak"-space, fract() erover en het zijn UV-coordinaten. 

In plaats daarvan gebruikt hun "algoritme" de vier rauwe vertex posities van een vlak die worden omgevormd naar een breedte en hoogte vector (punt 0,0 - punt 1,0 en punt 0,0 - punt 0,1) met behulp van if-jes. Letterlijk als in: `if(size.x === 0) u = size.y && v = size.z;` (Wanneer mijn vlak 0 breedte heeft, dan bepaalt hoogte de hoogte van de texture en de diepte de breedte van de texture). Zorgen zes.

Maar dankzij Mikola's mesher, hoeft dat stukje aanzienlijk minder vaak aangeroepen worden dan je zou denken, de impact is minder groot. En is eigenlijk best wel schattig: Het doet me denken aan mijn allereerste "move to point"-code wat ik ooit geschreven heb. Het was de code in een RTS die ervoor zorgt dat je unit naar een bepaalde plek toe gaat. In die tijd zat ik nog op de middelbare school, begreep niets van vectoren, lette niet op tijdens wiskunde en deed maar wat. (Shit, wat een heerlijke tijd was dat!) Mijn algoritme deed ongeveer het volgende:
//elke frame
if(doel.x < unitpositie.x) {
    unitpositie.x -= 1;
} else if(doel.x > unitpositie.x) {
    unitpositie.x += 1;
}
if(doel.z < unitpositie.z) {
    unitpositie.z -= 1;
} else if(doel.z > unitpositie.z) {
    unitpositie.z += 1;
}
Deze methode zorgde ervoor dat mijn units altijd recht of diagonaal over het veld verplaatsde. Tegenwoordig zou ik gewoon de genormaliseerde relatieve vector nemen tussen `unitpositie` en `doel` en dat vermedigvuldigen met de framerate-aangepaste snelheid. De hacky UV solver kan ik wel vergeven.

Ik skim verder door de source van VoxelJS en ik kom erachter dat de geoptimaliseerde meshing algoritme van Mikola niet eens gebruikt word! Mikola's meshing package heeft 4 tal meshing methoden: Stupid, Culled, Greedy en Monotone. De eerste twee methoden zijn super inefficent en eigenlijk alleen bedoeld ter ondersteuning van zijn blogpost voor screenshots en benchmark vergelijkings materiaal. VoxelJS maakt gebruik van Culled. De Culled versie gebruikt alleen de zijden van de boxen die lucht aanraken. Eigenlijk de minimale optimalisatie die je zou verwachten bij een dergelijke game. Ik vervang Culled voor Greedy en ja hoor: De UV-coordinaten helemaal frox! Zorgen zeven.

Na een aantal avondjes stoeien met VoxelJS blijkt het behoorlijk lastig te zijn om daadwerkelijk een minecraft achtig game in elkaar te hakken. Bijna elk aspect aan Minecraft bestaat wel in een of andere voxel-* module vorm. Dus dat zou niet al te lastig moeten zijn. Maar de verschillende modules werken allemaal weer met andere versies van voxel-engine. Na wat gegoogel op Google, kwam ik het volgende blogpost tegen van Kyle "Shama" Robinson Young. Die precies de kutheid beschrijft waarmee ik al een een aantal avonden te kampen had. Zorgen acht!

Tijd om af te haken en VoxelJS te ditchen! Thanks but no thanks!

Ik geloof dat Minecraft het begin is van een hele nieuwe game genre, net zoals The Rise of Triad ooit was voor FPS. Ik geloof ook dat op een dag, al onze software via een browser gaat draaien. Alleen professionals die de extra rekenkracht/hardware toegang nodig hebben zullen native apps blijven gebruiken. Dus zoiets als Minecraft in de browser gaat er gewoon komen. (Minecraft draait nu al de browser als applet, maar dat is wat anders.) Daarom waag ik zelf een poging om dit voor elkaar te krijgen. Eens kijken hoe ver een actual game developer die niet aan twitter doet komt.

Wordt vervolgd.

dinsdag 14 januari 2014

Avontuur in games


Soms denk ik nog terug aan de games van vroeger en kan het dan niet laten om deze te vergelijken met het aanbod van nu. Hoe erg ik mij heb vermaakt met die games, alleen of met vrienden, en waar is die tijd nu gebleven? Dikwijls tijdens het fanatiek discussiëren met andere gamers valt snel de conclusie dat ik een perceptie heb vol met nostalgie. Met moeite dat ik toe geef, bang dat de discussie vervalt en men niet verder wil kijken wat nog meer speelt bij het gemis in hedendaagse games. 

Waar is het avontuur?

Als mij iets mateloos stoort is het wel het gebrek aan verkenning en ontdekken, het gevoel van vrijheid en de beloning die een fantasievolle wereld biedt. Stel je eens voor: Wolfenstein 3D met een zelfde lineair leveldesign als Call Of Duty, gang na gang, geen splitsende wegen en geen zoektocht naar benodigde items. Alles komt vanzelf voorbij dermate je vooruitloopt en meer nazi´s afschiet. De teleurstelling in de lineariteit waarbij ik een gescript verhaal aan het afspelen ben door middel van herhalende gameplay mechanics, het fenomeen van het avontuurlijke gevoel dat zoek is. Ik zie het niet alleen terug in shooters, ook andere games hebben er last van. Met grote verwachting speelde ik The Legend of Zelda: Skyward Sword en snel voelde ik mij weer met de hand worden meegenomen door heel de game, jammer... Gelukkig maakte Nintendo het weer goed met de nieuwe The Legend of Zelda: A Link to the Past, maar dat betekent nu niet dat het fenomeen de wereld uit is.

Vroegâh...

Welke games hadden het gevoel van avontuur dan wel op orde? Als ik terugkijk naar Duke Nukem 3d, Doom en bijvoorbeeld Quake zie ik games die de opzet van doolhoven hebben. Doolhoven waar links op de map een sleutel ligt, rechts een hendel, bij een doodspoor een ammopack en verderop weer een deur die op slot is. Met bijna elk pad gevuld aan rewards (ammo, weapons, switches, visuals) bieden deze games juist het gevoel van avontuur en creëerde het voor mij de behoefte naar meer verkenning en hoop op nieuwe ontdekkingen. Het idee dat ik geen lineair verhaal aan het afspelen ben maar een spel speel dat een gevoel van avontuur genereert, geeft mij het idee dat ik tijdens het gamen zelf iets heb gepresteerd en het mijn gametijd waard is.

Het is dus niet alleen nostalgie, er speelt meer wat we als ontwikkelaars onder ogen mogen zien om de kwaliteit in games die vroeger aanwezig was terugbrengen naar het nu!

M.Krol


Animatie als communicatiemiddel voor gamedesign

Als je in de games industrie actief bent heb je vast wel eens te maken gehad met een design document. Een goed design document is niet altijd een noodzakelijkheid maar bij grotere projecten ontkom je er meestal niet aan. Een design document geeft houvast aan een visie is en het is een handig centraal naslagwerk voor het bouwen van je game.

Toch ontstaat er juist bij design documenten vaak veel misverstanden. Dit moet dan opgelost worden met veel overleg zoals bijvoorbeeld de scrum-methode. In de meeste design documenten wordt de visuele impressie over gebracht door uitgewerkt concept art of ander beeld materiaal. Level designs worden vaak uitgetekend met kleine symbolische markeringen om duidelijk te maken welke spel objecten of entiteiten zich waar bevinden. Dit is een vrij klassiek scenario. Toch is met al dit moois het design vaak slecht gecommuniceerd. Er moet veel terug gekoppeld worden en uiteindelijk moet er vaak ook veel geschrapt of toegevoegd worden.

Sinds een paar weken werk ik als programmeur aan een nieuw project en tot nu toe is het design document nog helemaal leeg. Toch is het design heel helder gecommuniceerd. Dat komt omdat design werk al gedaan is in de vorm van korte animaties inclusief geluid. Het project bestaat uit verschillende mini games. Voor elke mini game is er een korte animatie van enkele seconde gemaakt waarin alle mechanics duidelijk zichtbaar zijn. Tevens is de animatie al opgebouwd uit de art assets en de sounds van de uiteindelijke versie. De hele look & feel ligt dus duidelijk vast en je hebt alle assets al.

Voor een programmeur geeft dit heel een duidelijk beeld wat er allemaal moet gebeuren en alle benodigdheden zijn er al. Je weet precies wat het moet worden en je kan dus gelijk aan de slag.
Het nadeel is dat je als programmeur dan veel minder invloed hebt op de basis van het ontwerp. Er zit ook het risico in dat als de game geprogrammeerd is de gameplay toch tegenvalt.

Een iteratief proces heeft z'n voordelen maar een kapitein en een stuurman in een hiërarchische waterval structuur geeft wel meer duidelijkheid. Bovendien is er voor de programmeur als de basis er staat nog voldoende om voor te stellen en om toe te voegen. Dus beperk de animatie tot een paar korte seconde van de core gameplay. Ook is het een vereiste dat de game designer de graphics kan maken en kan animeren.

Werken met pseudo gameplay footage heeft zeker bij uitbesteden en telewerken voordelen. De meeste outsourcing projecten hebben als grootste probleem dat communicatie niet helder was. Er zitten over de hele wereld programmeurs, designers en andere creatievelingen. Maar het aanboren van globaal talent wordt vaak door taalbarrières of cultuur verschillen geblokkeerd.

Wellicht werk je al met animaties om game mechanics en een overal visuele impressie te communiceren dan weet je hoe fijn dat kan werken. En anders hoop ik dat ik een nuttige tool aan je toolbox heb kunnen toevoegen.

Dit was m'n eerste blog post. Heb jij nou een game gerelateerd artikel of iets waar jij een blog post over zou willen maken stuur me dan even een berichtje naar Simon@adjumagames.com en dan verschaf ik je toegang tot een account.

S.Alkemade