Tfe

Ongi etorri tfe-ren webgunera...

Old stuff/old_sites/threejs/11_pingu_2_animations/js/doors.js

(Deskargatu)
var Doors = function(game_mesh, options)
{
    var self=this;
    self.game_mesh = game_mesh;

    this.mesh = [];
    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) * options.door_size*1.0;
        depth2 = (Math.sqrt(3)/2) * options.door_size * Math.sqrt(3)/2 *1.3;

        var texloader = new THREE.TextureLoader();
        this.cubeTexture=THREE.ImageUtils.loadTexture('textures/wall.jpg');
        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.door_mat = mat;
                ended++;
                if(ended==2)
                {
                    ok();
                }
            });
        });
    };

    this.build = function()
    {
        var self=this;
        self.data_doors= {}
        this.num_items_line = Math.floor(Math.sqrt(options.maze_num));
        this.half_num = Math.floor(this.num_items_line/2);

        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 - this.half_num, y: 1, z:line - this.half_num});
                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++)
            {
                var cell =  self.create_meshes({num:total, real_x:row, x: row - this.half_num, y: 1, real_z : line, z:line - this.half_num});
                total++;
            }
        }
    };

    this.get_external_coord = function()
    {
        var exit_on_x = !!Math.floor(Math.random()*2);
        var x = z =0;
        if(exit_on_x)
        {
            x = Math.floor(Math.random()*(this.max_line+1));
            z = Math.floor(Math.random()*2) ? 0 : this.max_line;
        }
        else
        {
            x = Math.floor(Math.random()*2) ? 0 : this.max_row;
            z = Math.floor(Math.random()*(this.max_line+1));
        }
        return { x: x, z: z};
    };

    this.maze_doors = function()
    {
        var coords = this.get_external_coord();
        this.start_x = this.end_x = coords.x;
        this.start_z = this.end_z = coords.z;

        while(this.end_x===this.start_x && this.end_z === this.start_z)
        {
            coords = this.get_external_coord();
            this.end_x = coords.x;
            this.end_z = coords.z;

        }
        this.generated_doors[this.end_x][this.end_z].opened_doors.push(this.end_z ? 0 : 3);
        if((!this.end_x || this.end_x==this.max_row) && (this.end_z!=0 && this.end_z!=this.max_line))
        {
            this.generated_doors[this.end_x][this.end_z].opened_doors.push(this.end_x ? 1 : 4);
        }
        this.generated_doors[this.start_x][this.start_z].opened_doors.push(this.start_z ? 0 : 3);
        if((!this.start_x || this.start_x==this.max_row) && (this.start_z!=0 && this.start_z!=this.max_line))
        {
            this.generated_doors[this.start_x][this.start_z].opened_doors.push(this.start_x ? 1 : 4);
        }

        this.maze_doors_next([this.start_x, this.start_z]);
    };

    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];
            //console.log('link between ',initial_x+'/'+initial_z+' and ',dest_x+'/'+dest_z);

            // 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 ? 2 : 1);
                    this.generated_doors[dest_x][dest_z].opened_doors.push(pair ? 5 : 4);
                }
                else
                {
                    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
            {
                var pair = !!(initial_x%2===0)
                if(initial_z==dest_z)
                {
                    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);
                }
                else
                {
                    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);
                }
            }

            this.maze_doors_next(next_doors_unused[opened_link]);

            // 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 material = new THREE.LineBasicMaterial( { color: Math.random() * 0xffff00 + 0x0000ff, linewidth: 2 } );
            // line
            line = new THREE.Line( geometry,  material );
            self.game_mesh.add( line );

            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 positions = line.geometry.attributes.position.array;
            positions[0]=(ref.position.x);
            positions[1]=(ref.position.y);
            positions[2]=(ref.position.z);
            positions[3]=(dest.position.x);
            positions[4]=(dest.position.y);
            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 next_doors = [];

        // Top next door
        if(initial_z>0)
        {
            if(this.generated_doors[initial_x][initial_z-1])
            {
                next_doors.push([initial_x, initial_z-1]);
            }
        }
        // Bottom next door
        if(initial_z<=this.max_line)
        {
            if(this.generated_doors[initial_x][initial_z+1])
            {
                next_doors.push([initial_x, initial_z+1]);
            }
        }
        // Left next doors
        if(initial_x>0)
        {
            var pair = !!(initial_x%2===0)

            // Pair 2,1 has left next doors: 1,1 and 1,2
            if(pair)
            {
                if(this.generated_doors[initial_x-1][initial_z])
                {
                    next_doors.push([initial_x-1, initial_z]);
                }
                if(initial_z<this.max_line)
                {
                    if(this.generated_doors[initial_x-1][initial_z+1])
                    {
                        next_doors.push([initial_x-1, initial_z+1]);
                    }
                }
            }
            // Impair 1,1 has 0,0 and 0,1
            else
            {
                if(this.generated_doors[initial_x-1][initial_z])
                {
                    next_doors.push([initial_x-1, initial_z]);
                }
                if(initial_z-1>-1)
                {
                    if(this.generated_doors[initial_x-1][initial_z-1])
                    {
                        next_doors.push([initial_x-1, initial_z-1]);
                    }
                }
            }
        }
        if(initial_x<=this.max_row)
        {
            var pair = !!(initial_x%2===0)

            // Pair 2,1 has left next doors: 1,1 and 1,2
            if(pair)
            {
                if(this.generated_doors[initial_x+1] && this.generated_doors[initial_x+1][initial_z])
                {
                    next_doors.push([initial_x+1, initial_z]);
                }
                if(initial_z<this.max_line)
                {
                    if(this.generated_doors[initial_x+1] && this.generated_doors[initial_x+1][initial_z+1])
                    {
                        next_doors.push([initial_x+1, initial_z+1]);
                    }
                }
            }
            // Impair 1,1 has 0,0 and 0,1
            else
            {
                if(this.generated_doors[initial_x+1] && this.generated_doors[initial_x+1][initial_z])
                {
                    next_doors.push([initial_x+1, initial_z]);
                }
                if(initial_z-1>-1)
                {
                    if(this.generated_doors[initial_x+1] && this.generated_doors[initial_x+1][initial_z-1])
                    {
                        next_doors.push([initial_x+1, initial_z-1]);
                    }
                }
            }
        }
        return next_doors;
    };

    /* Memorize the doors created, to avoid creating doble contiguous doors */
    this.register_door= function(x, z, i, cell)
    {
        if(x<0 || z<0)
        {
            return;
        }
        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()
    {
        return this.get_pos({ x: this.start_x - this.half_num, z: this.start_z - this.half_num});
    };
    this.get_end_pos = function()
    {
        return this.get_pos({ x: this.end_x - this.half_num, z: this.end_z - this.half_num});
    };

    this.create_cell = function(params)
    {
        var self=this;

        var pivots=[];

        this.fulldepth = options.door_size + options.door_size*2;

        var pair = params.x%2 ? depth2 : 0;

        var cell = new THREE.Object3D();
        var pos = this.get_pos(params);
        cell.position.x=pos.x;
        cell.position.y=0;
        cell.position.z=pos.z;
        this.cells.push(cell);
        self.game_mesh.add(cell);
        return cell;
    };

    this.create_meshes = function(params)
    {
        var self=this;

        var pivots=[];

        this.fulldepth = options.door_size + options.door_size*2;
        var total=this.mesh.length;
        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++;

                pivots[total] = new THREE.Object3D();
                cell.add(pivots[total]);

                var materials = [];
                materials.push(new THREE.MeshLambertMaterial({ map: this.cubeTexture} ));
                materials.push(new THREE.MeshLambertMaterial({ map: this.cubeTexture} ));
                materials.push(new THREE.MeshLambertMaterial({ map: this.cubeTexture} ));
                materials.push(new THREE.MeshLambertMaterial({ map: this.cubeTexture} ));

                if(this.generated_doors[params.real_x][params.real_z].opened_doors.indexOf(i)!==-1)
                {
                    this.mesh[total] = new THREE.Mesh( self.door_geo, new THREE.MeshFaceMaterial(materials));
                }
                else
                {
                    this.mesh[total] = new THREE.Mesh( self.wall_geo, new THREE.MeshFaceMaterial(materials));
                }
                this.mesh[total].scale.x=options.door_size;
                this.mesh[total].scale.y= options.door_size;
                this.mesh[total].scale.z= options.door_size;

                this.mesh[total].receiveShadow  = true;
                pivots[total].add( this.mesh[total] );
                this.mesh[total].position.set(0, 0, options.door_size);
                pivots[total].rotation.y= Math.radians(i*60);


                total++;
            }
        }
        self.pivots = pivots;
        return cell;
    };

}