Tfe

Ongi etorri tfe-ren webgunera...

Old stuff/old_sites/threejs/18/js/game.js

(Deskargatu)
var Game = function(opt)
{
    var scene;
    var lock;
    var SCREEN_HEIGHT;
    var SCREEN_HEIGHT;
    var camera;
    var renderer;
    var mazes= {};

    var animations = [];

    var camera_decal_x = 10;
    var camera_decal_y = 150;
    var camera_decal_z = 100;

    var drop_delay_multiple=50;
    if(opt.debug_level>1)
    {
        camera_decal_x = 0;
        camera_decal_y = 200;
        camera_decal_z = 50;
    }

    var current_item_id = 0;
    var clock  = new THREE.Clock();

    //var stats = new Stats();
    //stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
    //document.body.appendChild( stats.dom );


    this.load = function()
    {
        var promises = [];
        this.assets = new Assets();
        return  this.assets.load();
    };

    this.init = function()
    {
        var self=this;
        this.load().then(function()
        {
            self.init_loaded();
        }, function(e)
        {
            console.error('error loading ',e);
            alert('Error loading some assets...');
        });
    };

    this.init_loaded= function()
    {
        var self=this;
        this.opt = opt;

        this.static_obstacles = [];
        this.moving_obstacles = [];
        this.moving_and_static_obstacles = [];
        this.obstacles_with_player = [];
        this.collision_callbacks = [];
        this.scene = new THREE.Scene();


        // Build basic structures
        var width = 10000;
        var height = 10000;
        var click_ground = new THREE.PlaneGeometry(width, height);
        var material = new THREE.LineBasicMaterial( { color: 0x555555, opacity:0, transparent:true  } );
        // Set and add the click_ground
        this.click_ground = new THREE.Mesh(click_ground, material);
        this.click_ground.name='click_ground';
        this.click_ground.rotation.x = -Math.PI / 2;

        this.scene.add(this.click_ground);

        this.camera = new THREE.PerspectiveCamera(45, 1, 0.1, 10000);
        this.scene.add(this.camera);

        this.ambient_light = new THREE.PointLight();
        this.ambient_light.intensity=opt.debug_level>1 ? 2.0 : 1.0;
        this.ambient_light.position.set(100, 200, 80);
        this.ambient_light.castShadow=opt.enable_shadow;
        this.scene.add(this.ambient_light);



        //this.scene.fog = new THREE.FogExp2( 0x333355, 0.0055 );


        this.renderer = new THREE.WebGLRenderer({ antialias: true});
        this.renderer.setClearColor(opt.debug_level>1 ? 0x000000 : 0x000000, 1);
        this.renderer.shadowMapEnabled=opt.enable_shadow;
        this.renderer.shadowMapSoft=opt.enable_shadow;
        this.renderer.shadowMapType = THREE.PCFSoftShadowMap;


        window.addEventListener( 'resize', onWindowResize, false );
        function onWindowResize(){
            self.camera.aspect = window.innerWidth / window.innerHeight;
            self.camera.updateProjectionMatrix();

            self.renderer.setSize( window.innerWidth, window.innerHeight );
        }
        this.container = opt.root;

        this.setAspect();
        this.container.appendChild(this.renderer.domElement);

        this.start();
        this.gui.init();
        this.render();

        this.updateCollisionsCache();
    };

    this.setAspect= function()
    {
        var w = this.container.offsetWidth;
        // Fit the initial visible area's height
        h = this.container.offsetHeight;
        // Update the renderer and the camera
        this.renderer.setSize(w, h);
        this.camera.aspect = w / h;
        this.camera.updateProjectionMatrix();
    };

    this.setFocus = function(object)
    {
        this.ambient_light.position.set(100+object.position.x, 200, 80+object.position.z);
        this.camera.position.x = object.position.x + camera_decal_x;
        this.camera.position.y = object.position.y + camera_decal_y;
        this.camera.position.z = object.position.z + camera_decal_z;

        this.camera.lookAt(object.position);
    };

    this.start = function()
    {
        var self=this;

        this.direction=0;

        this.focus_perso = self.add_character({
            x: 10,
            y: 0,
            z: 10,
            moveable: true,
            ai: false,
            game: self
        });
        this.focus_perso.name='main character';

        // Create start path
        var path = new Path(this, {level: 2, direction: this.direction, x: 0, z: 0});
        path.build();

        var pos = path.get_start_pos();
        var angle = Math.radians(30);
        pos.x += Math.cos(angle) * 20;
        pos.z += Math.sin(angle) * 20;


        this.current_item = path;
        path.enter();

        // Look at player
        this.resetCamera();
    };

    this.add_character= function(params)
    {
        return new Perso(this, params);
    },
    this.add_key= function(params)
    {
        return new Key(this, params);
    },

    this.reload = function()
    {
        this.current_item.reload();
        var pos = this.current_item.get_start_pos();
        game.focus_perso.reload(pos);
    },

    // Camera refresh animation
    this.update = function(delta)
    {
        if(this.zoomOut)
        {
        }
        else if(this.zoominDestination)
        {
            this.zoominAngle-= 0.01;
            this.current_radius = Math.min(this.current_radius+1, game.opt.door_size);

            this.current_camera_decal_x *=0.96;
            this.current_camera_decal_y *=0.96;
            this.current_camera_decal_z *=0.96;

            this.camera.position.x =
                    game.focus_perso.container.position.x + 
                    this.current_camera_decal_x +
                    this.current_radius * Math.cos( this.zoominAngle);

            this.camera.position.y *= 0.99;

            this.camera.position.z =
                    game.focus_perso.container.position.z + 
                    this.current_camera_decal_z +
                    this.current_radius * Math.sin( this.zoominAngle);

            this.camera.lookAt(game.focus_perso.container.position);

            if(this.camera.position.y<this.zoominDestination)
            {
                this.zoomOutDestination=0;
                this.zoominCallback();
                this.zoominDestination=null;
            }
        }
        else
        {
            this.setFocus(this.focus_perso.container);
        }
    },

    this.render = function()
    {
        //stats.begin();
        this.renderer.render(this.scene, this.camera);

        if(!this.updating)
        {
            this.updating=1;
            var delta = clock.getDelta();
            if(delta>0.070 && game.opt.debug_level>10)
            {
                console.warn('SLOW RENDERING DELTA: ',delta);
                delta=0.070;
            }
			//delta=0.030;

            this.update(delta);

            animations.forEach(function(anim)
            {
                anim.animation_function();
            });

            this.focus_perso.update(delta);
            this.current_item.update(delta);
            this.updating=0;
        }
	    requestAnimationFrame(this.render_fct);
        //stats.end();
    };

    this.render_fct = this.render.bind(this);

    this.getStaticObstacles = function()
    {
        return this.static_obstacles;
    };
    this.getMovingObstacles = function()
    {
        return this.moving_obstacles;
    };
    this.getMovingAndStaticObstacles = function()
    {
        return this.moving_and_static_obstacles;
    };
    this.getHovers = function()
    {
        return this.hovers;
    };
    this.getHoversWithClickGround = function()
    {
        return this.hovers_with_ground;
    };
    this.getObstaclesWithPlayer = function()
    {
        return this.obstacles_with_player;
    };
    this.getCollisionCallbacks = function()
    {
        return this.collision_callbacks;
    }

    this.generateCollisionCallbacks = function()
    {
       return this.current_item.getCollisionCallbacks();
    };

    this.callCollisionCallbacks = function(perso,collisions)
    {
        collisions.forEach(function (obj)
        {
            obj.walk_through_callback();
        });
    };


    this.updateCollisionsCache = function()
    {
        this.hovers=this.current_item.getHovers();
        this.static_obstacles = this.current_item.getStaticObstacles();
        this.moving_obstacles = this.current_item.getMovingObstacles();
        this.obstacles_with_player = [].concat(this.static_obstacles, this.focus_perso.container_mesh);

        this.moving_and_static_obstacles = [].concat(this.static_obstacles).concat(this.moving_obstacles);
        this.hovers_with_ground= this.hovers.concat([this.click_ground]);
        this.collision_callbacks = this.generateCollisionCallbacks();
    };

    this.getNewId = function()
    {
        return 'item_'+(++current_item_id);
    };

    this.zoomInCircle = function(callback)
    {
        this.zoominAngle = 0;
        this.zoominDestination=50;
        this.zoominCallback=callback;

        this.current_radius = 0;
        this.current_camera_decal_x = camera_decal_x;
        this.current_camera_decal_y = camera_decal_y;
        this.current_camera_decal_z = camera_decal_z;
    };

    this.resetCamera = function()
    {
        this.camera.position.x = game.focus_perso.container.position.x + camera_decal_x;
        this.camera.position.y = game.focus_perso.container.position.y + camera_decal_y;
        this.camera.position.z = game.focus_perso.container.position.z + camera_decal_z;

        this.camera.lookAt(game.focus_perso.container.position);
    }

    this.enterType = function(item)
    {
        if(this.current_item.id!==item.id)
        {
            this.current_item.leave();
            this.current_item=item;
            this.current_item.enter();
        }
    };

    this.drop = function(params)
    {
        var self=this;
        var items = params.drops;
        var delay=0;
        var distance=0;
        var distance_step= opt.door_size*0.1;

        var start_pos = new THREE.Vector3(params.x, params.y, params.z);
        var obstacles = this.getObstaclesWithPlayer();

        items.forEach(function(item)
        {
            var collisionResults=[1];
            while(collisionResults.length>0)
            {
                item.params.x = params.x + Math.cos(distance)*distance_step;
                item.params.y = params.y;
                item.params.z = params.z + Math.sin(distance)*distance_step;

                var new_pos = new THREE.Vector3(item.params.x, item.params.y, item.params.z);
                var direction = new_pos.clone().sub(start_pos);

                var ray = new THREE.Raycaster( start_pos, direction.normalize(),0, new_pos.clone().distanceTo(start_pos));
                var collisionResults = ray.intersectObjects(obstacles);

                if(collisionResults.length===0)
                {
                    window.setTimeout(self.current_item.add_interraction_item.bind(self.current_item,item.type, item.params, true), delay);
                }
                distance+=Math.radians(20+Math.floor(Math.random()*180));
                if(distance>Math.radians(360))
                {
                    distance_step += opt.door_size*0.04;
                    distance= distance%Math.radians(360);
                }
            }
            delay+=drop_delay_multiple;
        });
    }

    this.get_attack_value = function(attack_object, defense_object)
    {
        var damage=0;
        var is_hit = Math.random() < attack_object.weapon_hit_chance;
        if(is_hit)
        {
            var quota = Math.random()*0.5+0.5;
            quota -=  defense_object.weapon_defense;
            damage = Math.ceil(quota*attack_object.weapon_attack_damage);
        }
        return Math.max(0,damage);
    };

    this.add_fadeout_text = function(params)
    {
        var text = params.text;
        var color = params.color;
        var size = params.size;
        var position = params.position;
        var delta_y = params.delta_y;

        var text_geo = new THREE.TextGeometry(text , {
            font: game.assets.text_font,
            size: size,
            height: 0,
            curveSegments: 4,
            bevelThickness: 1,
            bevelSize: 0.5,
            bevelEnabled: false,
            material: 0,
            extrudeMaterial: 1
        });
        text_geo.computeBoundingBox();
        var text_mesh = new THREE.Mesh( text_geo, new THREE.MeshPhongMaterial({color: color}));
        text_mesh.position.x= -( text_geo.boundingBox.max.x - text_geo.boundingBox.min.x)/2 + position.x;
        text_mesh.position.y= delta_y + position.y;
        text_mesh.position.z= -( text_geo.boundingBox.max.z - text_geo.boundingBox.min.z)/2 + position.z;
        
        //text_mesh.rotation.x = -this.camera.rotation.x;
        text_mesh.rotation.x=Math.radians(-90);
        text_mesh.rotation.y = -this.camera.rotation.y;
        text_mesh.rotation.z = -this.camera.rotation.z;

        text_mesh.animation_function = this.inc_scale_fadeout.bind(this, text_mesh);
        animations.push(text_mesh);

        this.scene.add(text_mesh);
        window.setTimeout(this.remove_fadeout_text.bind(this, text_mesh), 1000);
    };

    this.inc_scale_fadeout = function(mesh)
    {
        mesh.position.y+=0.3;
        mesh.scale.x+=0.05;
        mesh.scale.y+=0.05;
        mesh.scale.z+=0.05;
        mesh.material.transparent=true;
        mesh.material.opacity-=0.05;
    };

    this.remove_fadeout_text = function(mesh)
    {
        this.scene.remove(mesh);
        var idx = animations.indexOf(mesh);
        animations.splice(idx, 1);
    }

    this.fadeinmusic = function(audio)
    {
        if(audio.paused) { audio.play(); }
        if(audio.volume<game.config.music_volume)
        {
            audio.volume=Math.min(game.config.music_volume,audio.volume+0.1);
            window.clearTimeout(this.fadeinmusic_timer);
            this.fadeinmusic_timer = window.setTimeout(this.fadeinmusic.bind(this, audio), 100);
        }
        else
        {
            audio.volume = game.config.music_volume;
        }
    };

    this.fadeoutmusic = function(audio)
    {
        if(audio.volume>0)
        {
            audio.volume=Math.max(0,audio.volume-0.1);
            window.clearTimeout(this.fadeoutmusic_timer);
            this.fadeoutmusic_timer = window.setTimeout(this.fadeoutmusic.bind(this, audio), 100);
        }
        else
        {
            console.log('audio pause!');
            audio.pause()
        }
    };

};