3. Crazy geek

https://www.smashingmagazine….


This article first send WeChat messages public number: front-end pioneer welcome attention, every day to you push fresh front-end technology articles


In this tutorial, we’ll create 3D objects and add simple interactions to them. In addition, you will learn how to set up a simple messaging system between the client and the server.

Virtual reality (VR) is an experience that relies on a computer-generated environment and is used in a wide range of applications: in the United States, for sports training at the Winter Olympics; Surgeons are experimenting with virtual medical training; Using virtual reality for games is one of the most common applications.

We’re going to focus on the last category of apps, and we’re going to focus on point-and-click adventure games. It is a casual game in which the object of the game is to complete a puzzle by selecting three dimensional objects in the scene. In this tutorial, we’ll build a simple version in virtual reality. This is an introduction to 3D programming and a stand-alone primer for deploying virtual reality models on the Web. You’ll be building with WebVR, and the framework has the double advantage of being able to play games in VR, while people without VR goggles can play them on their phone or desktop.

In the second half of this tutorial, you will build an “image” of your desktop. This means that all moves made on the mobile device will be mirrored in the desktop preview. This allows you to see what the player is seeing, allowing you to provide instructions, document the game, or just entertain guests.

The premise condition

To get started you need to prepare the following. For the second half of this tutorial, you’ll need a Mac OSX. While the code can be applied to any platform, the installation instructions for the following dependencies apply to Mac.

  • Internet access, particularly Glitch.com;
  • VR glasses (optional, recommended). I’m using Google Cardboard, which costs $15 each.

Step 1: Set up the virtual reality (VR) model

In this step, we will set up a Web site that contains a single static HTML page. This allows you to code from the desktop and automatically deploy to the Web, which can then be loaded onto the phone and placed into the VR goggles. Or the deployed website could be loaded by a standalone VR goggles. First go to https://glitch.com/. then

  1. Click “New Project” in the upper right corner.
  2. Click Hello-Express in the drop-down list.

Next, click Views/Index.html in the left sidebar. We call this your “editor.”

To Preview the page, click Preview in the upper left corner. We’ll use this as your preview. Note that any changes in the editor will be automatically reflected in the preview, unless there is an error or an unsupported browser.

Return to the editor and replace the current HTML with the code skeleton for the VR model below.

<! DOCTYPE HTML > < HTML > < head > < script SRC = "https://aframe.io/releases/0.7.0/aframe.min.js" > < / script > < / head > < body > <a-scene> <! -- blue sky --> <a-sky color="#a3d0ed"></a-sky> <! -- Camera with WASD and Panning Controls --> < A-Entity Camera Look-Controls WASD-Controls position="0, 0.5, 2" and the rotation to WASD-Controls ="0  0 0"></a-entity> <! -- brown ground --> <a-box shadow id="ground" shadow="receive:true" color="#847452" width="10" height="0.1" depth="10"></a-box> <! -- start code here --> <! -- end code here --> </a-scene> </body> </html>

You can then see the following:

To preview this feature on the VR glasses, use the URL in the Omnibar. In the figure above, the URL is https://point-and-click-vr-game.glitch.me/. Your work environment is now established and you can share this URL with family and friends at any time. In the next step, you will create a virtual reality model.

Step 2: Create a model of the tree

Now, we’ll create a tree with primitives from AFRAMAE.IO. These are some of the standard objects that Aframe has preprogrammed for ease of use. Specifically, Aframe refers to objects as entities (entities). There are three concepts related to entities:

  1. Geometry and texture,
  2. Convert shaft,
  3. Relative transformation.

First, geometry and textures are the two building blocks of all 3D objects in the code. Geometry defines a series of “shapes” — cubes, spheres, pyramids, etc. Material defines the static properties of the shape, such as color, reflectivity, and roughness.

AFRAME simplifies this concept by defining primiums such as < A-box >, < A-sphere >, < A-cylinder >, and many other fundamentals to simplify geometry and its materials. Let’s define a green sphere. In line 19 of the code, the
.

