Old stuff/old_sites/threejs/12_game/js/doors.js
(Deskargatu)
var Doors = function(game, maze, options)
{
var self=this;
this.mesh = [];
this.pivots = [];
this.pivots_refs = {};
this.door_separators = [];
this.outside_separators = [];
var material;
var depth;
var depth2;
var total_doors=0;
this.cells = [];
this.generated_doors = {};
this.data_doors = {};
this.load= function()
{
var self=this;
depth = (Math.sqrt(3)/2) * game.opt.door_size*1.0;
depth2 = (Math.sqrt(3)/2) * game.opt.door_size * Math.sqrt(3)/2 *1.35;
var texloader = new THREE.TextureLoader();
this.cubeTexture=texloader.load('textures/wall.jpg');
this.cubeTexture.wireframe=true;
this.cubeTexture.wrapS = this.cubeTexture.wrapT = THREE.RepeatWrapping;
this.cubeTexture.repeat.set( 0.1, 0.1 );
return new Promise(function(ok, reject)
{
var ended=0;
var loader = new THREE.JSONLoader();
loader.load( "js/meshes/door.js", function(geometry, mat)
{
self.door_geo = geometry;
self.door_mat = mat;
ended++;
if(ended==2)
{
ok();
}
});
loader.load( "js/meshes/wall.js", function(geometry, mat)
{
self.wall_geo = geometry;
self.wall_mat = mat;
ended++;
if(ended==2)
{
ok();
}
});
});
};
this.build = function()
{
var self=this;
this.container = new THREE.Object3D();
this.floor_geom = new THREE.Geometry();
this.doors_geom = new THREE.Geometry();
this.num_items_line = Math.floor(Math.sqrt(options.maze_num));
var total=0;
self.max_row = 0;
self.max_line = 0;
// Loop to create maze
// Loop lines
for(var row=0; (row<this.num_items_line || total < options.maze_num); row++)
{
self.max_row = row;
for(var line=0; (line<this.num_items_line && total < options.maze_num); line++)
{
if(self.max_line<line) { self.max_line= line ; }
total++;
var cell = self.create_cell({ x: row , y: 1, z:line });
if(!self.generated_doors[row])
{
self.generated_doors[row] = {};
}
self.generated_doors[row][line] = cell;
self.generated_doors[row][line].opened_doors=[];
}
}
// Open/Close some doors
this.maze_doors();
// Loop to really the meshes
// Loop lines
total=0;
for(var row=0; (row<this.num_items_line || total < options.maze_num); row++)
{
for(var line=0; (line<this.num_items_line && total < options.maze_num); line++)
{
self.create_meshes({num:total, real_x:row, x: row , y: 1, real_z : line, z:line });
total++;
}
}
var material = new THREE.MeshBasicMaterial( { color: 0x3366bb } );
var floor = new THREE.Mesh( this.floor_geom, material);
this.container.add(floor);
material = new THREE.MeshBasicMaterial( { color: 0x442233 } );
console.log('mat ',this.wall_mat);
var doors = new THREE.Mesh( this.doors_geom, new THREE.MultiMaterial(this.wall_mat));
this.mesh = [ doors];
this.container.add(doors);
// Correct position of the maze depending on the start position and direction
var move_x = this.start_x*depth2*2;
var move_z = this.start_z*depth2*2;
this.container.position.x = options.x - move_x;
this.container.position.y = 0;
this.container.position.z = options.z - move_z;
game.scene.add( this.container );
};
this.get_random_start_end = function()
{
var start_on_x = !!Math.floor(Math.random()*2);
var x=0;
var z =-1;
// Start pos
while(!this.generated_doors[x] || !this.generated_doors[x][z])
{
z = Math.floor(Math.random()*(this.max_line+1));
}
this.start_x = x;
this.start_z = z;
this.start_door = this.generated_doors[x][z];
z=-1;
x= this.max_row;
// End door
while(!this.generated_doors[x] || !this.generated_doors[x][z] || (this.start_x===x && this.start_z===z))
{
z = Math.floor(Math.random()*(this.max_line+1));
}
this.end_x = x;
this.end_z = z;
this.end_door = this.generated_doors[x][z];
};
this.maze_doors = function()
{
this.get_random_start_end();
// Start doors
var params = { x: this.start_x , z: this.start_z, real_x:'outside',real_z:'outside'};
var cell = this.cells[this.start_x*this.num_items_line + this.start_z];
var start_door_top_bottom=false;
this.start_i = 4;
this.create_separation_line(cell,params, this.start_i, 'start');
this.generated_doors[this.start_x][this.start_z].opened_doors.push(this.start_i);
// End doors
var params = { x: this.end_x , z: this.end_z, real_x:'outside',real_z:'outside'};
var cell = this.cells[this.end_x*this.num_items_line + this.end_z];
this.end_i = 1;
this.create_separation_line(cell,params, this.end_i, 'end');
this.generated_doors[this.end_x][this.end_z].opened_doors.push(this.end_i);
this.maze_doors_next([Math.floor(Math.random()*(this.max_line-1)),Math.floor(Math.random()*(this.max_row-1))]);
};
this.maze_doors_next = function(opt)
{
var self=this;
var initial_x = opt[0];
var initial_z = opt[1];
this.generated_doors[initial_x][initial_z].used=1;
var next_doors_full = this.near_doors(initial_x, initial_z);
var next_doors_unused=[];
next_doors_full.forEach(function(door)
{
if(!self.generated_doors[door[0]][door[1]].used)
{
next_doors_unused.push(door);
}
});
if(next_doors_unused.length>0)
{
var opened_link = Math.floor(Math.random()*next_doors_unused.length);
var dest_x = next_doors_unused[opened_link][0];
var dest_z = next_doors_unused[opened_link][1];
// Fill generated_doors data
// Same row
if(initial_x ==dest_x)
{
// Bottom door
if(initial_z<dest_z)
{
this.generated_doors[initial_x][initial_z].opened_doors.push(0);
this.generated_doors[dest_x][dest_z].opened_doors.push(3);
}
else
{
this.generated_doors[initial_x][initial_z].opened_doors.push(3);
this.generated_doors[dest_x][dest_z].opened_doors.push(0);
}
}
else if(initial_x<dest_x)
{
var pair = !!(initial_x%2===0)
if(initial_z==dest_z)
{
this.generated_doors[initial_x][initial_z].opened_doors.push(pair ? 1 : 2);
this.generated_doors[dest_x][dest_z].opened_doors.push(pair ? 4 : 5);
}
else
{
this.generated_doors[initial_x][initial_z].opened_doors.push(pair ? 2 : 1);
this.generated_doors[dest_x][dest_z].opened_doors.push(pair ? 5 : 4);
}
}
else
{
var pair = !!(initial_x%2===0)
if(initial_z==dest_z)
{
this.generated_doors[initial_x][initial_z].opened_doors.push(pair ? 5 : 4);
this.generated_doors[dest_x][dest_z].opened_doors.push(pair ? 2 : 1);
}
else
{
this.generated_doors[initial_x][initial_z].opened_doors.push(pair ? 4 :5);
this.generated_doors[dest_x][dest_z].opened_doors.push(pair ? 1 : 2);
}
}
this.maze_doors_next(next_doors_unused[opened_link]);
// DEBUG!
// Create a visual line
if(game.opt.debug_level>1)
{
// Visualize path
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( 2 * 3 ); // 3 vertices per point
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );
var ref = this.cells[initial_x*this.num_items_line + initial_z];
var dest = this.cells[dest_x*this.num_items_line + dest_z];
var material = new THREE.LineBasicMaterial( { color: Math.random() * 0xffff00 + 0x0000ff, linewidth: 2 } );
line = new THREE.Line( geometry, material );
this.container.add( line );
var positions = line.geometry.attributes.position.array;
positions[0]=(ref.position.x);
positions[1]=(1);
positions[2]=(ref.position.z);
positions[3]=(dest.position.x);
positions[4]=(1);
positions[5]=(dest.position.z);
}
}
// Do a maze with the not connected dots too
else
{
for(var x=0; x<=this.max_row; x++)
{
for(var z=0; z<=this.max_line; z++)
{
// Need to link and unused cell with a used cell
if(this.generated_doors[x][z] && !this.generated_doors[x][z].used)
{
next_doors_full = this.near_doors(x, z);
next_doors_used=[];
next_doors_full.forEach(function(door)
{
if(self.generated_doors[door[0]][door[1]].used)
{
next_doors_used.push(door);
}
});
if(next_doors_used.length>0)
{
var connected_door = next_doors_used[Math.floor(Math.random()* next_doors_used.length)];
return this.maze_doors_next(connected_door);
}
}
}
}
}
};
this.near_doors = function(initial_x, initial_z)
{
var self=this;
var next_doors = [];
var pair = !!(initial_x%2===0);
var check = [];
// top
check.push([ initial_x, initial_z-1]);
// bottom
check.push([ initial_x, initial_z+1]);
// left top
check.push([ initial_x-1, pair ? initial_z-1 : initial_z ]);
// left bottom
check.push([ initial_x-1, pair ? initial_z : initial_z+1]);
// right top
check.push([ initial_x+1, pair ? initial_z-1 : initial_z]);
// right bottom
check.push([ initial_x+1, pair ? initial_z : initial_z+1]);
check.forEach(function(c)
{
var x = c[0];
var z = c[1];
if(self.generated_doors[x] && self.generated_doors[x][z])
{
next_doors.push([x,z]);
}
});
return next_doors;
};
/* Memorize the doors created, to avoid creating doble contiguous doors */
this.register_door= function(x, z, i, cell)
{
if(!this.data_doors[x+'.'+z])
{
this.data_doors[x+'.'+z]={};
}
this.data_doors[x+'.'+z][i] = 1;
var pair= x%2==0;
if(cell)
{
switch(i)
{
case 0: this.register_door(x, z+1, 3, false); break;
case 1: this.register_door(x+1, pair? z : z+1, 4, false); break;
case 2: this.register_door(x+1, pair ? z-1 : z, 5, false); break;
}
}
};
this.get_pos = function(params)
{
var pair = params.x%2 ? depth2 : 0;
var x =params.x * depth *2;
var z =params.z * depth2 *2 + pair;
return { x: x, z: z};
};
this.get_start_pos = function()
{
var coord = this.get_pos({ x: this.start_x , z: this.start_z });
return { x: coord.x + options.x , z: coord.z + options.z };
};
this.get_end_pos = function()
{
var coord = this.get_pos({ x: this.end_x - this.start_x , z: this.end_z - this.start_z });
return { x: coord.x + options.x , z: coord.z + options.z };
};
this.create_cell = function(params)
{
var self=this;
this.fulldepth = game.opt.door_size + game.opt.door_size*2;
var pair = params.x%2 ? depth2 : 0;
var cell = new THREE.Object3D();
cell.name='pos '+params.x+' / '+params.z;
var pos = this.get_pos(params);
cell.position.x=pos.x;
cell.position.y=0;
cell.position.z=pos.z;
this.cells.push(cell);
this.container.add(cell);
// Create ground of that pivot
var geom = new THREE.Geometry();
var v1 = new THREE.Vector3(cell.position.x - game.opt.door_size/1.8 , 0 , cell.position.z-depth2*1.0 );
var v2 = new THREE.Vector3(cell.position.x - game.opt.door_size*1.2 , 0,cell.position.z);
var v3 = new THREE.Vector3(cell.position.x - game.opt.door_size/1.8 , 0 , cell.position.z+depth2*1.0 );
var v4 = new THREE.Vector3(cell.position.x + game.opt.door_size/1.8 , 0 , cell.position.z+depth2*1.0 );
var v5 = new THREE.Vector3(cell.position.x + game.opt.door_size*1.2 , 0,cell.position.z);
var v6 = new THREE.Vector3(cell.position.x + game.opt.door_size/1.8 , 0 , cell.position.z-depth2*1.0 );
var vcenter = new THREE.Vector3(cell.position.x ,1,cell.position.z);
geom.vertices.push(vcenter);
geom.vertices.push(v1);
geom.vertices.push(v2);
geom.vertices.push(v3);
geom.vertices.push(v4);
geom.vertices.push(v5);
geom.vertices.push(v6);
var material = new THREE.MeshBasicMaterial( { color: 0x3366bb } );
geom.faces.push( new THREE.Face3( 0, 1, 2 ) );
geom.faces.push( new THREE.Face3( 0, 2, 3 ) );
geom.faces.push( new THREE.Face3( 0, 3, 4 ) );
geom.faces.push( new THREE.Face3( 0, 4, 5 ) );
geom.faces.push( new THREE.Face3( 0, 5, 6 ) );
geom.faces.push( new THREE.Face3( 0, 6, 1) );
var object = new THREE.Mesh( geom, material);
this.floor_geom.merge(object.geometry, object.matrix);
//this.container.add(object);
return cell;
};
this.get_pivot = function(cell, params, i)
{
var pivot = new THREE.Object3D();
this.pivots.push(pivot);
pivot.name ='p '+params.x+'/'+params.z+'/'+i;
this.pivots_refs[params.x+'_'+params.z+'_'+i] = pivot;
pivot.rotation.y= Math.radians(i*60);
cell.add(pivot);
return pivot;
};
this.create_meshes = function(params)
{
var self=this;
this.fulldepth = game.opt.door_size + game.opt.door_size*2;
var cell = this.cells[params.num];
for(var i=0; i<6;i++)
{
if(!this.data_doors[params.x+'.'+params.z] || !this.data_doors[params.x+'.'+params.z][i])
{
this.register_door(params.x, params.z, i, cell);
total_doors++;
var pivot = this.get_pivot(cell, params, i);
var materials = [];
var mesh;
if(this.generated_doors[params.real_x][params.real_z].opened_doors.indexOf(i)!==-1)
{
//mesh = new THREE.Mesh( self.door_geo);
//pivot.add(mesh);
//this.mesh.push(mesh);
}
else
{
mesh = new THREE.Mesh( self.wall_geo);
//pivot.add(mesh);
//this.mesh.push(mesh);
mesh.scale.x=game.opt.door_size;
mesh.scale.y= game.opt.door_size;
mesh.scale.z= game.opt.door_size;
mesh.rotation.y= Math.radians(i*60);
mesh.position.x = cell.position.x;
mesh.position.y = cell.position.y;
mesh.position.z = cell.position.z;
switch(i)
{
case 0:
mesh.position.z += game.opt.door_size;
break;
case 1:
mesh.position.z += game.opt.door_size * 0.50;
mesh.position.x += depth;
break;
case 2:
mesh.position.z -= game.opt.door_size * 0.50;
mesh.position.x += depth;
break;
case 3:
mesh.position.z -= game.opt.door_size;
break;
case 4:
mesh.position.z -= game.opt.door_size * 0.50;
mesh.position.x -= depth;
break;
case 5:
mesh.position.z += game.opt.door_size * 0.50;
mesh.position.x -= depth;
break;
}
mesh.updateMatrix();
//this.container.add(mesh);
this.doors_geom.merge(mesh.geometry, mesh.matrix);
//mesh.position.set(0, 0, game.opt.door_size);
mesh.receiveShadow = true;
}
}
var areas=[];
// Create collision items to detect enter in the cell
if(this.generated_doors[params.real_x][params.real_z].opened_doors.indexOf(i)!==-1)
{
var door = this.generated_doors[params.real_x][params.real_z];
var outside_door =
( params.real_x == this.start_x && params.real_z == this.start_z && i == this.start_i) ||
( params.real_x == this.end_x && params.real_z == this.end_z && i == this.end_i);
this.create_separation_line(cell,params, i, false, outside_door);
}
}
return cell;
};
this.create_separation_line= function(cell,params, i, extra_door, outside_door)
{
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( 2 * 3 ); // 3 vertices per point
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );
var material = new THREE.LineBasicMaterial( { color: 0xffff00, linewidth: 2, transparent:true, opacity:0 } );
if(game.opt.debug_level>1)
{
material = new THREE.LineBasicMaterial( { color: Math.random() * 0xffff00 + 0x0000ff, linewidth: 2 } );
}
var line = new THREE.Line( geometry, material );
var pivot = this.get_pivot(cell, params, i);
pivot.add(line);
var extra = extra_door ? game.opt.door_size*0.4 : 0;
var positions = line.geometry.attributes.position.array;
positions[0]=(depth*( !extra_door ? .5 : .7));
positions[1]=(1);
positions[2]=(game.opt.door_size*0.9 +extra);
positions[3]=(-depth*(!extra_door ? .5 : .7));
positions[4]=(1);
positions[5]=(game.opt.door_size*0.9 +extra);
line.name='l '+params.real_x+' / '+params.real_z;
line.callback_data = {mazeid: maze.id, id:'cell_'+params.real_x+'_'+params.real_z, type:'change_cell', x: params.real_x, z:params.real_z};
line.mazeid = maze.id;
self.door_separators.push(line);
if(extra_door=='start'){
line.callback_data.action = 'leave_maze_from_start';
}
if(extra_door=='end'){
line.callback_data.action = 'leave_maze_from_end';
}
if(outside_door)
{
self.outside_separators.push(line);
}
};
}