Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Livecoding Recap: Almost Building a Ballistic Missile With React and AR.js

DZone's Guide to

Livecoding Recap: Almost Building a Ballistic Missile With React and AR.js

AR isn't just for mobile devs anymore! Read and watch to see how one dev used the React framework and an open source library to create a web AR app.

· Web Dev Zone
Free Resource

Tips, tricks and tools for creating your own data-driven app, brought to you in partnership with Qlik.



This Sunday we had 3 jobs:

  1. Get the AR Minecraft guy working ✅
  2. Use a hand drawn custom marker ❌
  3. Fire an AR ballistic missile from Korea ✅❌

But AR is hard.

We got pretty close, just like I suggested in last week's Livecoding Recap the Minecraft guy just needed some textures. After we added those, he became visible and looked great.

Here he is next to Kiwi.

To get that working we learned about A-FRAME Schemas. They're a way to describe the properties that an A-FRAME component can accept. A lot like React's propTypes, but as an object.

The minecraft component comes from A-FRAME-minecraft.js, which we copied off examples in Jerome Etienne's AR.js repo. That looks like this:

FRAME.registerComponent('minecraft', {
    schema: {
        skinUrl: {
            type: 'string',
            default : ''
        },
        wellKnownSkin: {
            type: 'string',
            default : ''
        },
        heightMeter : {
            default : 1
        }
    },
    init: function () {
        var character   = new THREEx.MinecraftChar()
        this.character = character

        this.el.object3D.add( character.root )
        // this.el.setObject3D('superRoot', character.root);
    },
    update: function () {
                if( Object.keys(this.data).length === 0 )       return
        var character = this.character
        character.root.scale.set(1,1,1).multiplyScalar(this.data.heightMeter)

        if( this.data.skinUrl ){
            character.loadSkin(this.data.skinUrl)
        }else if( this.data.wellKnownSkin ){
            character.loadWellKnownSkin(this.data.wellKnownSkin)
        }
    },
});

I have no idea which component system this is modeled after, but it works. Looks like we can define Minecraft guy's height in meters, a URL for the skin texture, and choose one of the well-known skins. Those won't work in our project because we don't have the files.

Schema props are passed into A-FRAME components as a string. Like this:

<Entity minecraft={`heightMeter: 2; skinUrl: ${skinUrl}`}
                                minecraft-head-anim="yes"
                                minecraft-body-anim="hiwave" />

You can read that as *"Create an A-FRAME Entity composed out of minecraft with heightMeter: 2; skinUrl: , and minecraft-head-anim set to yes and minecraft-body-anim set to hiwave. Both minecraft-head-anim and minecraft-body-anim are A-FRAME components.

I don't know yet how that composition works, but it looks neat.

Equipped with a working Minecraft demo dude, we went on to try creating our own marker from scratch. According to the AR.js repo, you are to use this Flash-based marker training implementation from 2009.

Flash doesn't work well in 2017. Couldn't get it to run at all in Chrome, and Firefox wouldn't let us click on "Give camera permissions." Had to hack around that and manually add a rule to the global permissions table.

We were able to create a marker file. The trick is to have an enclosed area with straight lines. You can put any sort of scribble inside, as long as the outside is straight and enclosed.

Unfortunately we weren't able to convince AR.js to use our marker. Even explicitly setting the marker URL didn't work and it kept using default settings.

Oh, well...

Onwards to making a ballistic missile!

We went the aframe-react way to build our ballistic missile. That way we could postpone understanding true A-FRAME components a little longer.

BallisticMissile is a class component because we wanted to use a tickHandler to animate as aframe-react README suggests.

For example, don't create requestAnimationFrames to continuously throw React prop updates to A-Frame. Instead, create an A-Frame component with a tick handler such that everything is done in memory with little overhead.

This did not work. I couldn't figure out how to set a tick handler that actually gets called, so we set up a little game loop in our component to make the missile fly.

On every requestAnimationFrame we update missilePos with velocity on each axis, and missileV with acceleration for each axis. This creates a missile that flies straight up and never stops.

You can try launching a missile here. You'll need the hiro marker.

Join me next time as we try to make the missile look better and convince it to fly in a ballistic trajectory.

Explore data-driven apps with less coding and query writing, brought to you in partnership with Qlik.

Topics:
web dev ,ar.js ,augmented reality ,react

Published at DZone with permission of Swizec Teller, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}