<! -- Start code here --> <a-sphere color="green" radius="0.5"></a-sphere> <! -- new line --> <! -- end code here -->

Second, there are three axes to convert objects. The X-axis is moving horizontally, and as we move to the right, the x-value is going to increase. The Y-axis runs vertically, and the y-value increases as we move up. The Z axis is perpendicular to your screen, increasing the Z value as the object moves toward you. We can translate, rotate, or scale the entity along these three axes.

For example, to move an object to the “right,” we need to increase its x value. To rotate an object up, we need to rotate it along the Y-axis. Now let’s change line 19 to move the sphere “up” — this means you need to increase the sphere’s Y value. Note that all conversions are specified as

, meaning that to increase their y value, you need to increase the second value. By default, all objects are in position 0,0,0. Add Position below.

<! -- Start code here --> <a-sphere color="green" radius="0.5" position="0 1 0"></a-sphere> <! -- edited line --> <! -- end code here -->

Third, all transformations are relative to their parent object. To add a tree trunk, add a cylinder inside the upper sphere to determine the position of the trunk relative to the sphere, and to integrate your tree into a unit. In “a – sphere… Add

entity between > and
tags.

<a-sphere color="green" radius="0.5" position="0 1 0"> <a-cylinder color="# 84651E "position=" 0-0.9 0" The radius = "0.05" > < / a - cylinder > <! -- new line --> </a-sphere>

Then add two green spheres as more leaves.

<a-sphere color="green" radius="0.5" position="0 0.75 0"> <a-cylinder color="#84651e" position=" 0-0.9 0" Radius ="0.05"></ a-sphere color="green" radius="0.35" position="0 0.5 0"></a-sphere> <! -- new line --> <a-sphere ></a-sphere> <! -- new line --> </a-sphere>

Switch back to Preview and you’ll see the following tree:

Reload the site preview on VR Glasses and view it. In the next section, we’ll make the tree interactive.

Step 3: Add Click Interaction to the Model

To make an entity interactive, you need to:

  • Add animation,
  • Clicking triggers an animation.

Since the end user uses VR goggles, the clicking action is equivalent to staring: in other words, staring at an object is “clicking” on it. To implement these changes, we’ll start with the cursor. Redefine the camera by replacing line 13 with the following.

< A-Entity Camera Look-Controls WASD-Controls position="0 0.5 2" Rotation ="0 0 0" fuseTimeout: 250" position="0 0 -1" geometry="primitive: ring; RadiusInner: 0.02; RadiusOuter: 0.03 "material =" color: black. Shader: flat" scale="0.5 0.5 0.5" raycaster="far: 20; interval: 1000; objects: .clickable"> <! -- add animation here --> </a-entity> </a-entity>

The code above adds a cursor that triggers a click. Note the objects:.clickable property. This means that all objects with a “clickable” class will trigger an animation and receive a “click” command when appropriate. We will also add animation to the click cursor so that the user knows when the cursor triggers a click. When pointing to a clickable object, the cursor slowly shrinks, catching after a second to represent the clickable object. Replace the comment
:

<a-animation begin="fusing" easing="ease-in" attribute="scale" fill="backwards" from="1 1 1" to=" 0.0.0.0.2" dur="250"></a-animation>

Move the tree to the right 2 units and modify action 29 to add the class “Clickable” to the tree.

<a-sphere color="green" radius="0.5" position="2 0.75 0" class=" Clickable ">

Next, we will:

  • Specify animation,
  • Click to trigger the animation.

Both of these steps can be done in quick succession, thanks to Aframe’s easy-to-use animation entity.

Add an

tag at line 33, immediately after the

tag but before the end of .

<a-animation begin="click" attribute="position" from="2 0.75 0" to="2.2 0.75 0" fill="both" direction="alternate" repeat="1"></a-animation>

