Creating a 3D browser game with physics in a few steps.

Some days ago I released a new version of WhitestormJS framework named r10 and decided to develop a game using almost all it’s functionality. (Just was curious how easy it would be). The task was to make a 3D game that requires complex 3D physics parts like concave objects and softbodies.

Setting up workflow

Before starting developing the game I added a couple of directories that I will use later: js, css, textures and img. Difference between textures and img folders is that textures folder will be used for images that will be used in 3D part of app and img is for images that are used in html, css and stuff like that.

Rollup

Useful thing when you need to work with es6 models in front-end, especially when you use most of es6 features and want them even on old browser versions. I used it with two plugins: babel for rollup and uglify for rollup to develop a cross-browser 3D app.

Bower

Some libraries are getting updates regularly (yep, like whitestorm.js). For them I need front-end package manager like bower (You can use npm too, but bower will be enough). For tweening I used GSAP library, because of it’s performance and also we need basket.js to keep such a large library as WhitestormJS in localStorage.

…And also i wrote a small bower plugin that will help me make preloading. Check it out there.



bower install whitestormjs gsap progress-loader basket.js

Okay, now seems to be ready…

My index.html file will be simple and will contain just loaded scripts and style.css for featured usage. Note that we don’t load whitestorm.js yet. We will add it then using basket.js.

app.js

As you already noticed, we have app.js included. So, let’s create an empty 3D world with enabled softbody physics(will be used later for a net), autoresize, filled background, camera position and aspect, + gravity:

Now we have a basic world that has 0xcccccc (grey) as it’s background color, gravity set as {x: 0, y: -200, z: 0} and camera that will be at same height as our basket. Also we start the app only after we have whitestorm.js loaded.

I counted 14 objects that we will load for desktop devices. (I hope we’ll also have an optimized version for mobile devices, so i used APP.isMobile variable which is a boolean.

Creating a scene. Ground and a wall.

Next thing we’ll do is implementing a floor with just a ground and wall. Wall and ground will be very similar and we create them both from one object. We’ll create a default plane 1000×800 with buffer geometry (Actually no need for buffer geometry there, but somebody says it increase performance;), but it won’t be a big deal for a plane with 1×1 segments.

0 mass means that this object is not affected by gravity and won’t move when collides with other objects. And we need to rotate it’s by (-Math.PI / 2, 0, 0) euler.

When we add each object to world — it returns a promise which is resolved when object is generated and added to world. Such stuff is very useful when work with models or object’s you want to know they are ready. Such as when we need to update loading status when each one is added.

Lights

We need just 2 simple lights to get a cool effect. Ambient light will cast light on the whole scene, Point light will cast only on objects near basket.

That’s how it looks now:



Adding a basket

After we added lights we need to have a basket in which we will throw a ball. Our basket will be a simple torus with thin tube radius. Also I experimented with material parameters to get it metal look.

One more thing is that we set a “concave” physics object type. By default, in performance reason each mesh with concave geometry works as a convex mesh for physics, but you can simply make it concave by setting this parameter. We make it static by applying 0 mass to this object.

Adding a ball

Now it’s time to make a ball. This time we are going to use optimization for mobile devices again (geometry with less vertices. It won’t work with physics because when we process sphere collisions it’s enough to have just a sphere radius)

This time we also have to apply x3 restitution to make out sphere jump like a basketball ball.

We use 2 textures for ball material. First one (in map parameter) is a default colored texture. Second one (normalMap) defines how light will be casted on this ball.

I generated a normal map using this normal map generator. I often use it. You can make a normal map not just from a black-white height map, for generating this one, I just used the first texture.

Summary

If everything done right, you should see something like this:

…And the ball will fall down…

Links

A result of this part is also available on github.

Full game: Github | Demo

This HTML5 blog post was written by Alexander Buzin.