おはようございます。
最近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
Three_example.zip
sourceはこんな感じです。FPS_BASEの構成の基本にして書きました。
(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);
ここで問題点がいくつかありましたけどその中で
下のsourceを見ると FPC_Controler(...)のClassは元々Three.jsのFirstPersonControlsというclassでした。
FirstPersonControlsClassはkeyboardやmouseのeventが定義されて上書きができなかったところで別のClassにして修正をしました。
controler = new FPC_Controler(chr.camera, renderer.domElement);
次の公開は来週になる予定です。
次は鳥が飛んでいて鳥を落とすまでと思います。
よろしくお願いします。