The above properties specify many of the configurations for the animation. Animation:

  • Triggered by the “click” event
  • Modification of the treeposition
  • From the original position2, 0.75 0start
  • End in2.2 0.75 0Move to the right 0.2 units
  • The animation of the round trip to the destination
  • An animation that alternates between destinations and back
  • Repeat this animation once. This means that the object animation is played twice in total: once to the destination and once to the original location.

Finally, switch to Preview and drag from the cursor to the tree. Once the black circle is placed on the tree, the tree moves to the right and backward.

This wraps up all the basic knowledge needed to build a point-and-click adventure game in virtual reality. To view and play a more complete version of the game, please see the following video (http://alvinwan.com/shift/sce)… . The task is to open the gate and hide the tree behind it by clicking on various objects in the scene.

Next, let’s set up a simple NodeJS server to provide a static demo.

Step 4: Set up the NodeJS server

In this step, we’ll set up a basic, functional NodeJS server to serve your existing VR model. In the left sidebar of the editor, select package.json.

First delete lines 2-4.

"//1": "describes your app and its dependencies",
"//2": "https://docs.npmjs.com/files/package.json",
"//3": "updating this file will download and update your packages", 

Change the name to mirrorvr.

{" name ":" mirrorvr ", / / change the me "version" : "0.0.1",...

Under Dependencies, add socket.io.

"Dependencies" : {" express ", "^ 4.16.3", "socketio" : "^" 1.0.0,},

Update the repository URL to match the current glitch. The example Glitch project is called Point-and-Click-VR-Game. Replace it with your Glitch project name.

"repository": { "url": "https://glitch.com/edit/#! /point-and-click-vr-game" },

Finally, change the “Glitch” TAB to “VR”.

"keywords": [
  "node",
  "vr",  // change me
  "express"
]

Double-check that your package.json is consistent with the following.

{"name": "mirrorVR ", "version": "0.0.1", "description": "Mirror virtual reality models", "main": "Server.js ", "scripts": {"start": "node server.js"}, "dependencies": {"express": "^4.16.3", "socketio": "^ 1.0.0"}, "engines" : {" node ":" 8 "x}," repository ": {" url" : "https://glitch.com/edit/#! /point-and-click-vr-game" }, "license": "MIT", "keywords": [ "node", "vr", "express" ] }

Double check the previous section of code in the Views/Index.html to see if it is consistent with the following.

<! DOCTYPE HTML > < HTML > < head > < script SRC = "https://aframe.io/releases/0.7.0/aframe.min.js" > < / script > < / head > < body > <a-scene> <! -- blue sky --> <a-sky color="#a3d0ed"></a-sky> <! -- Camera with WASD and Panning Controls --> < A-Entity Camera Look-Controls WASD-Controls position="0, 0.5, 2" and the rotation to WASD-Controls ="0  0 0"> <a-entity cursor="fuse: true; fuseTimeout: 250" position="0 0 -1" geometry="primitive: ring; RadiusInner: 0.02; RadiusOuter: 0.03 "material =" color: black. Shader: flat" scale="0.5 0.5 0.5" raycaster="far: 20; interval: 1000; objects: .clickable"> <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="backwards" from="1 1 1" to="0.2 0.2 0.2 "dur =" 250 "> < / a - animation > < / a - the entity > < / a - the entity > <! -- brown ground --> <a-box shadow id="ground" shadow="receive:true" color="#847452" width="10" height="0.1" depth="10"></a-box> <! -- start code here --> <a-sphere color="green" radius="0.5" position="2 0.75 0" class="clickable"> <a-cylinder Color ="# 84651E "position=" 0-0.9 0" radius="0.05"></ a-sphere color="green" radius="0.35" position="0 0.5" 0"></a-sphere> <a-sphere color="green" radius="0.2" position="0 0.8 0"></a-sphere> <a-animation begin="click" Attribute ="position" from="2 0.75 0" to="2.2 0.75 0" fill="both" direction="alternate" repeat="1"></a-animation> </a-sphere> <! -- end code here --> </a-scene> </body> </html>

Next, modify Server.js.

First, import a few NodeJS packages.

  • Express is the Web framework for the server.
  • http

    This allows us to start a daemon that listens for activity on various ports.

  • Socket. IO with socket implementation allows us to communicate between client and server in real time.

When importing these packages, we will also initialize the ExpressJS program. Notice that the first two lines have been written for you.

var express = require('express');
var app = express();

/* start new code */
var http = require('http').Server(app);
var io = require('socket.io')(http);
/* end new code */

// we've started you off with Express, 

When the package is loaded, the server returns index.html as the home page. Notice that there is no new code below; This is just an explanation of the existing source code.

// http://expressjs.com/en/starter/basic-routing.html
app.get('/', function(request, response) {
  response.sendFile(__dirname + '/views/index.html');
});

Finally, the existing source code instructs the program to bind and listen on a port that is 3000 by default, unless otherwise stated.

// listen for requests :)
var listener = app.listen(process.env.PORT, function() {
  console.log('Your app is listening on port ' + listener.address().port);
});

When the edit is complete, Glitch automatically reloads the server. Preview your application by clicking “Show” in the upper left corner.

Your Web application is now up and running. Next, we will send a message from the client to the server.

Step 5: Send information from the client to the server

In this step, we will use the client to initialize the connection to the server. The client will also tell the server whether it is a phone or a desktop. First, import the JavaScript file you are going to add in the Views/Index.html.

After line 4, include a new script.

<script src="/client.js" type="text/javascript"></script>

In line 14, add Camera – Listener to the list of properties for the camera entity.

<a-entity camera-listener camera look-controls...>
    ...
</a-entity>

Then, switch to public/client.js in the left sidebar. Delete all the JavaScript code in this file. Then, define a utility function that checks if the client is a mobile device.

/** * Check if client is on mobile */ function mobilecheck() { var check = false; (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip( hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)? |phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|cra w|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc |fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01| 02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)| oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12| 21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1 )|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1 |si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| ) | webc | whit | wi (g) nw | nc | | WMLB | wonu | x700 | yas \ | - your | zeto | zte \ - / i.t est (a.s ubstr (0, 4))) check = true; })(navigator.userAgent||navigator.vendor||window.opera); return check; };

