Building a 'whack-a-mole' game in VR using hoxel and A-Frame
Play the game yourself on a headset over at the live demo and checkout the code to remix and build your own game!
As a new hire here at Scandy, I have been anxious to start working on hoxel, our latest project that allows for volumetric capture using just an iPhone. Needless to say, I was thrilled when I learned a few weeks ago that I was being given free rein to build a game to demo the possibilities of hoxel in 3D space.
During a recent team hackathon, we came up with a few fun ideas, one of which was a 'whack-a-mole' game where you could hit volumetric recordings of yourself or your friends with various objects. Before integrating hoxel into the game, my first task was to create a VR space in which to interact with the hoxels.
As a frontend developer with little-to-no experience in VR or 3D, the framework of choice was a no-brainer - Supermedium's A-Frame. Per the docs:
A-Frame is a web framework for building virtual reality (VR) experiences. A-Frame is based on top of HTML, making it simple to get started. But A-Frame is not just a 3D scene graph or a markup language; the core is a powerful entity-component framework that provides a declarative, extensible, and composable structure to three.js.
Not long after diving into the docs did I realize just how easy it was to get a simple scene up and running. If you are a developer looking to get your feet wet in VR, I can't stress how easy it has been to get started. For example, with the single line of code below, which leverages A-Frame's built-in environment component, you are able to create a landscape for your scene using one of several presets.
<a-scene environment="preset: tron"></a-scene>
Building the Table
As you will learn quickly as you dig deeper into A-Frame, the library does a great job of creating convenience layers to get you building your scene as fast as possible. One of the ways it does this is by providing you with what are called primitives. Primitives are essentially pre-built elements that abstract the framework's entity-component pattern. I won't go into much more detail here, but as you spend the time to construct your own scene, you will quickly catch onto the pattern and will soon be building your own entity-component elements and even creating your own primitives. Take the example below, which is included in the A-Frame docs here.
If you wanted to create a box (or a box-shaped table), you could simply append the following html to your <a-scene>
<a-box color="red" width="3"></a-box>
The code above is an example of a primitive, which abstracts and is the same as writing the entity-component element below:
<a-entity geometry="primitive: box; width: 3" material="color: red"></a-entity>
The <a-entity> is the base-level element in A-Frame. Entities are container objects into which components (ie geometry and material) can be attached to define appearance and functionality. You can think of entities as empty divs with no CSS and no content, they are the basic building blocks of A-Frame.
In the demo, I started with a simple red box similar to the above, but wound up creating a more custom version of it in order to create the slant of the top side of the box. The 'holes' of the box are portrayed using a primitive as well, the <a-circle>. Check out the docs for a full list of the primitives available to you.
Introducing hoxels to the scene
<a-entity scvv="src: ../assets/hoxels/neilson_01"></a-entity>
<a-entity id="hoxel5" mixin="hoxelPhysics"></a-entity>
As you can see, each hoxel is comprised of three entities. A few notes:
> The parent entity controls the up-and-down motion via a component called move-up-down. Take a look at ./src/components/moveUpdown.js to understand how this component is working.
> The remaining entities are both children, one that brings in the actual hoxel recording via the scvv component and one that controls the physics interactions between the bat/racket and the hoxel via what is known as an A-Frame mixin called hoxelPhyics.
> I won't delve into mixins here, but they essentially allow you to mix and match and reuse components. More can be read about mixins here;
Physics & State Management
The breadth of this post is not meant to cover every aspect of the demo so I will not be going into the physics of the scene but as a brief overview, I used the following add-on component libraries to include physics dynamics to the scene.
The 'weapons' (baseball bat and tennis racket) are 3D models that I found on Google Poly.
As for state, I used aframe-state-component to manage score keeping and progress of the hoxel loading-indicator.
I can't express enough how much fun it was to work on this project. No doubt the world of 3D and VR can be a little daunting to those of us who haven't yet dived in but trust me, it doesn't have to be, thanks in large part to A-Frame. Before joining Scandy I had never even tried on a headset. Within a matter of weeks I was building a game that was so fun, I have often find myself utterly distracted by actually playing it during development and testing. Developing in 3D space provides a freedom that I haven't felt in a long time as a developer. The more time I spent building, the more ideas would come to me. I can't wait to see where we can take hoxel next and look forward to seeing what other crazy things the community we are building is able to bring to the table.