Let's create a new app. We will work with mouse events and VR gazer pointer.

react-vr init MouseActions

And now we have the default react-vr application, inside the chess board and the hello message.

We will enable the VR gazer pointer. Let's add Simple raycaster.

yarn add simple-raycaster

Ok, now we need to change our client.js to support this, and enable the cursor.

vim vr/client.js

We will add SimpleRaycaster in the raycasters options, and we will set the cursorVisibility to visible.

import { VRInstance } from "react-vr-web";
import * as SimpleRaycaster from "simple-raycaster";

function init(bundle, parent, options) {
  const vr = new VRInstance(bundle, "MouseActions", parent, {
    raycasters: [
      SimpleRaycaster // Add SimpleRaycaster to the options
    ],
    cursorVisibility: "visible", // Add cursorVisibility
    ...options
  });
  vr.render = function() {
    // Any custom behavior you want to perform on each frame goes here
  };
  // Begin the animation loop
  vr.start();
  return vr;
}

window.ReactVR = { init };

Let's reload our app. And, we can't see anything. Why? The thing is, Chrome supports VR, but we need to enable it; because it doesn't come by default.

Enabling... And now we can see our cursor. Just a detail, if we set the cursorVisibility to auto it doesn't show. So, it really needs to be set to visible.

This cursor is interesting because it sets this as default in any device we are seeing. So, we don't need to worry about what it will look like if you see this on a desktop browser or a mobile browser.

Using onEnter

We saw this week the onEnter property, it is fired when the mouse is hovering the view. This also can be fired if we are using the cursor.

Let's create a text and implement the onEnter property. If the mouse/cursor is on it, it will change the color. The text will be orange as initial state. If the cursor is not on it will be white, red if the cursor is on it.

<Text
  style={{color: this.state.textColor}}
  onEnter={() => this.setState({textColor: 'red'})}
  onExit={() => this.setState({textColor: 'white'})}>
  This text will turn red when you look at it.
</Text>

So, as you can see it works.

Creating the questions

Our idea is to have a list of questions, for the moment it will be an array of objects. But in a real world scenario this could come from an API. Each question has the right answer, the question text and two options. We can answer the question by focusing the cursor on the right answer, and it passes to the next question. We will choose the question by using the property onEnter for the option.

Let's implement that. We will have an array of 5 questions, for the moment.

const questions = [
  {
    text: "Question 1",
    option1: "YES",
    option2: "NO",
    correct: "NO"
  },
  {
    text: "Question 2",
    option1: "YES",
    option2: "NO",
    correct: "NO"
  },
  {
    text: "Question 3",
    option1: "YES",
    option2: "NO",
    correct: "YES"
  },
  {
    text: "Question 4",
    option1: "YES",
    option2: "NO",
    correct: "YES"
  },
  {
    text: "Question 5",
    option1: "YES",
    option2: "NO",
    correct: "YES"
  }
];

In our state, we will have current that will be a number. Each time we check the answer we will increment the counter.

In the question view, we will show the question text and the two options. We will use flexDirection column for dividing the question and the options. And in the options view, it will be flexDirection row.

      <View>
        <Pano source={asset("chess-world.jpg")} />
        <View
          style={{
            flexDirection: "column",
            width: 1,
            backgroundColor: "gray",
            transform: [{ translate: [-0.5, 0, -2] }]
          }}
        >
          <Text
            style={{
              color: textColor,
              textAlign: "center"
            }}
          >
            {question}
          </Text>
          <View
            style={{
              flexDirection: "row",
              justifyContent: "center"
            }}
          >
            <Text
              style={{
                color: textColor,
                marginRight: 0.3
              }}
              onEnter={() => this.setState({ current: current + 1 })}
            >
              {option1}
            </Text>
            <Text
              style={{
                color: textColor
              }}
              onEnter={() => this.setState({ current: current + 1 })}
            >
              {option2}
            </Text>
          </View>
        </View>
      </View>

We will get the options and the question text from our array of questions, and any time we pass the cursor an answer, it will increment.

Let's test that!

Ok, so, if I choose any an answer, it changes the question! Cool!

Implementing real questions

Let's create a Questions component that will handle all these questions for us. This is just something to organize our code. We could probably use redux here to handle the actions, but for now we won’t.

All the questions will be inside the component. Let's create some questions.

Now we will create a variable in our state to handle the feedback message. These messages will be "CORRECT ANSWER" or "WRONG ANSWER". We will initialize it with an empty string.

    const showMessage = msg == ""
      ? <Text
          style={{
            height: 0,
            transform: [{ translate: [0, 0, 0] }]
          }}
        />
      : <Text
          style={{
            flexDirection: "column",
            backgroundColor: "gray",
            textAlign: "center",
            transform: [{ translate: [-0.5, 0.3, -2] }]
          }}
        >
          {msg}
        </Text>;

In our nextQuestion function we will check if the answer is the correct answer or not. If we have the correct answer, we increment the current question and we also check if this is the end of the game. If it's not the right answer we show a message saying "WRONG ANSWER".

Now, let's play our game! Playing...Answering the questions... And we have finished the game! These answers could come from an API. And our implementation can be improved, but this is just an example of what we can do.

Summary

Today we saw how to handle the pointer in VR, and we have created a simple questions and answer game. I hope you enjoyed using React VR.

Resources

Franzé Jr

Software Engineer with experience working in multi-cultural teams, Franze wants to help people when he can, and he is passionate about programming and Computer Science. Founder of RemoteMeetup.com where he can meet people all over the World. When Franze is not coding, he is studying something about programming.

  1. Comments for Controlling an app with your face

You must login to comment

You May Also Like