Next, we will define a series of messages that are exchanged with the server side. Define a new Socket. IO object to represent the connection between the client and the server. After the socket is connected, the message is logged to the console.

var socket = io();

socket.on('connect', function() {
  console.log(' * Connection established');
});

Check whether it is a mobile device and send the corresponding information to the server with the emit function.

if (mobilecheck()) {
  socket.emit('newHost');
} else {
  socket.emit('newMirror');
}

This ends the client’s message sending. Now modify the server code so that it can receive this message and react appropriately. Open the server-side server.js file.

Process the new connection and listen for the client type immediately. Add the following at the end of the file.

/**
 * Handle socket interactions
 */

io.on('connection', function(socket) {

  socket.on('newMirror', function() {
    console.log(" * Participant registered as 'mirror'")
  });

  socket.on('newHost', function() {
    console.log(" * Participant registered as 'host'");
  });
});

Preview the program again by clicking “Show” in the upper left corner. Load the same URL on a mobile device. In your terminal, you will see the following.

listening on *: 3000
 * Participant registered as 'host'
 * Participant registered as 'mirror'

This is the first simple messaging, where our client sends information back to the server. Exit the running NodeJS process. For the last part of this step, we will have the client send the camera information back to the server. Open the public/client. Js.

At the end of the file, add the following.

var camera; if (mobilecheck()) { AFRAME.registerComponent('camera-listener', { tick: function () { camera = this.el.sceneEl.camera.el; var position = camera.getAttribute('position'); var rotation = camera.getAttribute('rotation'); socket.emit('onMove', { "position": position, "rotation": rotation }); }}); }

