{"id":28415,"date":"2022-05-30T12:11:45","date_gmt":"2022-05-30T12:11:45","guid":{"rendered":"http:\/\/build-a-virtual-world-with-user-input"},"modified":"2022-05-30T12:11:45","modified_gmt":"2022-05-30T12:11:45","slug":"build-a-virtual-world-with-user-input","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/","title":{"rendered":"Build a Virtual World with User Input"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Working with virtual reality (VR) has typically involved building apps and worlds using tools like Unity and Unreal Engine and headsets. You don\u2019t need to have all of these things if you know some basic HTML and JavaScript. You can build and test your own virtual world directly in the browser without a headset.<\/p>\n<p>We\u2019re going to build a simple VR app using the <a href=\"https:\/\/aframe.io\/\">A-frame library<\/a>. Any apps you build with this can be developed in the browser and used on any of the popular headsets. This project is going to be different from a lot of other projects because we aren\u2019t going to use a JavaScript framework. This will just be an HTML file and a JavaScript file.<\/p>\n<h2>Make the VR world<\/h2>\n<p>This little VR world will consist of a few boxes falling from the sky that let you change the material for a robot figure. Let\u2019s start by creating a new folder called <code>virtual-world<\/code>. Inside this folder, add a file called <code>world.html<\/code> and another file called <code>change-materials.js<\/code>. Open the <code>world.html<\/code> file and add the following code.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/aframe.io\/releases\/1.3.0\/aframe.min.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-scene<\/span> <span class=\"hljs-attr\">background<\/span>=<span class=\"hljs-string\">\"color: #7BFAFA\"<\/span>&gt;<\/span> <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-scene<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This sets up the HTML file to use A-frame and we have a scene in the <code>&lt;body&gt;<\/code> to get things started. The way we use A-frame elements is very similar to working with regular HTML elements. They all have attributes we can add to get different behaviors and looks. In <code>&lt;a-scene&gt;<\/code>, there\u2019s a <code>background<\/code> attribute that sets the color for the entire scene or world.<\/p>\n<p>Now we need a way to look around and interact with the world, so we\u2019ll add a camera for the user.<\/p>\n<h3>Add the camera and marker<\/h3>\n<p>Knowing where you are in a virtual world is the only way you can move around and do things. That\u2019s why the camera placement and having an indicator for where the user is looking are important. Add the following code just above the closing <code>&lt;a-scene&gt;<\/code> tag.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-comment\">&lt;!-- set the camera for the user --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-camera<\/span> <span class=\"hljs-attr\">look-controls<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"world-camera\"<\/span> <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"0 3 0\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-entity<\/span>\n    <span class=\"hljs-attr\">cursor<\/span>=<span class=\"hljs-string\">\"fuse: true; fuseTimeout: 500\"<\/span>\n    <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"0 0 -1\"<\/span>\n    <span class=\"hljs-attr\">geometry<\/span>=<span class=\"hljs-string\">\"primitive: ring; radiusInner: 0.01; radiusOuter: 0.03\"<\/span>\n    <span class=\"hljs-attr\">material<\/span>=<span class=\"hljs-string\">\"color: black; shader: flat\"<\/span>\n    <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"marker\"<\/span>\n  &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-entity<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-camera<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This tells A-frame that the camera is being used for the <code>look-controls<\/code> that let us do things in the world. It also has a cursor as part of the camera so the user can always see where their focus is. Since we have the scene and the camera in place now, we need to put something in the world. So let\u2019s start with the boxes falling out of the sky.<\/p>\n<h3>Add material selection boxes<\/h3>\n<p>There are going to be a couple of boxes that let us decide whether the robot should be made out of wood or metal. We\u2019ll use some images we have on Cloudinary as the basis for the materials. Add the following code inside of the <code>&lt;a-scene&gt;<\/code> tags.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-comment\">&lt;!-- assets for the scene --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-assets<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n    <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"woodTexture\"<\/span>\n    <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/res.cloudinary.com\/milecia\/image\/upload\/v1653756834\/wood_vuxmb7.jpg\"<\/span>\n    <span class=\"hljs-attr\">crossorigin<\/span>=<span class=\"hljs-string\">\"anonymous\"<\/span>\n  \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n    <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"metalTexture\"<\/span>\n    <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/res.cloudinary.com\/milecia\/image\/upload\/v1653776620\/metal_ehet1g.jpg\"<\/span>\n    <span class=\"hljs-attr\">crossorigin<\/span>=<span class=\"hljs-string\">\"anonymous\"<\/span>\n  \/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-assets<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Any time you want to add new textures, audio, or even 3D objects to your world, you\u2019ll have to add them as assets at the top of your scene. Here, we have 2 images as part of our assets to define the metal and wood materials for the robot. Now we can create the boxes that show off those materials. Add the following code below the assets.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-comment\">&lt;!-- boxes that drop in --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"woodBox\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"-1 6 -3\"<\/span>\n  <span class=\"hljs-attr\">rotation<\/span>=<span class=\"hljs-string\">\"0 45 0\"<\/span>\n  <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"#woodTexture\"<\/span>\n  <span class=\"hljs-attr\">animation__position<\/span>=<span class=\"hljs-string\">\"property: object3D.position.y; to: 1;\"<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"metalBox\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"2 6 -3\"<\/span>\n  <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"#metalTexture\"<\/span>\n  <span class=\"hljs-attr\">animation__position<\/span>=<span class=\"hljs-string\">\"property: object3D.position.y; to: 1;\"<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-plane<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"0 0 -5\"<\/span>\n  <span class=\"hljs-attr\">rotation<\/span>=<span class=\"hljs-string\">\"-90 0 0\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"60\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"60\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#7C992B\"<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-plane<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We\u2019ve just added 2 boxes with <code>src<\/code> attributes that reference the image assets we pulled from Cloudinary. They both have the <code>animation__position<\/code> attribute which is what defines how they fall to the ground. Take note that we\u2019ve created IDs for these boxes because we\u2019ll be adding click events to them.<\/p>\n<p>Finally, there\u2019s a plane that defines the ground the entire world is based on. Now if you open the <code>world.html<\/code> file in a browser, you should see something like this.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/mediadevs\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1653778737\/e-603fc55d218a650069f5228b\/hldhp5kz92ttet2mrx8f.png\" alt=\"the ground, sky, and boxes of the world\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1530\" height=\"1204\"\/><\/p>\n<h3>Build the robot<\/h3>\n<p>We\u2019ve built an environment for things to exist in and we have a way to update textures to wood or metal. Now it\u2019s finally time to build the robot. Below the <code>&lt;a-plane&gt;<\/code> tag, add the following code.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-comment\">&lt;!-- robot right leg --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"2 1.25 -5\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"2.5\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"0.75\"<\/span>\n  <span class=\"hljs-attr\">depth<\/span>=<span class=\"hljs-string\">\"0.75\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">shadow<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- robot left leg --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"0.25 1.25 -5\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"2.5\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"0.75\"<\/span>\n  <span class=\"hljs-attr\">depth<\/span>=<span class=\"hljs-string\">\"0.75\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">shadow<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- robot waist --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"1.15 2.5 -5\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"0.5\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"2.5\"<\/span>\n  <span class=\"hljs-attr\">depth<\/span>=<span class=\"hljs-string\">\"0.75\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">shadow<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- robot body --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"1 3.75 -5\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"3\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"1\"<\/span>\n  <span class=\"hljs-attr\">depth<\/span>=<span class=\"hljs-string\">\"1\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">shadow<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- robot head --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"1 5.75 -5\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"1.25\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"1.75\"<\/span>\n  <span class=\"hljs-attr\">depth<\/span>=<span class=\"hljs-string\">\"1.25\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">shadow<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- base of robot right arm --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-cylinder<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"2.25 4.25 -5\"<\/span>\n  <span class=\"hljs-attr\">radius<\/span>=<span class=\"hljs-string\">\"0.35\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"2\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">segments-radial<\/span>=<span class=\"hljs-string\">\"6\"<\/span>\n  <span class=\"hljs-attr\">rotation<\/span>=<span class=\"hljs-string\">\"0 0 90\"<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-cylinder<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- second part of robot right arm --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-cylinder<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"3.8 3.75 -5\"<\/span>\n  <span class=\"hljs-attr\">radius<\/span>=<span class=\"hljs-string\">\"0.35\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"2\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">segments-radial<\/span>=<span class=\"hljs-string\">\"6\"<\/span>\n  <span class=\"hljs-attr\">rotation<\/span>=<span class=\"hljs-string\">\"0 0 45\"<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-cylinder<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- base of robot left arm --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-cylinder<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"-0.25 4.25 -5\"<\/span>\n  <span class=\"hljs-attr\">radius<\/span>=<span class=\"hljs-string\">\"0.35\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"2\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">segments-radial<\/span>=<span class=\"hljs-string\">\"6\"<\/span>\n  <span class=\"hljs-attr\">rotation<\/span>=<span class=\"hljs-string\">\"0 0 90\"<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-cylinder<\/span>&gt;<\/span>\n<span class=\"hljs-comment\">&lt;!-- second part of robot left arm --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-cylinder<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"robot\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"-1.8 5 -5\"<\/span>\n  <span class=\"hljs-attr\">radius<\/span>=<span class=\"hljs-string\">\"0.35\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"2\"<\/span>\n  <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"#bcc9b5\"<\/span>\n  <span class=\"hljs-attr\">segments-radial<\/span>=<span class=\"hljs-string\">\"6\"<\/span>\n  <span class=\"hljs-attr\">rotation<\/span>=<span class=\"hljs-string\">\"0 0 45\"<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-cylinder<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We\u2019re using a lot of A-frame primitive shapes to make this robot so you can have a lot of fun with this later. You might also consider making a 3D object in <a href=\"https:\/\/www.blender.org\/\">Blender<\/a> or you might try some of the free 3D objects <a href=\"https:\/\/clara.io\/library\">here<\/a> or <a href=\"https:\/\/archive3d.net\/\">here<\/a>. We\u2019ll keep it pretty basic here with just the built-in A-frame primitives.<\/p>\n<p>All of the shapes have essentially the same attributes, just changed to handle the positioning of robot parts correctly. Once you have all of the robot code in place, you should see something like this when you refresh the page.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/mediadevs\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1653779738\/e-603fc55d218a650069f5228b\/wfiwvqhueoeo3pld2lyt.png\" alt=\"robot in the scene with the boxes\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1630\" height=\"1250\"\/><\/p>\n<p>All that\u2019s left is implementing the functionality to update the robot\u2019s material when one of the boxes is selected.<\/p>\n<h3>Add an A-frame component<\/h3>\n<p>We\u2019ll update the robot\u2019s material through an A-frame component. Open the <code>change-materials.js<\/code> file and add the following code.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">AFRAME.registerComponent(<span class=\"hljs-string\">\"change-materials\"<\/span>, {\n  <span class=\"hljs-attr\">init<\/span>: <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-keyword\">const<\/span> woodBox = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\"#woodBox\"<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> metalBox = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\"#metalBox\"<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> robotBody = <span class=\"hljs-built_in\">document<\/span>.querySelectorAll(<span class=\"hljs-string\">\".robot\"<\/span>);\n\n    woodBox.addEventListener(<span class=\"hljs-string\">\"click\"<\/span>, () =&gt; {\n      robotBody.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">part<\/span>) =&gt;<\/span> {\n        part.setAttribute(<span class=\"hljs-string\">\"src\"<\/span>, <span class=\"hljs-string\">\"#woodTexture\"<\/span>);\n      });\n    });\n\n    metalBox.addEventListener(<span class=\"hljs-string\">\"click\"<\/span>, () =&gt; {\n      robotBody.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">part<\/span>) =&gt;<\/span> {\n        part.setAttribute(<span class=\"hljs-string\">\"src\"<\/span>, <span class=\"hljs-string\">\"#metalTexture\"<\/span>);\n      });\n    });\n  },\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This creates a new A-frame component called <code>change-materials<\/code> that we can reference on elements in the scene. In the <code>init<\/code> function, we\u2019re getting the elements in the scene based on their IDs and class. This is much like we would do in a regular web app. Next, we add some click event listeners to the metal and wood boxes that will update the <code>src<\/code> for each part of the robot\u2019s body.<\/p>\n<p>We do need to add references to this <code>change-materials<\/code> component in the HTML file. Add the following import to the <code>&lt;head&gt;<\/code> tag.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"change-materials.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Now we have the A-frame component accessible to the scene. We\u2019ll need to add this as an attribute to the wood and metal boxes. Update those elements like this.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"woodBox\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"-1 6 -3\"<\/span>\n  <span class=\"hljs-attr\">rotation<\/span>=<span class=\"hljs-string\">\"0 45 0\"<\/span>\n  <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"#woodTexture\"<\/span>\n  <span class=\"hljs-attr\">animation__position<\/span>=<span class=\"hljs-string\">\"property: object3D.position.y; to: 1;\"<\/span>\n  <span class=\"hljs-attr\">change-materials<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a-box<\/span>\n  <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"metalBox\"<\/span>\n  <span class=\"hljs-attr\">position<\/span>=<span class=\"hljs-string\">\"2 6 -3\"<\/span>\n  <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"#metalTexture\"<\/span>\n  <span class=\"hljs-attr\">animation__position<\/span>=<span class=\"hljs-string\">\"property: object3D.position.y; to: 1;\"<\/span>\n  <span class=\"hljs-attr\">change-materials<\/span>\n&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a-box<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The only difference is that now these boxes have the <code>change-materials<\/code> attribute. This is how A-frame works with components so now these elements will have the correct event listeners. If you reload the page and move the marker over one of the boxes, your robot should look like one of these.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/mediadevs\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1653780759\/e-603fc55d218a650069f5228b\/w6oxfbegc0gftwkwgsfv.png\" alt=\"metal robot\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1464\" height=\"1276\"\/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/mediadevs\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1653780729\/e-603fc55d218a650069f5228b\/m8qd19xumo0dvprbf7m9.png\" alt=\"wood robot\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1660\" height=\"1264\"\/><\/p>\n<p>That\u2019s all! Now you can add more assets or more user interactions. If you have a VR headset, I\u2019d encourage you to try it out there as well!<\/p>\n<h2>Finished Code<\/h2>\n<p>You can find the code for this project in the <a href=\"\"><code>virtual-world<\/code> folder of this repo<\/a> or you can check it out in this <a href=\"https:\/\/codesandbox.io\/s\/optimistic-hellman-5kuetw\">Code Sandbox<\/a>.<\/p>\n<p>&lt;CodeSandBox\ntitle=\u201coptimistic-hellman-5kuetw\u201d\nid=\u201coptimistic-hellman-5kuetw\u201d\n\/&gt;<\/p>\n<h2>Conclusion<\/h2>\n<p>Working with VR takes a number of different skills which is part of the fun of it. From building assets, deciding on textures, and creating a whole experience for users, you can go in a lot of different directions. This is another creative way to practice your JavaScript or test out a new career path.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28416,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,145,370,177,371],"class_list":["post-28415","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-html5","tag-image","tag-javascript","tag-under-review"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Build a Virtual World with User Input<\/title>\n<meta name=\"description\" content=\"If you already know JavaScript, building a VR world doesn&#039;t mean you need to learn a different language. In this tutorial, we&#039;ll build a simple. interactive VR world that users can do things in with A-frame.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build a Virtual World with User Input\" \/>\n<meta property=\"og:description\" content=\"If you already know JavaScript, building a VR world doesn&#039;t mean you need to learn a different language. In this tutorial, we&#039;ll build a simple. interactive VR world that users can do things in with A-frame.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-05-30T12:11:45+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Build a Virtual World with User Input\",\"datePublished\":\"2022-05-30T12:11:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/\"},\"wordCount\":7,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"HTML5\",\"Image\",\"Javascript\",\"Under Review\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/\",\"name\":\"Build a Virtual World with User Input\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA\",\"datePublished\":\"2022-05-30T12:11:45+00:00\",\"description\":\"If you already know JavaScript, building a VR world doesn't mean you need to learn a different language. In this tutorial, we'll build a simple. interactive VR world that users can do things in with A-frame.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA\",\"width\":6000,\"height\":4000},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build a Virtual World with User Input\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Build a Virtual World with User Input","description":"If you already know JavaScript, building a VR world doesn't mean you need to learn a different language. In this tutorial, we'll build a simple. interactive VR world that users can do things in with A-frame.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/","og_locale":"en_US","og_type":"article","og_title":"Build a Virtual World with User Input","og_description":"If you already know JavaScript, building a VR world doesn't mean you need to learn a different language. In this tutorial, we'll build a simple. interactive VR world that users can do things in with A-frame.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-05-30T12:11:45+00:00","twitter_card":"summary_large_image","twitter_image":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/"},"author":{"name":"","@id":""},"headline":"Build a Virtual World with User Input","datePublished":"2022-05-30T12:11:45+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/"},"wordCount":7,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA","keywords":["Guest Post","HTML5","Image","Javascript","Under Review"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/","name":"Build a Virtual World with User Input","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA","datePublished":"2022-05-30T12:11:45+00:00","description":"If you already know JavaScript, building a VR world doesn't mean you need to learn a different language. In this tutorial, we'll build a simple. interactive VR world that users can do things in with A-frame.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA","width":6000,"height":4000},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-virtual-world-with-user-input\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Build a Virtual World with User Input"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924567\/Web_Assets\/blog\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d\/5fb4a10dfc6c7fd1a4d37f18b1cf1f47d9eb114d-6000x4000-1_284160497d.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28415","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28415"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28415\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28416"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28415"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28415"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28415"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}