Hot File

Game with Three.js, ReactJS and WebGL in java

View: 353    Dowload: 0   Comment: 0   Post by: hanhga  
Author: none   Category: Javascript   Fields: Other

0 point/1 review File has been tested

I’m making a game titled “Charisma The Chameleon.” It’s built with Three.js, ReactJS and WebGL. This is an introduction to how these technologies work together using react-three-renderer (abbreviated R3R).

Introduction

I’m making a game titled “Charisma The Chameleon.” It’s built with Three.js, ReactJS and WebGL. This is an introduction to how these technologies work together using react-three-renderer (abbreviated R3R).

Check out A Beginner’s Guide to WebGL and Getting Started with React and JSX here on SitePoint for introductions to React and WebGL. This article and the accompanying code use ES6 Syntax.

How It All Began

Some time ago Pete Hunt made a joke about building a game using React in the #reactjs IRC channel:

“I bet we could make a first person shooter with React!
Enemy has <Head /> <Body> <Legs> etc.”

I laughed. He laughed. Everyone had a great time. “Who on earth would do that?” I wondered.

Years later, that’s exactly what I’m doing.

Charisma The Chameleon is a game where you collect power-ups that make you shrink to solve an infinite fractal maze. I’ve been a React developer for a few years, and I was curious if there was a way to drive Three.js using React. That’s when R3R caught my eye.

Why React?

I know what you’re thinking: why? Humor me for a moment. Here’s some reasons to consider using React to drive your 3D scene:

  • “Declarative” views let you cleanly separate your scene rendering from your game logic.
  • Design easy to reason about components, like <Player /><Wall /><Level />, etc.
  • “Hot” (live) reloading of game assets. Change textures and models and see them update live in your scene!
  • Inspect and debug your 3D scene as markup with native browser tools, like the Chrome inspector.
  • Manage game assets in a dependency graph using Webpack, eg <Texture src={require('../assets/image.png') } />

Let’s set up a scene to get an understanding of how this all works.

React and WebGL

I’ve created a sample Github repository to accompany this article. Clone the repository and follow the instructions in the README to run the code and follow along. It stars SitePointy: The 3D Robot!

Organizing View Code

The main benefit of using React to drive WebGL is our view code is decoupled from our game logic. That means our rendered entities are small components that are easy to reason about.

R3R exposes a declarative API that wraps Three.js. For example, we can write:

