UNPKG

threex

Version:

Game Extensions for three.js http://www.threejsgames.com/extensions/

608 lines (369 loc) 11.2 kB
title: Three.js Mini Game Workshop author: name: "Jerome Etienne" twitter: "@jerome_etienne" url: "http://jetienne.com" output: index.html -- # What Is Threex -- ### What we gonna do ? * a mini game called 'flying spaceship' * all in browser * three.js to get 3d * webaudio api to get sound -- ### Expect Final Result [demo](../index99.html) <img src="images/screenshot-final-result.png" style="width: 80%;"/> -- ### Steps * threejs boilerplate * then spaceships * then move it via keyboard * then planets and stars * then collisions * then sounds -- # Let's Get Started -- ### Install three.js boilerplate * Basic WebGL Page * only a moving cube * best practices already setup * tunable thru yeoman -- ### Three.js + yeoman * effort by google * "Modern Workflow for WebApps" * Composed of 3 tools: [bower](http://yeoman.io/packagemanager.html) / [grunt](http://gruntjs.com/) / [yo](https://github.com/yeoman/yo) ### Smoother * used to generate boilerplate with yo * used to handle packages with bower * **but not required** -- ### Install three.js boilerplate Make folder mkdir flyingspaceship cd flyingspaceship Generate boilerplate with yeoman yo threejs-boilerplate -- ### Install three.js boilerplate Serves Static Files make server -- ### Result [demo](../step0-00-naked-boilerplate.html) <img src="images/step0-00-naked-boilerplate.png" style="width: 80%;"/> -- ## That's a start... # Let's Add SpaceShips -- ### threex.spaceships * got it from threex extensions * install with bower * or get the files on [github](https://github.com/jeromeetienne/threex.spaceships) ``` bower install threex.spaceships ``` -- # Wait! ## What is threex ? -- ### A Bit on threex ? * ultra light extension system for [three.js](http://mrdoob.github.io/three.js/) * [threex](http://jeromeetienne.github.io/threex/) on github - 28 modules and counting <img src='images/screenshot-threex-homepage.png' width='100%' height='400px'></iframe> -- ### threex modules with require.js * Most threex extension support require.js * Convention: ```package.require.js``` at project root * require this file to load the module ### Required ? * Optional * Feel free to pick another tech if you wish * Faster to dev tho -- ### Include it in the code Find the require line and add require([ 'bower_components/threex.spaceships/package.require.js' , 'bower_components/threex.spaceships/examples/vendor/three.js/examples/js/loaders/OBJMTLLoader.js' , 'bower_components/threex.spaceships/examples/vendor/three.js/examples/js/loaders/OBJLoader.js' , 'bower_components/threex.spaceships/examples/vendor/three.js/examples/js/loaders/MTLLoader.js' ], function(){ // ... }); -- ### Add SpaceShip put that after the scene init var spaceship = null; THREEx.SpaceShips.loadSpaceFighter03(function(object3d){ scene.add(object3d) spaceship = object3d }) -- ### Result [demo](../step1-00-spaceship-cube.html) <img src="images/step1-00-spaceship-cube.png" style="width: 80%;"/> -- ## Almost... Let's remove the cube :) [demo](../step1-01-naked-spaceship.html) <img src="images/step1-01-naked-spaceship.png" style="width: 80%;"/> -- ## Not Bad... lack of interactivity # Controls by Keyboard -- ### threex.keyboardstate * to keep the current state of the keyboard. * threex module for three.js * github [repo](https://github.com/jeromeetienne/threex.keyboardstate/) / [demo](http://jeromeetienne.github.io/threex.keyboardstate/examples/basic.html) * blog post explaining internals [here](http://learningthreejs.com/blog/2011/09/12/lets-Make-a-3D-game-keyboard/) * with bower and require.js again -- ### Basic Usage var keyboard = new THREEx.KeyboardState(); if( keyboard.pressed("shift+H") ){ console.log('you are pressing shift and H') } -- ### threex.keyboardstate setup Install it with bower ```bower install threex.keyboardstate``` Include it with require.js require([ 'bower_components/threex.keyboardstate/package.require.js' ], function(){ // ... }); Done... not too hard like last time -- ### Controls Player With Keyboard The Algo * add a function in the rendering loop * monitor keyboard state * move spaceship accordingly Pitfalls * async in spaceship loading * speed independent of fps -- ### The Code // create keyboard instance var keyboard = new THREEx.KeyboardState(); // add function in rendering loop onRenderFcts.push(function(delta, now){ // only if the spaceship is loaded if( spaceship === null ) return; // set the speed var speed = 1; // only if spaceships is loaded if( keyboard.pressed('down') ){ spaceship.position.y -= speed * delta; }else if( keyboard.pressed('up') ){ spaceship.position.y += speed * delta; } }) -- ## Result [demo](../step2-00-with-keyboard.html) <img src="images/step1-01-naked-spaceship.png" style="width: 80%;"/> -- ## What goes well with spaceships ? # Let's add planets -- ### threex.planets * content module for threex * available in [threex.planets](https://github.com/jeromeetienne/threex.planets) * blog post explaining internals [here](http://learningthreejs.com/blog/2013/09/16/how-to-make-the-earth-in-webgl/) * with bower and require.js again -- ### Earth demo [link](http://jeromeetienne.github.io/threex.planets/examples/earth.html) Earth, cloud, atmosphere, stars, moon, shadow <img src="images/screenshot-threex-planets-demo-earth.png" style="width: 80%;"/> -- ### Select Any planets [link](http://jeromeetienne.github.io/threex.planets/examples/select.html#Uranus) based on [planetpixelemporium](http://planetpixelemporium.com/planets.html) <img src="images/screenshot-threex-planets-examples-select.png" style="width: 80%;"/> -- ### threex planets with bower ```bower install threex.planets``` Now it is in ```bower_components/threex.planets/``` Rather Easy... -- ### threex planets with require.js Find require.js call in the header and put that require([ 'bower_components/threex.planets/package.require.js' ], function(){ // ... }); Done... not too hard -- ### The Code var moonMesh = THREEx.Planets.createMoon() scene.add(moonMesh) -- ### The Result [link](../step3-00-simple-moon.html) <img src="images/step3-00-simple-moon.png" style="width: 80%;"/> -- ## a bit overcrowded -- ### Move Spaceship Away spaceship = object3d spaceship.rotateY(Math.PI/2) spaceship.position.x = -1 The Result [link](../step3-01-spaceship-away-moon.html) <img src="images/step3-01-spaceship-away-moon.png" style="width: 80%;"/> -- ### Make The Moon Moves Initial position function resetMoon(){ moonMesh.position.x = 5 moonMesh.position.x += 5 * (Math.random()-0.5) moonMesh.position.y = 2 * (Math.random()-0.5) } resetMoon() -- ### Make The Moon Moves Animate the moon and handle limits onRenderFcts.push(function(delta, now){ // move the moon to the left moonMesh.position.x += -1 * delta; // make it warp if( moonMesh.position.x < -3 ) resetMoon() }) -- ### The Result [link](../step3-02-moving-moon.html) <img src="images/step3-02-moving-moon.png" style="width: 80%;"/> -- ## Grey Background ? Not Too Shabby # Let's add Stars! -- ### Stars * part of threex.planets * no install needed -- ### How ? with a *environmantal sphere* * Large Sphere * we are at its center * we see the inside of it * with a proper texture it does the tricks -- ### The Texture Part of threex.spaceships module <iframe src='../bower_components/threex.planets/examples/images/galaxy_starfield.png' width='100%' height='400px'></iframe> -- ### The Code a geometry var geometry = new THREE.SphereGeometry(90, 32, 32) a material var url = 'bower_components/threex.planets/examples/images/galaxy_starfield.png' var material = new THREE.MeshBasicMaterial({ map : THREE.ImageUtils.loadTexture(url), side : THREE.BackSide }) a mesh var starSphere = new THREE.Mesh(geometry, material) scene.add(starSphere) -- ### The Result [link](../step4-00-stars-sphere.html) <img src="images/step4-00-stars-sphere.png" style="width: 80%;"/> -- ## a bit of Game Play # Let's add Collision -- ### Collision for GamePlay * **Goal**: destroy moons * **Means**: going thru the moon destroy it -- ### Algo * collide if distance < 3 * if contact, reset moon position ### Pitfalls * async model loading * spaceship isn't spheric -- ### Code to add onRenderFcts.push(function(delta, now){ // only if the spaceship is loaded if( spaceship === null ) return // compute distance between spaceship and the moon var distance = moonMesh.position.distanceTo(spaceship.position) if( distance < 0.3 ){ resetMoon() } }) -- ### The Result [link](../step5-00-collision.html) <img src="images/step5-00-collision.png" style="width: 80%;"/> -- ## What about sounds # Let's make some noise -- ### Use Web Audio API * low latency sound API for games * [webaudiox.js](https://github.com/jeromeetienne/webaudiox) : bunch of helpers * heavily documented * Explosion Sound from [freesounds.org](http://www.freesound.org) -- ### Installation with bower ```bower install webaudiox``` now files are in ```bower_components/webaudiox``` as usual ### Include it with require.js require([ 'bower_components/webaudiox/build/webaudiox.js' ], function(){ // ... }); -- ### Init Web Audio var context = new AudioContext() var lineOut = new WebAudiox.LineOut(context) lineOut.volume = 0.2 ### Load Sound var soundBuffer; // load the sound var soundUrl = 'sounds/102720__sarge4267__explosion.wav' WebAudiox.loadBuffer(context, soundUrl, function(buffer){ soundBuffer = buffer }) -- ### Function to play // setup a play function function playExplosionSound(){ if( !soundBuffer ) return var source = context.createBufferSource() source.buffer = soundBuffer source.connect(lineOut.destination) source.start(0) return source } ### Play Sound on contact var distance = moonMesh.position.distanceTo(spaceship.position) if( distance < 0.3 ){ resetMoon() playExplosionSound() } -- ### Result [link](../step6-00-explosion.html) <img src="images/step6-00-explosion.png" style="width: 80%;"/> -- ## and we are ... # DONE! -- ### Let's Pat our back * pure html5 game * 3d models * collision * sounds * mini gameplay #### not bad! -- ### Result [link](../step99.html) <img src="images/step99.png" style="width: 80%;"/> -- ### not bad for less than 1h * Thanks to threex modules * Thanks to three.js boilerplate * Thanks to yeoman #### Make it real easy