var camera, scene, renderer,
material, materials, mesh, stats, plane;
//width
var w = 520;
//height
var h = 390;
//cubeサイズ
var cubeSize = 40;
//カメラ位置角度
var cameraPos3 = new THREE.Vector3;
//カメラ移動先の位置角度
var cameraTarget3 = new THREE.Vector3;
//カメラ距離初期値
var distance = 750;
//カメラ移動ターゲット
var distanceTarget = 500;
var zoomCycle = 150;
var zoomMin = 300;
var zoomMax = 1500;
//カメラ移動角度
var angleCycle = 90;
var angleYCycle = 5;
var angleYMin = 20;
var angleYMax = 70;
//y軸カメラ回転初期値
cameraPos3.y = cameraTarget3.y = 50;
function init() {
camera = new THREE.Camera( 50, w / h, 1, 10000 );
camera.position.z = distance;
scene = new THREE.Scene();
//Cubeの各面のマテリアル
materials = [
new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture(\'images/texture001.png\')}), // right
new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture(\'images/texture001.png\')}), // left
new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture(\'images/texture001.png\')}), //top
new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture(\'images/texture001.png\')}), // bottom
new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture(\'images/texture001.png\')}), // back
new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture(\'images/texture001.png\')}) // front
];
material = new THREE.MeshFaceMaterial();
mesh = [];
renderer = new THREE.CanvasRenderer();
renderer.setSize( w, h );
$(\'#three-stage\').append( renderer.domElement );
//Stats SetUp
stats = new Stats();
stats.domElement.style.position = \'absolute\';
stats.domElement.style.top = \'0px\';
stats.domElement.style.zIndex = 100;
$(\'#three-stage\').append( stats.domElement );
//Event
$(document).bind(\'keydown\', keyDownHandler);
};
function keyDownHandler(e){
e.preventDefault();
switch(e.keyCode){
case 37:
cameraTarget3.x += angleCycle;
cameraTarget3.z += angleCycle;
break;
case 38:
cameraTarget3.y += angleYCycle;
break;
case 39:
cameraTarget3.x -= angleCycle;
cameraTarget3.z -= angleCycle;
break;
case 40:
cameraTarget3.y -= angleYCycle;
break;
case 88:
distanceTarget += zoomCycle;
break;
case 90:
distanceTarget -= zoomCycle;
break;
default:
break;
}
cameraTarget3.y = Math.max(Math.min(cameraTarget3.y, angleYMax), angleYMin);
distanceTarget = Math.max(Math.min(distanceTarget, zoomMax), zoomMin);
};
/**
* Cubeをシーンに追加
*/
function makeCubes(mtx){
var i,imax,j,jmax,k,sides,cube;
for (i = 0, imax = mtx.length; i < imax; i++) {
for (j = 0, jmax = mtx[i].length; j < jmax; j++) {
for (k = 0; k < mtx[i][j]; k++) {
sides = {
px: true,
nx: true,
py: true,
ny: true,
pz: true,
nz: true
};
sides.ny = false;
if (i > 0 && k < mtx[i - 1][j]) {
sides.nz = false;
}
if (j < (jmax - 1) && k < mtx[i][j + 1]) {
sides.nx = false;
}
if (i < (imax - 1) && k < mtx[i + 1][j]) {
sides.pz = false;
}
if (j > 0 && k < mtx[i][j - 1]) {
sides.px = false;
}
cube = new THREE.Mesh( new THREE.Cube(cubeSize, cubeSize, cubeSize, 1, 1, 1, materials, false, sides), material);
cube.position.x = cubeSize * j - (jmax*cubeSize/2) + cubeSize / 2;
cube.position.y = cubeSize * k + cubeSize / 2;
cube.position.z = cubeSize * i - (imax*cubeSize/2) + cubeSize / 2;
cube.overdraw = false;
cube.doubleSided = false;
scene.addObject(cube);
mesh.push(cube);
}
}
}
plane = new THREE.Mesh(
new THREE.Plane(cubeSize * jmax, cubeSize * imax, jmax, imax),
new THREE.MeshBasicMaterial({color: 0x504237})
);
plane.rotation.x = -90 * Math.PI / 180;
scene.addObject(plane);
};
/**
* シーンオブジェクトを全てクリア
*/
function clearCube(){
if(plane){
scene.removeObject(plane);
}
for(var i in mesh){
scene.removeObject(mesh[i]);
}
mesh = [];
};
function animate() {
requestAnimationFrame( animate );
render();
};
function render() {
//移動計算
cameraPos3.x += (cameraTarget3.x - cameraPos3.x) * 0.2;
cameraPos3.y += (cameraTarget3.y - cameraPos3.y) * 0.2;
cameraPos3.z += (cameraTarget3.z - cameraPos3.z) * 0.2;
distance += (distanceTarget - distance) * 0.2;
//カメラを動かす
camera.position.x = distance * Math.sin( cameraPos3.x * Math.PI / 180 );
camera.position.y = distance * Math.tan( cameraPos3.y * Math.PI / 180 );
camera.position.z = distance * Math.cos( cameraPos3.z * Math.PI / 180 );
renderer.render( scene, camera );
//Stats update
stats.update();
};
/**
* 迷路生成
*/
function createMaze(){
clearCube();
var w = $(\'#mazeWidth\').val();
var h = $(\'#mazeHeight\').val();
var mtx = (new MAZE(w, h)).getMatrix();
makeCubes(mtx);
};
$(function(){
init();
animate();
createMaze();
});
/*==================================================================
MAZE GENERATOR
==================================================================*/
var MAZE = function(cols, rows){
this.cfg = {
maxLoop: 15000,
cols: 10,
rows: 10
};
this.cluster = {};
this.build(cols, rows);
};
MAZE.prototype.build = function(cols, rows){
var _arr = [];
var _col = [];
var _row = [];
var _num = 0;
this.cfg.cols = cols;
this.cfg.rows = rows;
for(var i=0;i<rows;i++){
_arr[i] = [];
for(var j=0;j<cols;j++){
_arr[i][j] = _num++;
}
}
for(var i=0;i<rows;i++){
_col[i] = [];
for(var j=0;j<=cols;j++){
_col[i][j] = (j==0 || j==cols) ? 3 : 1 ;
}
}
for(var i=0;i<=rows;i++){
_row[i] = [];
for(var j=0;j<cols;j++){
_row[i][j] = (i==0 || i==rows) ? 3 : 1 ;
}
}
this.cluster = {
el: _arr,
col: _col,
row: _row
};
this._breakWark();
};
MAZE.prototype._fillNumber = function(tg, num){
var c = this.cluster.el;
for (var i = 0, max = c.length; i < max; i++) {
for (var j = 0, max2 = c[i].length; j < max2; j++) {
if(c[i][j] == tg){
c[i][j] = num;
}
}
}
};
MAZE.prototype._isAllFill = function(){
var check = null;
var c = this.cluster.el;
for (var i = 0, max = c.length; i < max; i++) {
for (var j = 0, max2 = c[i].length; j < max2; j++) {
if(check == null){
check = c[i][j];
}else if(check != c[i][j]){
return false;
}
}
}
return true;
};
MAZE.prototype._borderBreak = function(){
var c = this.cluster;
var cfg = this.cfg;
var type = (Math.round(Math.random()) == 0) ? \'col\' : \'row\' ;
switch(type){
case \'row\':
var colNum = Math.floor(Math.random()*cfg.cols);
var rowNum = Math.floor(Math.random()*cfg.rows);
if(rowNum <= 0) rowNum = 1;
if(c[type][rowNum][colNum] == 1){
var num1 = c.el[rowNum-1][colNum];
var num2 = c.el[rowNum][colNum];
if(num1 == num2){
c[type][rowNum][colNum] = 2;
}else{
this._fillNumber(Math.max(num1, num2), Math.min(num1, num2));
c[type][rowNum][colNum] = 0;
}
}
break;
case \'col\':
var colNum = Math.floor(Math.random()*cfg.cols);
var rowNum = Math.floor(Math.random()*cfg.rows);
if(colNum <= 0) colNum = 1;
if(c[type][rowNum][colNum] == 1){
var num1 = c.el[rowNum][colNum-1];
var num2 = c.el[rowNum][colNum];
if(num1 == num2){
c[type][rowNum][colNum] = 2;
}else{
this._fillNumber(Math.max(num1, num2), Math.min(num1, num2));
c[type][rowNum][colNum] = 0;
}
}
break;
default:
break;
}
};
MAZE.prototype._breakWark = function(){
var i = 1;
while(!this._isAllFill() && (i%this.cfg.maxLoop != 0 || window.confirm(\'処理を継続しますか ?\'))){
this._borderBreak();
i++;
}
};
MAZE.prototype.getMatrix = function(){
var cols = this.cfg.cols;
var rows = this.cfg.rows;
var col = this.cluster.col;
var row = this.cluster.row;
var mtx = [], i,imax,j,jmax;
for (i = 0, imax = rows*2+1; i < imax; i++) {
mtx[i] = [];
for (j = 0, jmax = cols*2+1; j < jmax; j++) {
mtx[i][j] = 0;
}
}
for (i = 0, imax = col.length; i < imax; i++) {
for (j = 0, jmax = col[i].length; j < jmax; j++) {
mtx[i*2][j*2] = 1;
mtx[(i+1)*2][j*2] = 1;
if(col[i][j] > 0){
mtx[i*2+1][j*2] = 1;
}
}
}
for (i = 0, imax = row.length; i < imax; i++) {
for (j = 0, jmax = row[i].length; j < jmax; j++) {
if(row[i][j] > 0){
mtx[i*2][j*2+1] = 1;
}
}
}
mtx[1][0] = 0;
mtx[rows*2-1][cols*2] = 0;
return mtx;
};