Save and close. Open your server code file, server.js, to listen for the onMove event.

Add the following to the newHost block of the socket code:

socket.on('newHost', function() {
    console.log(" * Participant registered as 'host'");
    /* start new code */
    socket.on('onMove', function(data) {
      console.log(data);
    });
    /* end new code */
  });

Load the preview again on your desktop and mobile device. Once the mobile client is connected, the server will immediately start recording the camera position and rotation information sent from the client to the server. Next, do the opposite, sending information from the server back to the client.

Step 6: Send information from the server to the client

In this step, you will send the host’s camera information to all images. Open the primary server source file server.js.

Change the onMove event handling to the following:

socket.on('onMove', function(data) {
  console.log(data);  // delete me
  socket.broadcast.emit('move', data)
});

The Broadcast modifier ensures that the server sends this information to all clients connected to the socket. After sending this information to the client, you need to set the mirrored camera accordingly. Open the client script public/client.js.

Check here that the client is a desktop. If so, the mobile data is received and recorded accordingly.

if (! mobilecheck()) { socket.on('move', function(data) { console.log(data); }); }

Load the preview on your desktop and mobile device. In the desktop browser, open the development console. Then, load the application on the phone. Once the phone has successfully loaded the app, the developer console on the desktop displays information such as the camera position and rotation.

Open the client script public/client.js again. We will finally adjust the client camera based on the information sent.

Modify the event handler above to get the Move event.

socket.on('move', function(data) {
  /* start new code */
  camera.setAttribute('rotation', data["rotation"]);
  camera.setAttribute('position', data["position"]);
  /* end new code */
});

Load apps on your desktop and phone. Every move you make on your phone is reflected in the corresponding mirror image on your desktop! This completes the mirrored portion of the program. As a desktop user, you can now preview what mobile users will see. The concepts described in this section are critical to further development of the game, as we will also be converting the single player game to a multiplayer game.

conclusion

In this tutorial, we create three-dimensional objects and add simple interactions to these objects. A simple messaging system has also been built between the client and the server to enable a desktop preview of what the user sees.

These concepts even go beyond WebVR, as the concepts of geometry and materials extend to Scenekit (related to ARKit), three.js (the backbone of AFRAME), and other 3D libraries on iOS. These simple building blocks come together to give us the flexibility to create a fully fledged point-and-click adventure game. More importantly, they allow us to create any game using a click-based interface.

Here are a few resources and examples to explore further:

  • Full implementation of real-time preview on MirrorVR. A live preview of any virtual reality model on your mobile device can be added to your desktop with just a JavaScript link.
  • Bit by Bit virtual reality model of the children’s painting gallery.
  • Examples of AFRAME virtual reality development, developer documentation, and other resources.
  • Google Cardboard Experiences provides customised tools for teachers.

Next time we’ll build a full game that uses network sockets for real-time communication between players in a virtual reality game.


This article first send WeChat messages public number: front-end pioneer

Welcome to scan the two-dimensional code to pay attention to the public number, every day to push you fresh front-end technology articles


Read on for the other great articles in this column:

  • 12 Amazing CSS Experiment Projects
  • 50 React Interview Questions You Must Know
  • What are the front-end interview questions at the world’s top companies
  • 11 of the best JavaScript dynamic effects libraries
  • CSS Flexbox Visualization Manual
  • React from a designer’s point of view
  • The holidays are boring? Write a little brain game in JavaScript!
  • How does CSS sticky positioning work
  • A step-by-step guide to implementing animations using HTML5 SVG
  • Programmer 30 years old before the monthly salary is less than 30K, which way to go
  • 14 of the best JavaScript data visualization libraries
  • 8 top VS Code extensions for the front end
  • A complete guide to Node.js multithreading
  • Convert HTML to PDF 4 solutions and implementation