This chapter explains how to manage external assets such as 3D models, as well as add details to your worlds with particle systems, sound, and graphic effects. It will also elaborate on the arena first-person shooter game we built in Chapter 3, Exploring and Interacting, to turn it into a Capture-the-Flag game.
You're reading from Game Development with Three.js
In order to have a proper Capture-the-Flag game, we first need to have teams. There are several things that need to be associated with a given team:
Flags (and the flag color)
Players (and the player skins)
Spawn points
Bullets (if you want to avoid same-team damage)
Potentially map decorations/materials
The simplest way to associate each of these elements with a team is to just add a property with a simple value such as R
or B
to represent Red or Blue (or some other team name). A more advanced approach could be to create a Team
class that holds references to everything that belongs to that team, since that could offer optimizations such as limiting the number of collision checks that need to be performed. If you do that, however, make sure you remove all the appropriate references from the Team
container when removing something (such as a bullet) from the world in order to avoid memory leaks.
Next, we need to modify our map to add flags for the Red and Blue teams, which we'll represent...
Primitive geometric shapes are great for tests, but any serious game these days will likely make heavy use of 3D models created in a specialized program such as Blender, Maya, or 3ds Max. These models need to be imported into Three.js scenes and converted to THREE.Mesh
objects with geometry and materials. Luckily, Three.js provides importers called loaders for a variety of file formats.
For our flags, we'll use a simple mesh in Collada format. (Collada is an XML-based format for storing 3D mesh and animation data, with files ending in .dae
.) You can download our flag mesh from the Packt Publishing website. The ColladaLoader
is not included in the main Three.js library, but can be copied from examples/js/loaders/ColladaLoader.js
and then included in your HTML as:
<script src="ColladaLoader.js"></script>
Then the model can be loaded like this:
var loader = new THREE.ColladaLoader(); loader.load('flag.dae', function(result) { scene.add(result.scene); });
Often...
Now that our flags are in place and we've learned how to manage the resources we'll need to decorate our world, let's add some additional visual effects. The first type of effect we'll look at is particle systems.
Particles are planes that always face the camera, usually grouped together into a system to create some effect like fire or steam. They are essential for creating great visuals like this colorful heart:
We'd like to set off a celebratory fireworks-style display when the player captures a flag, so if you haven't already done so, go ahead and add the mechanics of capturing flags. The core logic should be in a function we'll call for each player in our physics loop:
function checkHasFlag(unit) { var otherFlag = unit.team === TEAMS.R ? TEAMS.B.flag : TEAMS.R.flag; if (unit.hasFlag) { var flag = unit.team === TEAMS.R ? TEAMS.R.flag : TEAMS.B.flag; if (flag.mesh.visible...
Although Three.js is a graphics library, there is an experimental THREE.AudioObject
class at examples/js/AudioObject.js
that uses the Web Audio API to support 3D sound effects. This object inherits from Object3D
so it can be attached to other objects and placed in the world. It is designed to use spatially accurate 3D sound. The main caveat is that the class only works with Chrome as of Three.js version r61 due to browser incompatibilities.
That said, let's go ahead and try adding some cheering sounds when a flag is captured. First, we'll create our AudioObject
instances when we initialize our flags:
var cheering = new THREE.AudioObject('cheering.ogg', 0, 1, false); scene.add(cheering);
This code creates an object to play the cheering.ogg
file with a volume of 0
, a playback rate of 1
, and no looping. We set the volume to zero initially because AudioObject
plays the sound immediately, and...
Sometimes, effects that change the entire display can give a game or area a lot of personality. Three.js supports two major kinds of effects: renderer and postprocessing.
Renderer effects can be found in examples/js/effects
. They change what the renderer outputs, usually by rendering the scene multiple times with different settings. For example, the Anaglyph effect produces the familiar red-and-blue shadows that work with 3D glasses to make the scene pop out of the screen, and it does this by rendering the scene once for the left eye, once for the right eye, and once combined. Setting this up is easy:
effect = new THREE.AnaglyphEffect(renderer); effect.setSize(renderer.domElement.width, renderer.domElement.height);
Then just call effect.render(scene, camera)
instead of renderer.render(scene, camera)
. All of the other renderer effects work the same way except the ASCII effect, which requires adding a separate canvas so it can render the scene to text characters...
In this chapter, we learned how to manage 3D models and animation. We also explored particle systems, sound, and visual effects. Additionally, we used what we learned to transform our first-person shooter game from Chapter 3, Exploring and Interacting into a Capture-the-Flag game. In the next chapter, we'll discuss game design concepts, workflow processes, performance considerations, and networking.