topical media & game development

talk show tell print

mobile-query-three-plugins-ogsworkshop-examples-game080.htm / htm



  <!--
          i want to pick my own skin
  	* add dom element on top
  	* function updatePlayer()
  	* hook it to the network code
  -->        
  
  <!doctype html><title>Minimal tQuery Page</title>
  <script src="../../../build/tquery-bundle-require.js"></script>
  
  <!-- all network scripts -->
  <script src="http://localhost:4000/socket.io/socket.io.js"></script>
  <script src="http://localhost:4000/examples/client.js"></script>
  
  <body><div style="position: absolute; font-size: 200%; right: 0; z-index: 1; text-align: right;">
          <select id="skinSelect">
                  <option value="char.png">char</option>
                  <option value="3djesus.png">3djesus</option>
                  <option value="agentsmith.png">agentsmith</option>
                  <option value="batman.png">batman</option>
                  <option value="god.png">god</option>
                  <option value="Joker.png">Joker</option>
                  <option value="Mario.png">Mario</option>
                  <option value="martialartist.png">martialartist</option>
                  <option value="robocop.png">robocop</option>
                  <option value="Sonicthehedgehog.png">Sonic the hedgehog</option>
                  <option value="Spiderman.png">Spiderman</option>
                  <option value="Superman.png">Superman</option>
                  <option value="theflash.png">theflash</option>
                  <option value="woody.png">woody</option>
                  <option value="Iron-Man-Minecraft-Skin.png">ironman</option>
          </select>
          <form action="javascript:void(0)" id='nicknameForm' style='display: inline-block'>
                  <input type="text"/>
          </form>
  </div><script>
  require(['tquery.minecraft', 'tquery.skymap', 'tquery.grassground', 'tquery.keyboard'
          , 'tquery.shadowmap'], function(){
          // create world
          var world        = tQuery.createWorld().boilerplate().start();
  
          // enable shaddow in the renderer
          world.tRenderer().shadowMapEnabled        = true;
          world.tRenderer().shadowMapSoft                = true;
  
          // add a skybox
          tQuery.createSkymap('skybox').addTo(world);
  
          // add a ground        
          var ground  = tQuery.createGrassGround({
                  textureRepeatX  : 20,
                  textureRepeatY  : 20,
          }).addTo(world)
                  .scale(80)
                  .receiveShadow(true)
          
          ground.get(0).material.map.anisotropy = 16;
  
  

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

// lights //

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

var light = tQuery.createDirectionalLight().addTo(world) .position(-1, 2, 3) .color(0xffffff).intensity(4) .castShadow(true) .shadowDarkness(0.4) .shadowMap(512*2,512*2) .shadowCamera(8, -8, 8, -8, 0.1, 10) .shadowCameraVisible(true) // for light to follow character world.loop().hook(function(){ if( !players[mySourceId] ) return; var player = players[mySourceId]; var character = player.character; var model = character.object3D('root'); light.get(0).target.position.copy(model.position()); var delta = tQuery.createVector3(-1,2,3); var position = model.position().clone().addSelf(delta); light.position(position) });

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

// network //

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

// init the gameServer var mySourceId = null; var players = {}; // initiate connect with server var serverUrl = 'http://localhost:4000'; var userInfo = { nickName : 'Player-'+Math.floor(Math.random()*10000).toString(16), skinBasename : 'char.png', }; var gameServer = new SimpleMMOServer('public', userInfo, serverUrl); // handle event gameServer.addEventListener('connected', function(sourceId, usersInfo){ console.log('connected', arguments) createMyPlayer(sourceId, gameServer.userInfo()) Object.keys(usersInfo).forEach(function(sourceId){ var userInfo = usersInfo[sourceId]; createPlayer(sourceId, userInfo) }); }); gameServer.addEventListener('userJoin', function(data){ console.log('userJoin', arguments) createPlayer(data.sourceId, data.userInfo); }); gameServer.addEventListener('userLeft', function(data){ console.log('userLeft', data) destroyPlayer(data.sourceId); }); gameServer.addEventListener('clientEcho', function(data){ console.assert( players[data.sourceId] ); if( data.message.type === 'positionChange' ){ if( data.sourceId === mySourceId ) return; var player = players[data.sourceId]; var mesh = player.character.object3D('root') mesh.positionX( data.message.position.x ) mesh.positionY( data.message.position.y ) mesh.positionZ( data.message.position.z ) mesh.rotationX( data.message.rotation.x ) mesh.rotationY( data.message.rotation.y ) mesh.rotationZ( data.message.rotation.z ) }else{ console.log('unknown echo message.type', message.type) } }); gameServer.addEventListener('userInfo', function(sourceId, curUserInfo, oldUserInfo){ //console.log('userInfo', arguments) updatePlayer(sourceId, curUserInfo, oldUserInfo) });

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

// handle player animation //

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

setInterval(function(){ Object.keys(players).forEach(function(sourceId){ var player = players[sourceId]; var mesh = player.character.object3D('root') var velocity = mesh.position().clone().subSelf(player.prevPosition); if( velocity.length() ){ player.bodyAnims.start('run') }else{ player.bodyAnims.start('stand') } // update player.prevPosition/player.prevRotation player.prevPosition.copy( mesh.position() ) player.prevRotation.copy( mesh.rotation() ) }) }, 1000/5); // Important to be less than framerate - thus you dont misdetect still

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

// UI //

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

document.body.setAttribute("tabIndex", "0"); // make body focusable // handle nicknameForm var nicknameForm = document.getElementById('nicknameForm') nicknameForm.addEventListener('keydown', function(event){ event.stopPropagation(); }); // handle nick dom element nicknameForm[0].value = gameServer.userInfo().nickName; nicknameForm.addEventListener('submit', function(){ var myUserInfo = gameServer.userInfo(); // update myUserInfo myUserInfo.nickName = nicknameForm[0].value; // notify the server gameServer.userInfo(myUserInfo); // put back the focus on body document.body.focus(); }); // handle skin dom element var skinSelectEl = document.getElementById('skinSelect') skinSelectEl.addEventListener('change', function(){ var myUserInfo = gameServer.userInfo(); // update myUserInfo myUserInfo.skinBasename = skinSelectEl.value; // notify the server gameServer.userInfo(myUserInfo); // put back the focus on body document.body.focus(); });
////////////////////////////////////////////////////////////////////////////

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

function createMyPlayer(sourceId, userInfo){ console.assert(mySourceId === null) mySourceId = sourceId; createPlayer(mySourceId, userInfo) var character = players[mySourceId].character; // to enable a tracking camera var cameraControls = tQuery.createCameraFpsControls({ trackedObject : character.object3D('root').get(0), tCamera : world.tCamera() }); world.setCameraControls(cameraControls) //cameraControls.deltaCamera().position(0, 0.7, -0.07)

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

// user controls on keyboard //

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

tQuery.createMinecraftCharKeyboard2({ object3D : character.object3D('root').get(0), lateralMove : 'rotationY', //lateralMove : 'strafe' }); // periodically send the position of the character // - NOTE: not done on requestAnimationFrame as it has to be done even if page isnt visible setInterval(function(){ var mesh = character.object3D('root'); var position = mesh.position(); var rotation = mesh.rotation(); gameServer.clientEcho({ type : 'positionChange', position: { x : position.x, y : position.y, z : position.z }, rotation: { x : rotation.x, y : rotation.y, z : rotation.z }, }); }, 1000/60); } function createPlayer(sourceId, userInfo){ console.assert(players[sourceId] === undefined); players[sourceId] = {} // create the minecraft character var skinUrl = '../../minecraft/examples/images/'+userInfo.skinBasename; var character = tQuery.createMinecraftChar({ skinUrl : skinUrl }).addTo(world); tQuery('mesh', character.object3D('root')).castShadow(true) // store it players[sourceId].character = character; // add a nickname cartouche tQuery.createSprite().addTo(character.object3D('root')) .addClass('cartouche') .scaleBy(1/200).positionY(1.1) .map(buildNickCartouche(userInfo.nickName)) // init bodyAnims var bodyAnims = new tQuery.MinecraftCharAnimations(character); bodyAnims.start('run'); players[sourceId].bodyAnims = bodyAnims; // init prevPosition/prevRotation to estimate velocity later players[sourceId].prevPosition = tQuery.createVector3() players[sourceId].prevRotation = tQuery.createVector3() } function destroyPlayer(sourceId){ var player = players[sourceId]; player.character.removeFrom(world) player.bodyAnims.stop() delete players[sourceId] } function updatePlayer(sourceId, curUserInfo, oldUserInfo){ console.assert(players[sourceId] !== undefined); var otherInfo = players[sourceId]; var character = otherInfo.character; // update the nickname cartouche if needed if( !oldUserInfo || curUserInfo.nickName !== oldUserInfo.nickName ){ var texture = tQuery('.cartouche', character.object3D('root')).get(0).map; texture.image = buildNickCartouche(curUserInfo.nickName) texture.needsUpdate = true; } // update the skin if needed if( !oldUserInfo || curUserInfo.skinBasename !== oldUserInfo.skinBasename ){ var skinUrl = '../../minecraft/examples/images/'+curUserInfo.skinBasename; character.loadSkin(skinUrl) } } function buildNickCartouche(text){ // create the canvas var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); canvas.width = 256; canvas.height = 128; // center the origin context.translate( canvas.width/2, canvas.height/2 ); // measure text var fontSize = 36; context.font = "bolder "+fontSize+"px Verdana"; var fontH = fontSize; var fontW = context.measureText(text).width; // build the background context.fillStyle = "rgba(0,0,255,0.3)"; var scale = 1.2; context.fillRect(-fontW*scale/2,-fontH*scale/1.3,fontW*scale,fontH*scale) // display the text context.fillStyle = "rgba(0,0,0,0.7)"; context.fillText(text, -fontW/2, 0); // return the canvas element return canvas; } }) </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.