A status report from the one month old voxel.js project
Shortly after Christmas 2012 (about 3 and a half weeks ago) the Story of Mojang was intentionally released as a torrent. I watched it and was inspired. A year earlier I had purchased 2 copies of Minecraft for my nephews to play (and they haven't done much else since) but as gaming hasn't been a big part of my life for the last few years (because I've been too busy programming) I never had much time to play the game. Seeing how engaging Minecraft could be for my nephews was fascinating so I started looking into the modding community to see how feasible it would be to do things like hook Minecraft up to OpenStreetMap. My first foray into programming logic was in Starcraft over a decade ago so I figured that a game that is so addicting and yet so simple could be a really powerful platform for education.
I was disappointed to find out that not only is Minecraft closed-source but it also hasn't shipped an official API (these are used to extend a programs functionality). Instead, if you want to change the way Minecraft works, you have to decompile the Java program that Mojang distributes and then reverse engineer it to make it do what you want. Despite these technical hurdles, due to the success of Minecraft there is still a huge modding community. One of my favorites is World Edit, which lets you bulk edit the Minecraft world by doing things like making giant pyramids, spheres, rectangles or even frosted donuts.
The first thing I tried to do was install a plugin. I immediately found myself on old forum posts that I found on google while looking for answers to obscure questions like what the OS X path is for the plugin folder, how to downgrade my Minecraft version because I had upgraded to the newest version which broke the plugin I was trying to use and how to edit a Minecraft world file that I had downloaded from someone else to change the game mode from Survival to Creative (turns out you have to use a hex editor).
For the last couple years I have grown accustomed to the automated installation of modules that NPM provides and wondered if anyone had tried to make a package manager for Minecraft plugins. There are a few out there, but quite frankly they all reeked of Java (too many abstract interfaces, lots of boilerplate and hard to use build tools. Java was the first language I learned so I may very well be scarred from the experience) and were limited by the nature of decompiling as a workaround to Minecrafts lack of an API.
On Github I found 26 repositories that contained some approach to rendering voxels in a browser. I spent a few days getting them to run on my computer and reading the source code of every single one. The projects that stood out were webgl-meincraft, voxelworlds and WebGLCraft. Daniel Ribeiro wrote a post one year ago called Implementing Minecraft in WebGL and Jonas Wagner did a talk at OnGameStart a few months ago called Rendering Voxel Worlds using WebGL and produced this impressive demo. I later found BLK Game by Ben Vanik from Google which also has an impressive demo. My problem with every single one of the 26 projects that I found is that they were all huge projects that were hard to wrap your head around and hack on. I was trying to escape the Java mentality and make game development small and modular (like NPM) but didn't find a single project that had well documented, modular components. Some were written in coffeescript, hadn't been updated in over a year, had giant lib/ folders filled with custom written modules or only produced a single tech demo and then were never used again. To summarize: it was possible but still not very accessible.
I also discovered an obscure subreddit called voxelgamedev that had produced a wiki page called The BIG list of block engines and resources!. Through this I found out about Mikola Lysenko's blog 0fps.wordpress.com and his articles Meshing in a Minecraft Game, Meshing in a Minecraft Game (Part 2) and An Analysis of Minecraft-like Engines. Not only were these written in an amazingly accessible way but they also had a voxel meshing sandbox implemented in WebGL and three.js.
You should read Mikola's posts but the main idea with a voxel rendering engine is to create chunks of voxels. If you try to treat each individual voxel as an individual cube then you will have to send too much state back and forth to the GPU and your game will be slow. If you use one giant mesh for all the voxels in your world then it will take to long when a player digs a hole in the ground because you will have to recalculate the entire world. Chunks should be sized "just-right" in the middle of these two extremes so that you aren't making thousands of draw calls per frame but also can make voxel editing imperceptibly fast.
When you edit a voxel (to make a cave or build a tower) you are actually telling the engine to recalculate an entire chunk with or without a voxel present. To reduce the number of vertices these get culled/decimated (jargon for simplified) so that you aren't drawing voxel edges that the player can't see. To implement voxel editing I shoot an invisible ray (using the Raycaster in three.js), see where it intersected with the world, look up if the voxel there is air, dirt, brick or some other material, toggle it, and then tell the parent chunk to re-render (which includes the simplification). All of this happens quickly enough that the editing feels fast while you are playing the game.
The next thing to tackle was to get first person shooter style controls and physics hooked up. Luckily Chrome 23 was recently released and included support for the HTML5 Pointer Lock API. I based my physics on the code behind this demo by mrdoob but heavily modified it (made it more modular) and turned into the player-physics module. It still isn't perfect and I would love to see other approaches to FPS controls in JS now that Pointer Lock is here.
The project was a week old when I got stuck on collision detection and voxel texturing. I called for reinforcements and fellow Oakland JS hacker Substack answered the call. We stayed up until 2AM a couple of nights in a row and had a thing that kind of looked like Minecraft. Substack had some experience doing 3D programming and figured out how to calculate UV mappings and normals to texture our meshes. He also wrote some basic collision code so that the player could jump on top of and run into voxels. If you got stuck inside a voxel (which happened a lot) you would slowly float up to the top and pop out on the surface again. Good enough for a first version! One thing we couldn't figure out is how to have separate bottom, top and side textures for voxels so our world looked a little bland (but not too bad).
I decided to name the project voxel.js and figured that we should have a website. My wonderful girlfriend Jessica Lord offered to help design a basic website because she also wanted in on the exciting voxel action. We threw together voxeljs.com over the course of a couple days and substack and I made a bunch of inaugural modules to get the point across.
The core module is called voxel-engine. This module is used to create a game instance which can be given to other modules so that they can augment the game. The engine is responsible for doing things like rendering the world using a game loop. The goal of the engine is to be simple with sensible defaults that are easy to override.
To use Pointer Lock we got some help from Chris Dickinson who ended up writing the interact module for us (though it would be useful in many programs). I made a module for HTML selectable toolbars (used for selecting block types) called toolbar and another for generating terrain called perlin-terrain. Substack then wrote creature, debris and forest which really proved to me that we were on to something.
Before we "announced" the project publicly (I use quotes because all the code had been in public Github repos the whole time) I thought I should try to make a multiplayer server and a couple hundred lines of JS later had a basic implementation where every player was an animated 3D horse :D.
Pictured here is @izs (Node.js maintainer) running across a bridge he made in an early multiplayer test.
I later learned about techniques to make real time multiplayer games fast like the Source Multiplayer Networking article and the Build New Games HTML5 Networking article. The server is still a work in progress but has server-side physics and (somewhat currently broken) client-side prediction. If this project interests you then get in touch and I can help you start hacking on it!
The goal in most of my open source projects is to solve stupid problems so other people don't have to. Then people will use your solution to build other new things. It is a great feeling to see someone make something because of work that you did to make that thing easy.
In this way voxel.js has totally exceeded all of my expectations, even though I am writing this only a week and a half after the initial public release. Since the project started we have generated about 25 modules, half of which are from me and substack but half of which have come from outside contributors.
Many members of the Node.js community also are disciplined in writing small, Unixy pieces of software that do one thing and do them well. This is where the modular design of voxel.js comes from but also where our contributors come from. Since we used the package manager from node, put all of our code on Github, made some exciting demos and encouraged others to build new modules we were able to tap into the creativity of other members in our community like Kyle.
While I was writing this article Kyle actually released a new module called voxel-sky which lets you add sun and moon cycles to your voxel world.
Our old collision code needed some major love and luckily Chris Dickinson was knowledgable in the realm of collisions and physics and whipped up a ton of super useful (for any game) modules: aabb-3d, collide-3d-tilemap, spatial-events and spatial-trigger. Chris also sent a bunch of pull requests to the various voxel core modules to integrate in his modules and make our collisions super awesome.
We event had Darius and Greg from Bocoup volunteer two entire work days to hack on voxel.js. Darius edits the site Build New Games and made some great contributions to the player physics code and Greg made an awesome heightmap module.
This week I have written a handful of new modules: city, which dynamically renders any area of San Francisco into a crude voxel world, highlight and script-gun. Here is a video of highlight in action:
I am most excited about script-gun though. From here on out I'm going to focus on making voxel.js an environment in which you can learn to program. Script-gun is my first attempt (the module itself is only about 50 lines of JS) at a WorldEdit style module in the browser. You can try the demo here and use some example scripts that I prepared here to get an idea of the possibilities. It will get more intuitive as time goes on, this is just the very first version.
Substack is currently implementing detached chunks so that you can build voxel space ships and robots that walk around but are still editable. He also has mentioned that he wants to make a space vacuum with cellular automata logic for hull breaches to enable space battles where you would have to patch your hull to contain air leaks. An early example of these detached chunks is in voxel-servo.
We both see so many awesome things that can be done with voxel games that Minecraft isn't doing at all and don't intend on porting Minecraft in any way to JS. We instead just want to make it easier to make your own game in the same style. To me Minecraft should be a category and not an instance. (note: Minecraft is a trademark of Mojang.)
The next thing I am going to build is an in-browser game editor so that you don't need to know how to use the command line in order to start making games with voxel.js. JSFiddle is a great example of a web based editor like this. I'm going to implement it in such a way that you can create a game and then get a URL to share with your friends so that they can play your game, fork it, and remix your game.
The newest version of Chrome Beta for Android lets you enable WebGL through about:flags and I have a demo called fps-touch-controls that adds touch screen controls to voxel.js. The controls are still wonky but it is definitely possible to play on a phone.
Raspberry Pi is also capable of running it... in theory. Back in August someone got Firefox OS to run with WebGL enabled on the Pi but I haven't been able to get the newer versions of Firefox OS to work. FFOS is nearing a 1.0 release so hopefully someone makes it easy to install FFOS on a Pi soon! Once that is well supported I have plans to buy 10 Pis and start doing pop up computer labs for kids to teach them programming through hacking on voxel.js. The Raspberry Pi Foundation and Mojang have actually been working on a Minecraft Pi Edition that is intended for education but it isn't out yet, will be very stripped down and won't be open source!
To stay up to date with the project you can follow @voxeljs on twitter or hang out in #voxel.js on freenode IRC. But more importantly you should go forth and create modules and games!