<scene>
    <perspectiveCamera
        position={ new THREE.Vector3( 1, 1, 1 )
    />
</scene>

Now we have an empty 3D scene with a camera. Adding a mesh to the scene is as simple as including a <mesh />component, and giving it <geometry /> and a <material />.

<scene>
    ...
    <mesh>
        <boxGeometry
            width={ 1 }
            height={ 1 }
            depth={ 1 }
        />
        <meshBasicMaterial
            color={ 0x00ff00 }
        />
</mesh>

Under the hood this creates a THREE.Scene and automatically adds a mesh with THREE.BoxGeometry. R3R handles diffing the old scene with any changes. If you add a new mesh to the scene, the original mesh won’t be recreated. Just as with vanilla React and the DOM, the 3D scene is only updated with the differences.

Because we’re working in React, we can separate game entities into component files. The Robot.js file in the example repository demonstrates how to represent the main character with pure React view code. It’s a “stateless functional” component, meaning it doesn’t hold any local state:

const Robot = ({ position, rotation }) => <group
    position={ position }
    rotation={ rotation }
>
    <mesh rotation={ localRotation }>
        <geometryResource
            resourceId="robotGeometry"
        />
        <materialResource
            resourceId="robotTexture"
        />
    </mesh>
</group>;

And now we include the <Robot /> in our 3D scene!

<scene>
    ...
    <mesh>...</mesh>
    <Robot
        position={...}
        rotation={...}
    />
</scene>

You can see more examples of the API on the R3R Github repository, or view the complete example setup in the accompanying project.

Organizing Game Logic

The second half of the equation is handling game logic. Let’s give SitePointy, our robot, some simple animation.

//...
gameLoop( time ) {
    this.setState({
        robotPosition: new THREE.Vector3(
            Math.sin( time * 0.01 ), 0, 0
        )
    });
}

Calling setState() triggers a re-render of the child components, and the 3D scene updates. We pass the state down from the container component to the presentational <Game /> component:

render() {
    const { robotPosition } = this.state;
    return <Game
        robotPosition={ robotPosition }
    />;
}

There’s a useful pattern we can apply to help organize this code. Updating the robot position is a simple time based calculation. In the future, it might also take into account the previous robot position from the previous game state. A function that takes in some data, processes it, and returns new data, is often refered to as a reducer. We can abstract out the movement code into a reducer function!

Now we can write a clean, simple game loop that only has function calls in it.

import robotMovementReducer from './game-reducers/robotMovementReducer.js'; 

//...

gameLoop() {
    const oldState = this.state;
    const newState = robotMovementReducer( oldState );
    this.setState( newState );
}

To add more logic to the game loop, such as processing physics, create another reducer function and pass it the result of the previous reducer:

const newState = physicsReducer( robotMovementReducer( oldState ) );

As your game engine grows, organizing game logic into separate functions becomes critical. This organization is straightforward with the reducer pattern.

Asset management

This is still an evolving area of R3R. For textures, you specify a url attribute on the JSX tag. Using Webpack, you can require the local path to the image.

<texture url={ require( '../local/image/path.png' ) } />

With this setup, if you change the image on disk, your 3D scene will live update! This is invaluable for rapidly iterating game design and content.

For other assets like 3D models, you still have to process them using the built in loaders from Three.js, like the JSONLoader. I experimented with using a custom Webpack loader for loading 3D model files, but in the end it was too much work for no benefit. It’s easier to treat the model as binary data and load them with the file-loader. This still affords live reloading of model data. You can see this in action in the example code.

Debugging

R3R supports the React developer tools extension for both Chrome and Firefox. You can inspect your scene as if it were the vanilla DOM! Hovering over elements in the inspector shows their bounding box in the scene. You can also hover over texture definitions to see which objects in the scene use those textures.

Performance Considerations

While building Charisma The Chameleon I’ve run into several performance issues that are unique to this workflow.

  • My hot reload time with Webpack was as long as thirty seconds! This is because large assets have to be re-written to the bundle on every reload. The solution was to implement Webpack’s DLLPlugin, which cut down reload times to below five seconds.
  • Ideally your scene should only call one setState() per frame render. After profiling my game, React itself is the main bottleneck. Calling setState() more than once per frame can cause double renders and reduce performance.
  • Past a certain number of objects, R3R will perform worse than vanilla Three.js code. For me this was around 1,000 objects. You can compare R3R to Three.js under “Benchmarks” in the examples.

The Chrome DevTools Timeline feature is an amazing tool for debugging performance. It’s easy to visually inspect your game loop, and it’s more readable than the “Profile” feature of the DevTools.

That’s It!

Check out Charisma The Chameleon to see what’s possible using this setup. While this tool chain is still quite young, I’ve found React with R3R to be integral to organizing my WebGL game code cleanly. You can also check out the small but growing R3R examples page to see some well organized code samples.

What do you think – have you already tried using React to organize your JavaScript game code? What did you make, and what were the pros and cons? Comment below and share your experiences!

Game with Three.js, ReactJS and WebGL in java

Game with Three.js, ReactJS and WebGL in java Posted on 22-09-2016  I’m making a game titled “Charisma The Chameleon.” It’s built with Three.js, ReactJS and WebGL. This is an introduction to how these technologies work together using react-three-renderer (abbreviated R3R). 5/10 353

Comment:

To comment you must be logged in members.

Files with category

  • JUnit 5 State Of The Union using java

    View: 593    Download: 0   Comment: 0   Author: none  

    JUnit 5 State Of The Union using java

    Category: Javascript
    Fields: Other

    2.25/2 review
    JUnit 5 has been under development for about 14 months now and the prototype is almost a year old. Time to summarize what happened so far, where the project stands, and where it’s going.

  • Getting Started with Dropwizard using java

    View: 683    Download: 0   Comment: 0   Author: none  

    Getting Started with Dropwizard using java

    Category: Javascript
    Fields: Other

    2.25/2 review
    Dropwizard is a framework for building RESTful web services in Java. In this tutorial we’re going to have a look at how to get started with developing a Dropwizard application by building a new service from scratch.

  • Build Query NULL Value in MySql

    View: 312    Download: 0   Comment: 0   Author: none  

    Build Query NULL Value in MySql

    Category: Javascript
    Fields: Other

    2.5/2 review
    Misunderstanding NULL is common mistake beginners do while writing MySql query. While quering in MySql they compare column name with NULL. In MySql NULL is nothing or in simple word it isUnknown Value so if you use comparison operator for NULL values...

  • Manage Your JavaScript Application State with MobX

    View: 328    Download: 0   Comment: 0   Author: none  

    Manage Your JavaScript Application State with MobX

    Category: Javascript
    Fields: Other

    2.25/2 review
    This article was peer reviewed by Michel Weststrate and Aaron Boyer. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

  • Build Bringing Pages to Life with the Web Animations API

    View: 339    Download: 0   Comment: 0   Author: none  

    Build Bringing Pages to Life with the Web Animations API

    Category: Javascript
    Fields: Other

    4.5/2 review
    This article is by guest author Dudley Storey. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the JavaScript community.

  • How to Style Google Custom Search Manually

    View: 318    Download: 0   Comment: 0   Author: none  

    How to Style Google Custom Search Manually

    Category: Javascript
    Fields: Other

    0/0 review
    Website owners very often decide on using Google’s Custom Search Engine (GCSE) for searching through their content instead of using built-in and/or custom search functionality. The reason is simple – it’s much less work, and most often it does the...

  • Test React Components Using Jest

    View: 5089    Download: 0   Comment: 0   Author: none  

    Test React Components Using Jest

    Category: Javascript
    Fields: Other

    4.5/1 review
    This article is by guest author Jack Franklin. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the JavaScript community.

  • Programming Question Reverse String without using String function

    View: 776    Download: 0   Comment: 0   Author: none  

    Programming Question Reverse String without using String function

    Category: Javascript
    Fields: Other

    4.5/1 review
    Write a program to reverse string without using string function. You don’t have to use any in-built string library function. This problem can be solved by multiple approaches. Let’s check it.

 
Newsletter Email

File suggestion for you

File top downloads

logo codetitle
Codetitle.com - library source code to share, download the file to the community
Copyright © 2015. All rights reserved. codetitle.com Develope by Vinagon .Ltd