Tfe

Ongi etorri tfe-ren webgunera...

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);
        }
    };

}