Old stuff/old_sites/threejs/13_fighting/js/ennemy.js
(Deskargatu)
var Ennemy = function(game, options)
{
var self=this;
self.options = options;
self.game=game;
self.move_speed= 0.2;
self.run_speed= 1.1;
self.check_vision_every= 80;
self.is_running= false;
self.running_timer= null;
self.id='ennemy'+Math.random();
self.move_action_weight=0;
self.is_moving=false;
self.in_cells=[];
self.vision_distance=game.opt.door_size*1.5;
this.build = function()
{
this.patrol_id = 0;
this.patrol_inc = 1;
this.patrol_waiting_timer = null;
this.patrol_right_left_inc = 4;
this.patrol_right_left_deg = 180;
this.next_pos = this.get_next_patrol_point();
this.create();
};
};
Ennemy.prototype.create =function()
{
var self=this;
this.container = new THREE.Object3D();
this.game.scene.add(this.container);
// Cube simulating ennemy, for collision detection
var cube_material = new THREE.MeshBasicMaterial( { color: 0x0000ff, transparent:true, opacity: 0.3 } );
if(game.opt.debug_level>1)
{
cube_material = new THREE.MeshBasicMaterial( { color: 0x0000ff, transparent:true, opacity: 1 } );
}
var cube_geo = new THREE.BoxGeometry(6 , 6, 6);
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=1;
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;
// Vision geometry
this.vision_geom = new THREE.Geometry();
var deg_angle= 90;
var current_deg_angle = 0;
var angle = Math.radians(45-current_deg_angle);
var v1 = new THREE.Vector3(0, 1, 0);
var v2 = new THREE.Vector3(-Math.cos(angle)*this.vision_distance,1,Math.sin(angle)*this.vision_distance);
var v3 = new THREE.Vector3(Math.cos(angle)*this.vision_distance,1,Math.sin(angle)*this.vision_distance);
this.vision_orig_vertices=[];
this.vision_geom.vertices.push(v1);
this.vision_orig_vertices.push(v1.clone());
this.vision_geom.vertices.push(v2);
this.vision_orig_vertices.push(v2.clone());
this.vision_geom.vertices.push(v3);
this.vision_orig_vertices.push(v3.clone());
var vIndex=2;
for(true; current_deg_angle<deg_angle; current_deg_angle+=10)
{
var angle = Math.radians(90-current_deg_angle);
vLast = new THREE.Vector3(-Math.cos(angle)*this.vision_distance,1,Math.sin(angle)*this.vision_distance);
this.vision_geom.vertices.push(vLast);
this.vision_orig_vertices.push(vLast.clone());
vLast = new THREE.Vector3(Math.cos(angle)*this.vision_distance,1,Math.sin(angle)*this.vision_distance);
this.vision_geom.vertices.push(vLast);
this.vision_orig_vertices.push(vLast.clone());
this.vision_geom.faces.push(new THREE.Face3(0,vIndex-1,vIndex+1));
this.vision_geom.faces.push(new THREE.Face3(0,vIndex,vIndex+2));
vIndex+=2;
}
this.vision_geom.computeFaceNormals();
this.vision_geom.dynamic=true;
this.vision_geom.verticesNeedUpdate=true;
var vision_material = new THREE.MeshBasicMaterial( { color: 0x335533, transparent:true, opacity: 0.5 } );
if(game.opt.debug_level>1)
{
vision_material = new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe:true, transparent:true, opacity: 1 } );
}
this.vision = new THREE.Mesh( this.vision_geom, vision_material);
this.vision.rotation.y=Math.radians(0);
this.vision.position.x = this.options.x;
this.vision.position.y = 0;
this.vision.position.z = this.options.z;
game.scene.add(this.vision);
var materials = game.assets.ennemy_mat;
for ( var i = 0; i < materials.length; i ++ ) {
var m = materials[ i ];
m.skinning = true;
m.morphTargets = true;
}
this.mesh = new THREE.SkinnedMesh( game.assets.ennemy_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 = game.assets.ennemy_geo.animations[2];
this.iddlingClip = game.assets.ennemy_geo.animations[1];
this.move_action = this.mixer.clipAction(this.walkingClip, null ).setDuration(0.45);
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.walk();
};
Ennemy.prototype.run = function(destination)
{
window.clearTimeout(this.patrol_waiting_timer);
window.clearTimeout(this.running_timer);
this.patrol_waiting_timer=null;
this.running_timer=null;
this.move_destination = destination;
this.moveTo(this.move_destination);
this.lookAt(this.move_destination, this.move_destination);
if(!this.is_running)
{
this.is_running=true;
this.move_action.setDuration(0.45);
}
this.running_timer = window.setTimeout(this.walk.bind(this), 2000);
};
Ennemy.prototype.walk = function()
{
window.clearTimeout(this.running_timer);
window.clearTimeout(this.patrol_waiting_timer);
this.patrol_waiting_timer=null;
this.running_timer=null;
if(this.is_running)
{
this.is_running=false;
if(this.move_destination)
{
this.moveTo(this.move_destination);
this.move_action.setDuration(0.8);
}
}
};
Ennemy.prototype.lookAt= function(pos,view_pos)
{
pos.y=0;
this.container.lookAt(pos);
this.vision.lookAt(view_pos);
}
Ennemy.prototype.moveTo= function(pos)
{
var current_pos = this.container.position;
if(current_pos.equals(pos))
{
return;
}
// Last part of moving
this.is_moving=true;
var distance = Math.sqrt(Math.pow(pos.x-current_pos.x,2)+Math.pow(pos.z-current_pos.z,2));
var directionX = (pos.x-current_pos.x) / distance;
var directionZ = (pos.z-current_pos.z) / distance;
var speed = this.is_running ? this.run_speed : this.move_speed;
move_step_x = speed * directionX;
move_step_z = speed * directionZ;
this.move_step_vector_x = new THREE.Vector2();
this.move_step_vector_z = new THREE.Vector2();
this.move_step_vector_x.x = move_step_x;
this.move_step_vector_x.z=0;
this.move_step_vector_z.x=0;
this.move_step_vector_z.z = move_step_z;
// Actually moving...
this.move_destination = pos;
if(this.move_action_weight!=1)
{
this.move_weight_destination = 1;
}
};
Ennemy.prototype.move_step= function()
{
if(this.is_moving)
{
var moving=0;
// Patrol right/left
if(!this.is_running)
{
this.patrol_right_left_deg+=this.patrol_right_left_inc;
this.patrol_right_left_deg = this.patrol_right_left_deg%360;
var rad_ang = Math.radians(this.patrol_right_left_deg);
var diff_x = Math.abs(this.container.position.x>this.move_destination.x ? this.container.position.x-this.move_destination.x : this.move_destination.x - this.container.position.x);
var diff_z = Math.abs(this.container.position.z>this.move_destination.z ? this.container.position.z-this.move_destination.z : this.move_destination.z - this.container.position.z);
var distance = Math.sqrt(diff_x + diff_z);
if(distance>2)
{
this.lookAt(this.move_destination,{
x: this.move_destination.x + Math.cos(rad_ang) * distance,
y: this.move_destination.y,
z: this.move_destination.z + Math.sin(rad_ang) * distance
});
}
}
if(this.container.position.x!=this.move_destination.x || this.container.position.z!=this.move_destination.z)
{
moving++;
}
// Moving X restrictions
if(Math.abs(this.container.position.x - this.move_destination.x) > 1)
{
this.container.position.add(this.move_step_vector_x);
this.vision.position.add(this.move_step_vector_x);
}
else
{
this.container.position.x = this.move_destination.x;
this.vision.position.x = this.move_destination.x;
}
if(Math.abs(this.container.position.z - this.move_destination.z) > 1)
{
this.container.position.add(this.move_step_vector_z);
this.vision.position.add(this.move_step_vector_z);
}
else
{
this.container.position.z = this.move_destination.z;
this.vision.position.z = this.move_destination.z;
}
if(!moving)
{
game.assets.step_sound.pause();
this.move_weight_destination = 0;
this.is_moving=false;
this.move_destination=null;
}
}
else
{
this.patrol_right_left_deg+=this.patrol_right_left_inc;
this.patrol_right_left_deg = this.patrol_right_left_deg%360;
var rad_ang = Math.radians(this.patrol_right_left_deg);
var diff_x = Math.abs(this.container.position.x>this.next_pos.x ? this.container.position.x-this.next_pos.x : this.next_pos.x - this.container.position.x);
var diff_z = Math.abs(this.container.position.z>this.next_pos.z ? this.container.position.z-this.next_pos.z : this.next_pos.z - this.container.position.z);
var distance = Math.sqrt(diff_x + diff_z);
this.lookAt(this.next_pos,{
x: this.next_pos.x + Math.cos(rad_ang) * distance,
y: this.next_pos.y,
z: this.next_pos.z + Math.sin(rad_ang) * distance
});
}
};
Ennemy.prototype.update_vision = function()
{
this.check_vision_loop=1;
if(!this.check_vision_timer)
{
this.check_vision();
}
};
Ennemy.prototype.check_vision = function()
{
if(!this.check_vision_loop)
{
return;
}
// Collision callbacks
var originPoint = this.container.position;
var obstacles = game.getObstaclesWithPlayer();
var collisions=[];
for (var vertexIndex = 1; vertexIndex < this.vision.geometry.vertices.length; vertexIndex++)
{
var localVertex = this.vision.geometry.vertices[vertexIndex].clone();
var globalVertex = localVertex.applyMatrix4( this.vision.matrix );
var directionVector = globalVertex.sub( this.vision.position );
var ray = new THREE.Raycaster( originPoint, directionVector.clone().normalize(),0, this.vision_distance);
var collisionResults = ray.intersectObjects(obstacles);
this.vision.geometry.vertices[vertexIndex].x = this.vision_orig_vertices[vertexIndex].x;
this.vision.geometry.vertices[vertexIndex].y = this.vision_orig_vertices[vertexIndex].y;
this.vision.geometry.vertices[vertexIndex].z = this.vision_orig_vertices[vertexIndex].z;
this.vision.geometry.verticesNeedUpdate=true;
if ( collisionResults.length > 0 && collisionResults[0].distance < this.vision_distance)
{
// Display limited vision vertice
if(collisionResults[0].object.name=='walls')
{
var distance = collisionResults[0].distance;
this.vision.geometry.vertices[vertexIndex].x *= distance / this.vision_distance;
this.vision.geometry.vertices[vertexIndex].y *= distance / this.vision_distance;
this.vision.geometry.vertices[vertexIndex].z *= distance / this.vision_distance;
}
if(collisionResults[0].object.name=='p')
{
collisions.push(collisionResults[0].point);
}
}
}
if(collisions.length>0)
{
this.run(game.focus_perso.container.position.clone());
}
// Loop check vision
this.check_vision_loop=0;
this.check_vision_timer= window.setTimeout(this.check_vision_end.bind(this), this.check_vision_every);
};
Ennemy.prototype.check_vision_end = function()
{
this.check_vision_timer=null;
this.check_vision();
};
Ennemy.prototype.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.3);
this.move_action.setEffectiveWeight(dest);
this.idle_action.setEffectiveWeight(1-dest);
this.move_action_weight=dest;
}
else if(c<this.move_weight_destination)
{
var dest = Math.min(1,c+0.3);
this.move_action.setEffectiveWeight(dest);
this.idle_action.setEffectiveWeight(1-dest);
this.move_action_weight=dest;
}
else
{
this.move_weight_destination=null;
}
this.move_action_weight=c;
}
};
Ennemy.prototype.update= function(delta)
{
var self=this;
this.mixer.update(delta);
this.delta=delta;
if(!this.move_destination)
{
if(!this.patrol_waiting_timer)
{
var pos = this.next_pos;
this.lookAt(pos,pos);
console.log('will move to ',pos);
this.patrol_waiting_timer=window.setTimeout(function()
{
self.patrol_waiting_timer=null;
self.move_weight_destination=1;
self.moveTo(pos);
self.next_pos = self.get_next_patrol_point();
}, 2000);
}
}
this.move_step();
this.move_weight();
this.update_vision();
};
Ennemy.prototype.get_next_patrol_point = function()
{
var next_id = this.patrol_id+this.patrol_inc;
var next_inc = this.patrol_inc;
this.patrol_id+= next_inc
if(next_id<0)
{
next_inc=1;
next_id=1;
}
if(next_id>=this.options.patrol_positions.length)
{
next_id=this.options.patrol_positions.length-2;
next_inc=-1;
}
this.patrol_id=next_id;
this.patrol_inc=next_inc;
return this.options.patrol_positions[next_id];
};