topical media & game development

talk show tell print

mobile-query-three-plugins-iimminigame-examples-index.htm / htm



  <!doctype html><title>PongGL</title>
  <script src="../../../build/tquery-bundle.js"></script>
  
  <script src="../../../vendor/threex/THREEx.KeyboardState.js"></script>
  <script src="../../keyboard/tquery.keyboard.js"></script>
  
  <script src="../../../vendor/three.js/ShaderExtras.js"></script>
  <script src="../../../vendor/three.js/postprocessing/EffectComposer.js"></script>
  <script src="../../../vendor/three.js/postprocessing/BloomPass.js"></script>
  <script src="../../../vendor/three.js/postprocessing/DotScreenPass.js"></script>
  <script src="../../../vendor/three.js/postprocessing/FilmPass.js"></script>
  <script src="../../../vendor/three.js/postprocessing/MaskPass.js"></script>
  <script src="../../../vendor/three.js/postprocessing/RenderPass.js"></script>
  <script src="../../../vendor/three.js/postprocessing/SavePass.js"></script>
  <script src="../../../vendor/three.js/postprocessing/ShaderPass.js"></script>
  <script src="../../../vendor/three.js/postprocessing/TexturePass.js"></script>
  <script src="../../pproc/tquery.effectcomposer.js"></script>
  
  <script src='../../grassground/tquery.grassground.js'></script>
  
  <script src="../../skymap/tquery.cubetexture.js"></script>
  <script src="../../skymap/tquery.skymap.js"></script>
  
  <script src='../../shadowmap/tquery.light.shadowmap.js'></script>
  
  <script src="vendor/webaudio.js"></script>
  <script src="vendor/webaudio.sound.jsfx.js"></script>
  <script src="vendor/jsfx/audio.js"></script>
  <script src="vendor/jsfx/jsfx.js"></script>
  <script src="vendor/jsfx/jsfxlib.js"></script>
  
  <script src="../../tweenjs/examples/Tween.js"></script>
  
  <style>
  .score        {
          position        : absolute;
          top                : 0px;
          z-index                : 1;
  
          font-family        : arial, verdana, sans-serif;
          font-size        : 800%;
          font-weight        : bolder;
  
          color                : #dddddd;
          text-shadow        : 0 0 0.2em #F87, 0 0 0.2em #F87, 0 0 0.2em #F87;
  
          padding-left        : 10px;
          padding-right        : 10px;
  };
  #scoreLeft {
          left                : 0;        
  }
  #scoreRight {
          right                : 0;        
  }
  </style>
  <body>
  <div id="scoreLeft"        class="score">0</div>
  <div id="scoreRight"        class="score">0</div>
  <script>
          // init audio layer
          var webaudio        = new WebAudio();
          webaudio.volume(0.5)
          // init each sound
          var jsfxParam        = ["saw",0.0000,0.4000,0.0000,0.1640,0.0000,0.1880,20.0000,594.0000,2400.0000,0.5440,0.0000,0.0000,0.0100,0.0003,0.0000,0.0000,0.0000,0.0000,0.0000,0.5616,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000];
          var soundRacketWall        = webaudio.createSound().generateWithJsfx(jsfxParam);
          var jsfxParam        = ["square",0.0000,0.4000,0.0000,0.3560,0.0000,0.1900,20.0000,358.0000,2400.0000,0.3000,0.0000,0.0000,0.0100,0.0003,0.0000,0.0000,0.0000,0.1810,0.0000,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000];
          var soundRacketBall        = webaudio.createSound().generateWithJsfx(jsfxParam);
          soundRacketBall.volume(0.1)
          var jsfxParam        = ["square",0.0000,0.4000,0.0000,0.1640,0.0000,0.1380,20.0000,231.0000,2400.0000,0.0000,0.0000,0.0000,0.0100,0.0003,0.0000,0.0000,0.0000,0.0625,0.0000,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.1000,0.0000];
          var soundWall        = webaudio.createSound().generateWithJsfx(jsfxParam);
          soundWall.volume(0.1)
          var jsfxParam        = ["saw",0.0000,0.4000,0.0000,0.2800,0.0000,0.2380,20.0000,837.0000,2400.0000,-0.7300,0.0000,0.0000,0.0100,0.0003,0.0000,0.0000,0.0000,0.3235,0.0100,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000];
          var soundLose        = webaudio.createSound().generateWithJsfx(jsfxParam);
  
          // create a tQuery.World
          var world        = tQuery.createWorld().boilerplate().start();
          // no camera controls is needed
          world.removeCameraControls();
          world.tCamera().position.y        = 1.5;
          world.tCamera().position.z        = 3.2;
          world.tCamera().lookAt(world.tScene().position);
  
          // enable shadow in the renderer
          world.tRenderer().shadowMapEnabled        = true;
          world.tRenderer().shadowMapSoft                = true;
          
          // add a skybox
          tQuery.createSkymap('skybox').addTo(world);
  
          // create the ground
          tQuery.createPlane().addTo(world)
                  .receiveShadow(true)
                  .scale(3*1.5, 1, 1.8*1.5)
                  .translateY(-0.2)
                  .setLambertMaterial().map('../../grassground/images/grasslight-big.jpg').ambient(0x444444).back();
  
          // add postprocessing effects
          world.addEffectComposer()
                  //.motionBlur(0.7)
                  .vignette()
                  .finish();
  
          // lights
          tQuery.createAmbientLight().addTo(world).color(0x444444)
          tQuery.createPointLight().addTo(world).intensity(2).distance(30);
          tQuery.createDirectionalLight().addTo(world)
                  .position(2, 4, -1.5).color(0xffffff)
                  .castShadow(true)
                  .shadowCamera(2, -2, 2, -2, 0.01, 200)
                  .shadowDarkness(0.7).shadowBias(.002)
                  //.shadowCameraVisible(true);
  
          // some constants for players
          var players        = { "right" : {}, "left": {} };        
          var racketW        = 0.05;
          var racketD        = 0.5;
          var racketRangeY= 2;
          // init each player
          Object.keys(players).forEach(function(playerId){
                  var player        = players[playerId];
                  // create tQuery.Object3D for a racket
                  var url                = "../../physics/examples/images/rocks.jpg";
                  var playerColor        = playerId === 'right' ? 0xffaacc : 0xccaaff;
                  var object3d        = tQuery.createCube().addTo(world)
                                  .scale(racketW, 0.2, racketD)
                                  .setLambertMaterial().color(playerColor).ambient(0xaaaaaa).map(url).back()
                                  .id(playerId)
                                  .castShadow(true)
                  object3d.translateX(1.3 * (playerId === "right" ? +1 : -1));
                  player.object3d        = object3d;
          })
          
