THREE.JS を利用してFPSゲームを作ってみよう1
おはようございます。
最近Three.jsの勉強をしています。
それでThree.jsを使ってFPSゲームを作ってみようかと思いまして基本的なSourceを作ってみました。
現在FPS_base.html と FPS_Control.htmlがあります。
FPS_baseは名前とおりThree.jsのrendering構成Baseで
FPS_Controlはmouseやkeyboardに反応できるeventを追加してcameraを一人称視点で変えてみました。
FPS_base
FPS_Control
sourceはこんな感じです。FPS_BASEの構成の基本にして書きました。
[code lang="coffee"] (function() { var sw,sh, scene, camera,fov,aspect,near,far, renderer, light, stats; var chScene, chCamera; function init() { /* WINDOW SIZE */ sw = WindowSize.width(); sh = WindowSize.height(); /* SCENE SETTING*/ scene = new THREE.Scene(); /* RENDERER SETTING */ renderer = new THREE.WebGLRenderer({antialias : true}); renderer.setSize(sw,sh); document.body.appendChild(renderer.domElement); /* CAMERA SETTING */ fov = 45; aspect = sw/sh; near = 0.1; far = 10000; camera = new THREE.PerspectiveCamera(fov,aspect,near,far); camera.position.set(0,500,1000); scene.add(camera); /* LIGHT SETTING */ light = new THREE.DirectionalLight( 0xffffff, 1.5 ); light.position.set( 200, 450, 500 ); light.shadowMapWidth = 1024; light.shadowMapHeight = 1024; light.shadowMapDarkness = 0.95; scene.add(light); /* STATS */ stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; stats.domElement.style.zIndex = 100; document.body.appendChild( stats.domElement ); /* CROSSHAIR SECEN */ renderer.autoClear = false; chScene = new THREE.Scene(); chCamera = new THREE.PerspectiveCamera(fov,aspect,near,far); chCamera.position.set(0,0,0); chScene.add(chCamera); /* SETUP & RENDERING LOOP */ setup(); addEvent(); requestAnimationFrame(rendering); } // ------------------------------------------------------------------ // RENDERING // ------------------------------------------------------------------ function rendering() { delta = clock.getDelta(); animation(); renderer.setDepthTest(true); renderer.clear(); renderer.render(scene, camera); renderer.setDepthTest(false); renderer.render(chScene, chCamera); stats.update(); requestAnimationFrame(rendering); } var lookTarget = new THREE.Vector3(0,0,0); function animation() { camera.position = chr.camera.position; camera.rotation = chr.camera.rotation; //camera.lookAt(lookTarget); controler.update(delta); chr.update(); } // ------------------------------------------------------------------ // SETUP & ADD EVENT // ------------------------------------------------------------------ var clock,delta, ground,chr,tower, controler, crossHair; function setup() { clock = new THREE.Clock(); // object ground = new Ground("asset/img/grasslight-big.jpg") chr = new Cube(new THREE.Vector3(0,50,200),100,100,100,0xff0000); tower = new Cube(new THREE.Vector3(0,500,0),100,1000,100,0x0000ff); chr.cameraOn(); // controler controler = new FPC_Controler(chr.camera, renderer.domElement); controler.movementSpeed = 400; controler.lookSpeed = .2; controler.lookVertical = true; controler.constrainVertical = true; controler.verticalMin = (30 * Math.PI) / 180; controler.verticalMax = (100 * Math.PI) / 180; // CrossHair crossHair = new CrossHair(); scene.add(ground.root); scene.add(chr.root); scene.add(tower.root); } function addEvent() { document.addEventListener("keydown", onKeyDown, false); renderer.domElement.addEventListener("mousedown", onMouseDown, false); } // ------------------------------------------------------------------ // EVENT HANDLER // ------------------------------------------------------------------ function onKeyDown(e){ switch(e.keyCode){ case 32: /*space*/ break; case 49: /*1*/ crossHair.change(0); break; case 50: /*2*/ crossHair.change(1); break; case 51: /*3*/ break; case 52: /*4*/ break; case 53: /*5*/ break; }; } function onMouseDown(e){ switch ( e.button ) { case 0: console.log("attack"); break; } } // ------------------------------------------------------------------ // OBJECT CLASS // ------------------------------------------------------------------ //GROUND CLASS function Ground(imgURL) { this.root = new THREE.Object3D(); this.gt = THREE.ImageUtils.loadTexture( imgURL ); this.gg = new THREE.PlaneGeometry( 3000, 3000 ); this.gm = new THREE.MeshPhongMaterial( { color: 0xffffff, map: this.gt, perPixel: true } ); this.mesh = new THREE.Mesh( this.gg, this.gm ); this.mesh.material.map.wrapS = this.mesh.material.map.wrapT = THREE.RepeatWrapping; this.mesh.rotationAutoUpdate = true; this.mesh.castShadow = false; this.mesh.material.map.repeat.set( 100, 100 ); this.root.add(this.mesh); } Ground.prototype.constructor = Ground; //CUBE CLASS function Cube(position,width,height,depth,color,imgURL) { this.geo = new THREE.CubeGeometry(width,height,depth); this.mat = new THREE.MeshLambertMaterial({color:color});//new THREE.MeshBasicMaterial();// this.mesh = new THREE.Mesh(this.geo, this.mat); this.mesh.position.set(0,0,0); this.root = new THREE.Object3D(); this.root.add(this.mesh); this.root.position.set(position.x, position.y, position.z); } Cube.prototype.update = function(){ if(this.camera){ if(this.camera.position.y < 50 || this.camera.position.y > 50) this.camera.position.y = 50; this.root.position = this.camera.position; this.root.rotation = this.camera.rotation; } } Cube.prototype.cameraOn = function(){ if(!this.camera){ this.camera = new THREE.PerspectiveCamera(45,sw/sh,.1,10000); this.camera.position = this.root.position; this.root.add(this.camera); console.log(this.camera) } } Cube.prototype.cameraOff = function(){ if(this.camera){ this.root.remove(this.camera); this.camera = null; } } Cube.prototype.constructor = Cube; //CROSSHAIR CLASS function CrossHair() { this.CrossHairID = 0; this.CrossHairMaps = ["asset/img/crosshair1.png","asset/img/crosshair2.png"]; this.CrossHairMap = THREE.ImageUtils.loadTexture( this.CrossHairMaps[this.CrossHairID]); this.CrossHair = new THREE.Sprite({ useScreenCoordinates: false}); this.CrossHair.alignment = THREE.SpriteAlignment.center; this.CrossHair.useScreenCoordinates = false; this.CrossHair.position.z = -1000; // console.log(chScene); this.CrossHair.map = this.CrossHairMap; chScene.add(this.CrossHair); } CrossHair.prototype.change = function(id){ if(this.CrossHairID == id || this.CrossHairID > this.CrossHairMaps.length - 1) return; this.CrossHairID = id; this.CrossHairMap = THREE.ImageUtils.loadTexture( this.CrossHairMaps[this.CrossHairID]); this.CrossHair.map = this.CrossHairMap; } CrossHair.prototype.constructor = CrossHair; window.addEventListener("load",init) }).call(this); [/code]
ここで問題点がいくつかありましたけどその中で
下のsourceを見ると FPC_Controler(…)のClassは元々Three.jsのFirstPersonControlsというclassでした。
FirstPersonControlsClassはkeyboardやmouseのeventが定義されて上書きができなかったところで別のClassにして修正をしました。
[code lang="coffee"] controler = new FPC_Controler(chr.camera, renderer.domElement); [/code]
次の公開は来週になる予定です。
次は鳥が飛んでいて鳥を落とすまでと思います。
よろしくお願いします。