Developing a street basketball game. Part ll: Throw a ball into a basket.

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

This time we will talk about creating of basketball net (with physics), the way we will keep the ball, and throw it in different directions depending on mouse position. If you haven’t read a Part 1: Getting workflow ready, read it first, please. I describe there what to start with, how to create basic scene elements (ball, basket, wall and ground).

In this post i will try to describe in-game mechanics as much as possible and how all this things interact in Three.js and Ammo.js wrapped by Whitestorm.js framework. Without this framework there will be much more unnecessary code used. One more thing is softbody physics… in javascript… I have told you that we are going to create a net that will be shaked when it collides with the ball, not a scripted animation that happens when we score a goal, but a complete physics for net and ball collisions.

Two more files.

We compile this project using rollup.js, it means we can use es6 modules without any restrictions. Let’s add two files that will handle: 1) Events, 2) Loops.

App “js” folder structure

We’ll back to them soon, but let’s create a backboard and a basketball net first.

Backboard & basketball net

Backboard is just a WHS.Box with applied map, normalMap (defines how light will be casted on texture) and displacementMap. Backboard will be 41 x 28 and with depth of 1. We don’t want backboard to fall down, so it’s mass will be 0 as with wall and ground.

Net has a cylinder geometry with radiusTop bigger than radiusBottom. It is created from softTrimesh object, unlike softClothMesh it also has pressure property which defines how fast will this object return to it’s default state. This cylinder will be openEnded and have no bottom and top (Just like we need).

Number of segments will be different for desktop and mobile or tablet devices. This is used to make optimizations on mobile devices to make it as fast as it should be (like we have on desktops).

Setting config and variables…

We have already added some configuration details and isMobile variable. Now it’s time to fill all other properties and explain for what do we need each one.

I made this gist to describe each configuration or variable used in app:

We use arrow functions if we want to use other configuration settings to form a new one because other way they will return undefined because APP hasn’t been defined before they called.

New file: events.js

I splitted app.js into several files to make it smaller and show how to use ES6 module syntax in such apps. The first file i created will contain functions that register events:

Also note that we should pass APP variable in each function that should interact with main app and it’s variables.

There we see that some event handlers need to be added to app.js file, we also need to call all this functions to make them work:

We just added 4 new functions, let’s explain them:

initEvents(), starts all event handlers.

starts all event handlers. updateCoords(), updates local cursor position variables.

updates local cursor position variables. checkKeys(), checks for “Spacebar” key pressed. If yes — resets ball position.

checks for “Spacebar” key pressed. If yes — resets ball position. detectDoubleTap(), does the same as checkKeys(), but with double tap event and is more useful for mobile devices.

New file: loops.js

To keep a ball we need reset it’s position on each frame. We’ll call keepBall() function for that. But it should do it only if ball isn’t previously thrown by player and haven’t been returned to it’s default position with pressed spacebar or double tap.

One more function called throwBall(), we use it simply to apply a certain impulse to a ball. Note that impulse is applied only once, so we need to pass large numbers there. For that we’ll use APP.force.m, a number that multiplies Y and Z values of impulse (usually a large value).

One thing left

There are only one thing that we forgot to do. I mean that we forgot to start our keep_ball loop, it should be in init() function, that’s why i left it for last part.

To start the loop we need to add it to the world first. Adding to the world means that loop will be executed in the same function (same time) that renders our world. Only after that we should start executing it.