Function called when playerId scored a point

  
          function addScore(playerId){
                  var selector        = {
                          right        : '#scoreRight',
                          left        : '#scoreLeft'
                  }[playerId];
                  var element        = document.querySelectorAll(selector)[0];
                  var score        = parseInt(element.innerHTML);
                  score++;
                  element.innerHTML= score;
                  soundLose.play();
                  // reset ball velocity
                  ballAngle        = 0.2 * Math.random()*Math.PI*2;
                  ballVelX        = Math.cos(ballAngle)*0.03;
                  ballVelZ        = Math.sin(ballAngle)*0.03;
                  // put it back in the center
                  ball3d.position(0,0,0);
          };
          // handle player keyboard
          world.loop().hook(function(delta){
                  var keyboard        = tQuery.keyboard();
                  var speedY        = 2;
                  if( keyboard.pressed('up') )        players['right'].object3d.translateZ(-delta*speedY);
                  if( keyboard.pressed('down') )        players['right'].object3d.translateZ(+delta*speedY);
                  if( keyboard.pressed('q') )        players['left'] .object3d.translateZ(-delta*speedY);
                  if( keyboard.pressed('w') )        players['left'] .object3d.translateZ(+delta*speedY);
                  // handle racket limit
                  Object.keys(players).forEach(function(playerId){
                          var tMesh        = players[playerId].object3d.get(0);
                          if( tMesh.position.z < -fieldD/2 + racketD/2 )        soundRacketWall.play();
                          if( tMesh.position.z > +fieldD/2 - racketD/2 )        soundRacketWall.play();
                          tMesh.position.z        = Math.max(tMesh.position.z, -fieldD/2 + racketD/2);
                          tMesh.position.z        = Math.min(tMesh.position.z, +fieldD/2 - racketD/2);
                  });
          });
          
