var Perso = function(game) { var self=this; self.move_speed= 40; self.is_moving=false; self.in_rooms=[]; this.load= function() { var self=this; this.step_sound = new Audio('sounds/step.mp3'); this.step_sound.loop=true; this.step_sound.load(); return new Promise(function(ok, reject) { var loader = new THREE.JSONLoader(); loader.load( "blender/pingu_with_armature.json", function(geometry, mat) { self.perso_geo = geometry; self.perso_mat = mat; ok(); }); }); }; this.build = function(options, game) { this.game = game; this.options=options; this.create(); }; this.create =function() { var self=this; this.container = new THREE.Object3D(); this.game.scene.add(this.container); // Cube simulating perso, for collision detection var cube_material = new THREE.MeshBasicMaterial( { color: 0x0000ff, wireframe:true, transparent:true, opacity: game.opt.debug_level>1 ? 1 : 0 } ); var cube_geo = new THREE.PlaneGeometry(5 , 5); this.container_mesh = new THREE.Mesh(cube_geo, cube_material); this.container_mesh.rotation.x = Math.radians(90); this.container_mesh.rotation.z = Math.radians(45); this.container_mesh.position.y=0; this.container.add(this.container_mesh); this.container.position.x = this.options.x; this.container.position.y = 0; this.container.position.z = this.options.z; var materials = []; var mat1 = new THREE.MeshLambertMaterial({ color: 0xffff00} ); mat1.skinning=true; mat1.morphTargets=true; var mat2 = new THREE.MeshLambertMaterial({ color: 0x00ff00} ); mat2.skinning=true; mat2.morphTargets=true; var mat3 = new THREE.MeshLambertMaterial({ color: 0xff0000} ); mat3.skinning=true; mat3.morphTargets=true; materials.push(mat1); materials.push(mat2); materials.push(mat3); materials.push(mat2); materials.push(mat1); //material.skinning = true; //material.morphTargets = true; var materials = self.perso_mat; for ( var i = 0; i < materials.length; i ++ ) { var m = materials[ i ]; m.skinning = true; m.morphTargets = true; } this.mesh = new THREE.SkinnedMesh( self.perso_geo, new THREE.MultiMaterial(materials)); this.mesh.scale.x=15; this.mesh.scale.y=15; this.mesh.scale.z=15; this.container.add(this.mesh); this.mesh.receiveShadow = true; this.mesh.castShadow = true; this.mesh.position.x = 0; this.mesh.position.y = 1; this.mesh.position.z = 0; this.mixer = new THREE.AnimationMixer( this.mesh ); this.walkingClip = self.perso_geo.animations[2]; this.iddlingClip = self.perso_geo.animations[1]; this.move_action = this.mixer.clipAction(this.walkingClip, null ).setDuration(0.5); this.idle_action = this.mixer.clipAction(this.iddlingClip, null ).setDuration(5); this.move_action.play(); this.idle_action.play(); this.move_action.setEffectiveWeight(0); this.idle_action.setEffectiveWeight(1); }; this.getRayPos= function(event) { var raycaster = new THREE.Raycaster(); var mouse = new THREE.Vector2(); mouse.x = ( event.clientX / this.game.renderer.domElement.width ) * 2 - 1; mouse.y = - ( event.clientY / this.game.renderer.domElement.height ) * 2 + 1; raycaster.setFromCamera( mouse, this.game.camera ); var intersects = raycaster.intersectObjects( [this.game.click_ground], false ); if ( intersects.length > 0 ) { return intersects[0].point; } return null; } this.lookAtEvent= function(event) { var pos = this.getRayPos(event); if(pos) { this.lookAt(pos); } } this.lookAt= function(pos) { if(this.container) { pos.y=0; this.container.lookAt(pos); } } this.moveToEvent= function(event) { var pos = this.getRayPos(event); if(pos) { this.lookAt(pos); this.moveTo(pos); } } this.moveTo= function(pos) { var current_pos = this.container.position; // Last part of moving if(current_pos.equals(pos)) { return; } this.is_moving=true; // A: bottom right rectangle // B: start // C: destination var distance_ab = Math.abs(current_pos.x - pos.x); var distance_ac = Math.abs(current_pos.z - pos.z); var total = distance_ab + distance_ac; var ratio_x = (total-distance_ac) / total; var ratio_z = (total-distance_ab) / total; move_step_x = this.delta * this.move_speed * ratio_x; move_step_z = this.delta * this.move_speed * ratio_z; this.move_step_vector_x = new THREE.Vector2(); this.move_step_vector_z = new THREE.Vector2(); this.move_step_vector_x.x = current_pos.x>pos.x ? (- move_step_x) : move_step_x; this.move_step_vector_x.z=0; this.move_step_vector_z.x=0; this.move_step_vector_z.z = current_pos.z>pos.z ? (- move_step_z) : move_step_z; // Actually moving... this.move_destination = pos; this.move_weight_destination = 1; this.move_idx=0; }; this.move_step= function() { if(this.is_moving) { this.step_sound.play(); this.move_idx++; var moving=0; // Collision callbacks var originPoint_x = this.container.position.clone(); var obstacles = game.getObstacles(); var obstacles_with_callbacks = game.getCollisionCallbacks(); var objects=[]; for (var vertexIndex = 0; vertexIndex < this.container_mesh.geometry.vertices.length; vertexIndex++) { var localVertex = this.container_mesh.geometry.vertices[vertexIndex].clone(); var globalVertex = localVertex.applyMatrix4( this.container_mesh.matrix ); var directionVector = globalVertex.sub( this.container_mesh.position ); var ray = new THREE.Raycaster( originPoint_x, directionVector.clone().normalize() ); var collisionResults = ray.intersectObjects(obstacles_with_callbacks); if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) { objects.push(collisionResults[0].object); } } game.collisionCallbacks(this,objects); // Moving X restrictions if(Math.abs(this.container.position.x - this.move_destination.x) > this.move_speed*this.delta) { var originPoint_x = this.container.position.clone(); originPoint_x.add(this.move_step_vector_x); var collision_x=false; for (var vertexIndex = 0; vertexIndex < this.container_mesh.geometry.vertices.length; vertexIndex++) { var localVertex = this.container_mesh.geometry.vertices[vertexIndex].clone(); var globalVertex = localVertex.applyMatrix4( this.container_mesh.matrix ); var directionVector = globalVertex.sub( this.container_mesh.position ); var ray = new THREE.Raycaster( originPoint_x, directionVector.clone().normalize() ); var collisionResults = ray.intersectObjects(obstacles); if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) { collision_x=true; } } if(!collision_x) { moving++; this.container.position.add(this.move_step_vector_x); } } // Moving Z restrictions if(Math.abs(this.container.position.z - this.move_destination.z) > this.move_speed*this.delta) { var originPoint_z = this.container.position.clone(); originPoint_z.add(this.move_step_vector_z); var collision_z=false; for (var vertexIndex = 0; vertexIndex < this.container_mesh.geometry.vertices.length; vertexIndex++) { var localVertex = this.container_mesh.geometry.vertices[vertexIndex].clone(); var globalVertex = localVertex.applyMatrix4( this.container_mesh.matrix ); var directionVector = globalVertex.sub( this.container_mesh.position ); var ray = new THREE.Raycaster( originPoint_z, directionVector.clone().normalize() ); var collisionResults = ray.intersectObjects(obstacles); if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) { collision_z=true; } } if(!collision_z) { moving++; this.container.position.add(this.move_step_vector_z); } } if(!moving) { this.step_sound.pause(); this.move_weight_destination = 0; this.is_moving=false; this.move_destination=null; } } else { //this.move_action.stop(); } }; this.move_weight = function() { if(this.move_weight_destination!==null) { var c = this.move_action.getEffectiveWeight(); var dest; if(c>this.move_weight_destination) { var dest = Math.max(0,c-0.1); this.move_action.setEffectiveWeight(dest); this.idle_action.setEffectiveWeight(1-dest); } else if(c