Function called when the ball touch the racket

  
          players['right'].onContact = players['left'].onContact = function(player, ball3d){
                  // play a sound
                  soundRacketBall.play();
  
                  // increase velocity 
                  ballVelX         *= 1.1;
                  ballVelZ        *= 1.1;
                  
                  if( false ){
                          var deltaZ        = player.object3d.get(0).position.z - ball3d.get(0).position.z;
                          deltaZ                /= racketD;
  
                          var speed        = Math.sqrt(ballVelX*ballVelX+ballVelZ*ballVelZ)
                          var ballAngle        = Math.atan2(ballVelZ,ballVelX);
                          console.log(Math.atan2(ballVelZ,ballVelX)/Math.PI*180)
                          
                          var maxDeltaAng        = 30 * Math.PI/180;
                          var deltaAngle        = deltaZ * 2 * maxDeltaAng;
                          ballAngle        += deltaAngle * (player.object3d.id() === "right" ? +1 : -1);
                          
                          ballVelX        = Math.cos(ballAngle)*speed;
                          ballVelZ        = Math.sin(ballAngle)*speed;                        
                  }
                  // change racket color randomly
                  player.object3d.get(0).material.color.setHex(0xFfffff*Math.random());
          };
  
          // constant for the field
          var fieldW        = 3;
          var fieldD        = 1.8;
          // constant for the ball
          var ballRadius        = 1/5;
          var ballAngle        = Math.random()*Math.PI*2;
          var ballAngle        = 0.2 * Math.random()*Math.PI*2;
          var ballVelX        = Math.cos(ballAngle)*0.03;
          var ballVelZ        = Math.sin(ballAngle)*0.03;
          // create a tQuery.Object3d for the ball
          var ball3d        = tQuery.createSphere().addTo(world).scaleBy(ballRadius)
                          .setLambertMaterial().color(0xFFFF00).ambient(0xFFFFFF).map("../../physics/examples/images/rocks.jpg").back()
                          .castShadow(true)
          world.loop().hook(function(){
                  // get ball position
                  var position        = ball3d.get(0).position;
                  // update position
                  position.x        += ballVelX;        
                  position.z        += ballVelZ;
                  // handle border contact
                  if( position.z < -fieldD/2 + ballRadius/2)        wallOnContact(walls['north'])
                  if( position.z > +fieldD/2 - ballRadius/2)        wallOnContact(walls['south'])
                  // handle score
                  if( position.x < -fieldW/2 + ballRadius/2)        addScore('right');
                  if( position.x > +fieldW/2 - ballRadius/2)        addScore('left');
                  
                  // bounce the ball if it reach the border
                  if( position.x < -fieldW/2 + ballRadius/2)        ballVelX        *= -1;
                  if( position.x > +fieldW/2 - ballRadius/2)        ballVelX        *= -1;
                  if( position.z < -fieldD/2 + ballRadius/2)        ballVelZ        *= -1;
                  if( position.z > +fieldD/2 - ballRadius/2)        ballVelZ        *= -1;
  
                  // get the boundaries
                  position.x        = Math.max(position.x, -fieldW/2+ballRadius/2);
                  position.x        = Math.min(position.x, +fieldW/2-ballRadius/2);
                  position.z        = Math.max(position.z, -fieldD/2+ballRadius/2);
                  position.z        = Math.min(position.z, +fieldD/2-ballRadius/2);
                  // check collision with each player racket
                  ["right", "left"].forEach(function(playerId){
                          // get tQuery.Object3D for this player
                          var player        = players[playerId];
                          var object3d        = player.object3d;
                          // get the position in X and Y
                          var racketX        = object3d.get(0).position.x;
                          var racketZ        = object3d.get(0).position.z;
                          // test each ball boundary
                          var mayHitLeft        = (position.x+ballRadius/2) >= (racketX-racketW/2);
                          var mayHitRight        = (position.x-ballRadius/2) <= (racketX+racketW/2);
                          var mayHitTop        = (position.z+ballRadius/2) >= (racketZ-racketD/2);
                          var mayHitBottom= (position.z-ballRadius/2) <= (racketZ+racketD/2);
                          // test if there is collision
                          if( mayHitLeft && mayHitRight && mayHitTop && mayHitBottom ){
                                  // reaction of a collision
                                  ballVelX        *= -1;
                                  var deltaX        = racketW/2 + ballRadius/2;
                                  position.x        = racketX + (playerId === "right"? -deltaX : +deltaX);
                                  player.onContact && player.onContact(player, ball3d);
                          }
                  });
          });
  
  

/////////////////////////////////////////////////////////////////

// Walls //

/////////////////////////////////////////////////////////////////

var walls = {}; var url = "../../physics/examples/images/plywood.jpg"; walls['north'] = tQuery.createCylinder(0.05, 0.05, 3, 16, 4).addTo(world) .setLambertMaterial().color(0xFFFFFF).ambient(0xFFFFFF).map(url).back() .geometry().rotateZ(Math.PI/2).back() .translateY(-0.1) .translateZ(-1.8/2 - 0.05/2) .castShadow(true) walls['south'] = tQuery.createCylinder(0.05, 0.05, 3, 16, 4).addTo(world) .setLambertMaterial().color(0xFFFFFF).ambient(0xFFFFFF).map(url).back() .geometry().rotateZ(Math.PI/2).back() .translateY(-0.1) .translateZ(+1.8/2 + 0.05/2) .castShadow(true) function wallOnContact(object){ soundWall.play(); var tweenvars = { scale : 1 }; var tweenFwd = new TWEEN.Tween(tweenvars).to({ scale : 2 }, 100).easing(TWEEN.Easing.Elastic.Out).onUpdate(function(){ object.scale(1, this.scale, this.scale); }); // setup a backward tween var tweenBack = new TWEEN.Tween(tweenvars).to({ scale : 1 }, 200).easing(TWEEN.Easing.Linear.None) .onUpdate(function(){ object.scale(1, this.scale, this.scale); }); tweenFwd.chain(tweenBack); tweenFwd.start(); } // update TWEEN with world.loop world.loop().hook(function(){ TWEEN.update(); }); </script></body>


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.