591 lines
20 KiB
JavaScript
591 lines
20 KiB
JavaScript
var gorobots_render_webgl = function(){
|
|
var my = {};
|
|
var grey = "rgba(0, 0, 0, 0.5)";
|
|
var red = "rgba(200, 0, 0, 0.5)";
|
|
|
|
// Tracking last 50 frame lengths
|
|
var d = new Date();
|
|
my.delta_history = [];
|
|
my.last_frame_time = d.getTime();
|
|
my.delta = 0;
|
|
|
|
my.width = null;
|
|
my.height = null;
|
|
my.y_base = 16; // The top status bar
|
|
|
|
my.scene = null;
|
|
|
|
// Tracking the objects in the scene
|
|
my.robots = {};
|
|
my.objects = {};
|
|
my.dom_id = null;
|
|
my.target = null;
|
|
|
|
|
|
my.init = function(dom_id) {
|
|
my.dom_id = dom_id;
|
|
my.canvas = document.getElementById(dom_id);
|
|
$('body').keypress(function(e){
|
|
|
|
if (my.canvas.clientWidth === 0){
|
|
// dont respond to key events when canvas is not in view
|
|
return;
|
|
}
|
|
|
|
if(e.which == 118){
|
|
// v
|
|
my.currentcamera += 1;
|
|
if (my.currentcamera >= my.cameras.length) {
|
|
my.currentcamera = 0;
|
|
}
|
|
my.use_camera = my.cameras[my.currentcamera];
|
|
}
|
|
|
|
if (e.which == 45){
|
|
// -
|
|
if (my.use_camera == my.followcamera){
|
|
my.followcamera.fov = my.followcamera.fov - 5;
|
|
if (my.followcamera.fov < 5){
|
|
my.followcamera.fov = 5;
|
|
}
|
|
|
|
my.followcamera.updateProjectionMatrix();
|
|
}
|
|
if (my.use_camera == my.trackcamera){
|
|
my.track_area -= 10;
|
|
if (my.track_area < 50){
|
|
my.track_area = 50;
|
|
}
|
|
my.resize_view();
|
|
}
|
|
}
|
|
if (e.which == 61){
|
|
// =
|
|
if (my.use_camera == my.followcamera){
|
|
my.followcamera.fov = my.followcamera.fov + 5;
|
|
if (my.followcamera.fov > 120){
|
|
my.followcamera.fov = 120;
|
|
}
|
|
|
|
my.followcamera.updateProjectionMatrix();
|
|
}
|
|
if (my.use_camera == my.trackcamera){
|
|
my.track_area += 10;
|
|
if (my.track_area > 1000){
|
|
my.track_area = 1000;
|
|
}
|
|
my.resize_view();
|
|
}
|
|
|
|
}
|
|
if (e.which == 100){
|
|
// d
|
|
$(my.stats.domElement).toggle();
|
|
}
|
|
});
|
|
|
|
my.stats = new Stats();
|
|
my.stats.setMode(0); // 0: fps, 1: ms
|
|
|
|
// Align top-left
|
|
my.stats.domElement.style.position = 'absolute';
|
|
|
|
my.stats.domElement.style.left = '5px';
|
|
my.stats.domElement.style.top = '200px';
|
|
|
|
document.body.appendChild( my.stats.domElement );
|
|
$(my.stats.domElement).hide();
|
|
};
|
|
|
|
var random_color = function () {
|
|
var letters = '0123456789ABCDEF'.split('');
|
|
var color = '#';
|
|
for (var i = 0; i < 6; i++ ) {
|
|
color += letters[Math.round(Math.random() * 15)];
|
|
}
|
|
return color;
|
|
};
|
|
|
|
my.setup_cameras = function(){
|
|
console.log("Setting up cameras");
|
|
my.canvas = document.getElementById(my.dom_id);
|
|
my.cameras = [];
|
|
|
|
var pos = new THREE.Vector3(my.width / 2, my.height / 2, 0);
|
|
var game_aspect = my.height / my.width;
|
|
var aspect = my.canvas.clientHeight / my.canvas.clientWidth;
|
|
var scale = game_aspect/aspect;
|
|
if (scale < 1){
|
|
var new_scale = (1/game_aspect) / (1/aspect);
|
|
var s = (my.height * new_scale) / 2;
|
|
my.camera = new THREE.OrthographicCamera( 0, my.width , s + (my.height/2), -(s - (my.height/2)), 0.1, 200 );
|
|
} else {
|
|
var s = (my.width * scale) / 2;
|
|
my.camera = new THREE.OrthographicCamera( -(s - (my.width/2)), s + (my.width/2), my.height, 0, 0.1, 200 );
|
|
}
|
|
|
|
my.camera.position.z = 99;
|
|
my.camera.updateProjectionMatrix();
|
|
my.cameras.push(my.camera);
|
|
|
|
var view_aspect = my.canvas.clientHeight / my.canvas.clientWidth;
|
|
my.track_area = 300;
|
|
my.trackcamera = new THREE.OrthographicCamera( -my.track_area, my.track_area, my.track_area * view_aspect, -my.track_area * view_aspect, -100, 200 );
|
|
my.trackcamera.position.z = 100;
|
|
my.trackcamera.updateProjectionMatrix();
|
|
my.cameras.push(my.trackcamera);
|
|
|
|
my.followcamera = new THREE.PerspectiveCamera( 35, my.canvas.clientWidth / my.canvas.clientHeight, 1, 10000 );
|
|
my.followcamera.position = new THREE.Vector3(my.width / 2, -my.height + (my.height/2), (my.height / 2) + 200);
|
|
my.followcamera.up = new THREE.Vector3(0,0,1);
|
|
my.followcamera.lookAt(pos);
|
|
my.followcamera.updateProjectionMatrix();
|
|
my.controls = new THREE.TrackballControls( my.followcamera );
|
|
|
|
my.cameras.push(my.followcamera);
|
|
};
|
|
|
|
my.setup_render_target = function(map_width, map_height, screen_width, screen_height){
|
|
if (my.renderer){
|
|
console.log("Renderer already initialized");
|
|
my.reset();
|
|
return;
|
|
}
|
|
|
|
my.turn = 0;
|
|
my.robots = {};
|
|
my.objects = {};
|
|
my.labels = [];
|
|
my.scene = new THREE.Scene();
|
|
my.quit = false;
|
|
|
|
my.width = screen_width;
|
|
my.height = screen_height;
|
|
|
|
my.renderer = new THREE.WebGLRenderer({"canvas": my.canvas, antialias: true });
|
|
|
|
my.setup_cameras();
|
|
|
|
my.floorobj = new THREE.CubeGeometry(my.width, my.height, 0.1);
|
|
var material = new THREE.MeshLambertMaterial( { color: random_color() } );
|
|
|
|
my.floor = new THREE.Mesh(my.floorobj, material);
|
|
my.floor.position.x = my.width / 2;
|
|
my.floor.position.y = my.height / 2 ;
|
|
my.floor.position.z = -2;
|
|
my.scene.add(my.floor);
|
|
|
|
// Basic primitives
|
|
my.grey_material = new THREE.MeshLambertMaterial( { color: "#999999", transparent: false } );
|
|
my.red_material = new THREE.MeshLambertMaterial( { color: "#ff0000", transparent: true } );
|
|
my.black_material = new THREE.MeshLambertMaterial( { color: "#000000", transparent: false } );
|
|
|
|
my.robot_geom = new THREE.CubeGeometry(5,5,5);
|
|
|
|
var loader = new THREE.OBJLoader();
|
|
loader.load( '/ui/obj/robot.obj', function ( object ) {
|
|
object.position.x = 100;
|
|
object.position.y = 100;
|
|
object.position.z = 1;
|
|
object.up = new THREE.Vector3(0,0,1);
|
|
object.scale.set(5,5,5);
|
|
my.robot_geom = object;
|
|
} );
|
|
|
|
my.bullet_geom = new THREE.CubeGeometry(3,3,3);
|
|
my.splosion_geom = new THREE.SphereGeometry(1,50,50);
|
|
|
|
var axis = new THREE.AxisHelper(100);
|
|
my.scene.add(axis);
|
|
|
|
my.wallobjx = new THREE.CubeGeometry(my.width, 3, 3);
|
|
my.wallobjy = new THREE.CubeGeometry(3, my.height, 3);
|
|
var material = new THREE.MeshLambertMaterial( { color: "#cccccc" } );
|
|
|
|
my.scene.add(my.camera);
|
|
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.9 );
|
|
directionalLight.position.set( 0, 0, -1 );
|
|
my.scene.add( directionalLight );
|
|
|
|
var directionalLight2 = new THREE.DirectionalLight( 0xffffff, 0.9 );
|
|
directionalLight2.position.set( 0, 0.707, 0.707 );
|
|
my.scene.add( directionalLight2 );
|
|
|
|
var ambientLight = new THREE.AmbientLight(0x222222, 0.7);
|
|
my.scene.add(ambientLight);
|
|
|
|
my.currentcamera = 2;
|
|
my.use_camera = my.cameras[my.currentcamera];
|
|
|
|
var render = function render() {
|
|
my.stats.begin();
|
|
my.renderer.render(my.scene, my.use_camera);
|
|
my.update_labels();
|
|
if (my.controls){
|
|
my.controls.update();
|
|
}
|
|
|
|
if (!my.quit)
|
|
requestAnimationFrame(render);
|
|
|
|
my.stats.end();
|
|
};
|
|
render();
|
|
|
|
$(window).resize(function(){
|
|
my.resize_view();
|
|
});
|
|
|
|
my.resize_view();
|
|
};
|
|
|
|
my.resize_view = function(){
|
|
my.canvas.height = ($(window).height() - $(my.canvas).offset().top);
|
|
my.canvas.width = $(window).width();
|
|
var game_aspect = my.height / my.width;
|
|
var aspect = my.canvas.clientHeight / my.canvas.clientWidth;
|
|
var scale = game_aspect/aspect;
|
|
if (scale < 1){
|
|
var new_scale = (1/game_aspect) / (1/aspect);
|
|
var s = (my.height * new_scale) / 2;
|
|
my.camera.left = 0;
|
|
my.camera.right = my.width;
|
|
my.camera.top = s + (my.height/2);
|
|
my.camera.bottom = -(s - (my.height/2));
|
|
} else {
|
|
var s = (my.width * scale) / 2;
|
|
my.camera.left = -(s - (my.width/2));
|
|
my.camera.right = s + (my.width/2);
|
|
my.camera.top = my.height;
|
|
my.camera.bottom = 0;
|
|
}
|
|
my.camera.updateProjectionMatrix();
|
|
|
|
var view_aspect = my.canvas.clientHeight / my.canvas.clientWidth;
|
|
my.trackcamera.left = -my.track_area;
|
|
my.trackcamera.right = my.track_area;
|
|
my.trackcamera.top = my.track_area * view_aspect;
|
|
my.trackcamera.bottom = -my.track_area * view_aspect;
|
|
my.trackcamera.updateProjectionMatrix();
|
|
|
|
my.followcamera.aspect = my.canvas.clientWidth / my.canvas.clientHeight;
|
|
my.followcamera.updateProjectionMatrix();
|
|
|
|
my.use_camera = my.cameras[my.currentcamera];
|
|
my.renderer.context.viewport(0, 0, my.canvas.width, my.canvas.height);
|
|
};
|
|
|
|
my.begin_frame = function(turn){
|
|
my.turn = turn;
|
|
var d = new Date();
|
|
var time = d.getTime();
|
|
my.delta = time - my.last_frame_time;
|
|
my.delta_history.unshift(my.delta);
|
|
if (my.delta_history.length > 50){
|
|
my.delta_history.pop();
|
|
}
|
|
|
|
my.last_frame_time = time;
|
|
|
|
// Status Bar Text
|
|
var slowest = Math.max.apply(null, my.delta_history);
|
|
var debug_string = slowest + "ms";
|
|
};
|
|
|
|
my.render = function(draw_list){
|
|
var obj_count = 0;
|
|
|
|
for (var i in draw_list) {
|
|
var robot_data = draw_list[i];
|
|
var key, geometry, material, cube = null;
|
|
|
|
if (robot_data['type'] == 'object'){
|
|
|
|
key = robot_data['type'] + robot_data.bounds[0] + robot_data.bounds[1];
|
|
if (!(key in my.objects)){
|
|
obj_count++;
|
|
console.log(robot_data);
|
|
x = robot_data.bounds[0];
|
|
y = robot_data.bounds[1];
|
|
w = robot_data.bounds[2] - robot_data.bounds[0];
|
|
h = robot_data.bounds[3] - robot_data.bounds[1];
|
|
|
|
geometry = new THREE.CubeGeometry(w,h,5 + Math.round(Math.random() * 25));
|
|
var material = new THREE.MeshLambertMaterial( { color: random_color(), transparent: false } );
|
|
cube = new THREE.Mesh( geometry, material );
|
|
|
|
my.scene.add( cube );
|
|
cube.position.x = x + (w / 2);
|
|
cube.position.y = y + (h / 2);
|
|
cube.position.z = 0;
|
|
cube.turn = my.turn;
|
|
|
|
my.objects[key] = cube;
|
|
continue;
|
|
} else {
|
|
my.objects[key].turn = my.turn;
|
|
}
|
|
}
|
|
else{
|
|
key = robot_data['type'] + robot_data['id'];
|
|
|
|
if (!(key in my.robots)){
|
|
|
|
if (robot_data['type'] == 'bullet'){
|
|
material = my.black_material;
|
|
geometry = my.bullet_geom;
|
|
cube = new THREE.Mesh( geometry, material );
|
|
}
|
|
else if (robot_data['type'] == 'explosion'){
|
|
size = robot_data.radius;
|
|
material = my.red_material;
|
|
geometry = my.splosion_geom;
|
|
material.opacity = 0.8;
|
|
cube = new THREE.Mesh( geometry, material );
|
|
cube.scale.set(size, size, size);
|
|
}
|
|
else {
|
|
material = new THREE.MeshLambertMaterial( { color: robot_data['color'], transparent: false } );
|
|
geometry = my.robot_geom;
|
|
cube = geometry.clone();
|
|
cube.traverse(function ( geo ) {
|
|
geo.material = new THREE.MeshLambertMaterial( { color: robot_data['color'] } );
|
|
} );
|
|
my.make_bot_label(robot_data.id, robot_data.name, cube);
|
|
}
|
|
|
|
my.robots[key] = cube;
|
|
my.scene.add(cube);
|
|
cube.position.x = robot_data['position']['x'];
|
|
cube.position.y = robot_data['position']['y'];
|
|
cube.position.z = -1;
|
|
cube.turn = my.turn;
|
|
}
|
|
else{
|
|
my.robots[key].position.x = robot_data['position']['x'];
|
|
my.robots[key].position.y = robot_data['position']['y'];
|
|
my.robots[key].turn = my.turn;
|
|
|
|
if ("heading" in robot_data){
|
|
if (robot_data['heading']['x'] == 0 && robot_data['heading']['y'] == 0) {
|
|
robot_data['heading']['y'] = 1;
|
|
}
|
|
var tmp = new THREE.Vector3(
|
|
robot_data['heading']['x'] + robot_data.position.x,
|
|
robot_data['heading']['y'] + robot_data.position.y,
|
|
-1);
|
|
my.robots[key].up = new THREE.Vector3(0,0,1);
|
|
my.robots[key].lookAt( tmp );
|
|
}
|
|
|
|
if (robot_data.health){
|
|
var h = Math.round((robot_data.health / 200) * 100) + "%";
|
|
var x = "#health_" + robot_data.id;
|
|
$(x).css({
|
|
"width": h
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Worth noting this list contains robots, bullets and explosions
|
|
// it's badly named, I am sorry!
|
|
for (var q in my.robots){
|
|
if (my.turn - my.robots[q].turn > 1){
|
|
// find and remove label?
|
|
for (var w in my.labels){
|
|
if (my.labels[w].target == my.robots[q]){
|
|
my.labels[w].label.remove();
|
|
my.labels.splice(w, 1);
|
|
}
|
|
}
|
|
|
|
// Can I do this? I dont think so, we dont know
|
|
// if these things will ever be back
|
|
|
|
// my.robots[q].traverse(function ( geo ) {
|
|
// geo.visible = false;
|
|
// });
|
|
|
|
my.scene.remove(my.robots[q]);
|
|
delete my.robots[q];
|
|
}
|
|
}
|
|
|
|
for (var q in my.objects){
|
|
if (my.turn - my.objects[q].turn > 1){
|
|
my.objects[q].visible = false;
|
|
} else {
|
|
my.objects[q].visible = true;
|
|
}
|
|
}
|
|
|
|
for (var p in draw_list){
|
|
if (draw_list[p]['type'] == "robot"){
|
|
if (draw_list[p]['id'] == my.target){
|
|
var pos = new THREE.Vector3(draw_list[p].position.x, draw_list[p].position.y, 0);
|
|
my.followcamera.lookAt(pos);
|
|
my.controls.target = pos;
|
|
my.trackcamera.position.x = pos.x;
|
|
my.trackcamera.position.y = pos.y;
|
|
|
|
my.trackcamera.updateProjectionMatrix();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
var projector = new THREE.Projector();
|
|
|
|
my.update_labels = function(){
|
|
for (var i in my.labels){
|
|
var label = my.labels[i];
|
|
var screen_pos = label.target.position.clone();
|
|
var x = $(my.canvas).position();
|
|
if (my.canvas.clientWidth === 0){
|
|
$(label.label).css({
|
|
display: "none"});
|
|
} else {
|
|
projector.projectVector( screen_pos, my.use_camera );
|
|
if (screen_pos.x > 1 || screen_pos.x < -1 || screen_pos.y > 1 || screen_pos.y < -1){
|
|
$(label.label).css({
|
|
display: "none"});
|
|
continue;
|
|
}
|
|
|
|
var sx = (screen_pos.x * ((my.canvas.clientWidth)/2)) + ((my.canvas.clientWidth)/2) + x.left;
|
|
var sy = -(screen_pos.y * ((my.canvas.clientHeight)/2)) + ((my.canvas.clientHeight)/2) + x.top - 30;
|
|
$(label.label).css({
|
|
position: "absolute",
|
|
display:"block",
|
|
marginLeft: 0,
|
|
marginTop: 0,
|
|
top: sy,
|
|
left: sx});
|
|
}
|
|
}
|
|
};
|
|
|
|
my.make_bot_label = function(id, text, track_object){
|
|
var obj = $("<div class='label' style='display:none;'>" + text + "<div class='health' id='health_" + id + "'></div></div>");
|
|
$("body").append(obj);
|
|
my.labels.push({
|
|
label: obj,
|
|
target: track_object
|
|
});
|
|
};
|
|
|
|
my.debug_labels = [];
|
|
my.debug_lines = [];
|
|
|
|
my.clear_debug = function(){
|
|
for (var i in my.debug_labels){
|
|
my.debug_labels[i].remove();
|
|
}
|
|
|
|
my.debug_labels = [];
|
|
|
|
for (var i in my.debug_lines){
|
|
my.scene.remove(my.debug_lines[i]);
|
|
}
|
|
delete my.debug_lines;
|
|
my.debug_lines = [];
|
|
};
|
|
|
|
my.debug_label = function(x, y, msg){
|
|
if (my.canvas.clientWidth > 0){
|
|
var screen_pos = new THREE.Vector3(x, y, 0);
|
|
var canvas_pos = $(my.canvas).position();
|
|
projector.projectVector( screen_pos, my.use_camera );
|
|
|
|
if (screen_pos.x > 1 || screen_pos.x < -1 || screen_pos.y > 1 || screen_pos.y < -1){
|
|
return;
|
|
}
|
|
|
|
var sx = (screen_pos.x * ((my.canvas.clientWidth)/2)) + ((my.canvas.clientWidth)/2) + canvas_pos.left;
|
|
var sy = -(screen_pos.y * ((my.canvas.clientHeight)/2)) + ((my.canvas.clientHeight)/2) + canvas_pos.top;
|
|
var obj = $("<div class='label'>" + msg + "</div>");
|
|
$("body").append(obj);
|
|
$(obj).css({
|
|
position: "absolute",
|
|
marginLeft: 0,
|
|
marginTop: 0,
|
|
top: sy,
|
|
left: sx});
|
|
|
|
my.debug_labels.push(obj);
|
|
}
|
|
};
|
|
|
|
my.debug_label_screen = function(x, y, msg){
|
|
if (my.canvas.clientWidth > 0){
|
|
|
|
var canvas_pos = $(my.canvas).position();
|
|
var obj = $("<div class='label'>" + msg + "</div>");
|
|
$("body").append(obj);
|
|
$(obj).css({
|
|
position: "absolute",
|
|
marginLeft: 0,
|
|
marginTop: 0,
|
|
top: y + canvas_pos.top,
|
|
left: x + canvas_pos.left});
|
|
|
|
my.debug_labels.push(obj);
|
|
}
|
|
};
|
|
|
|
my.debug_line = function(x1, y1, x2, y2){
|
|
var material = new THREE.LineBasicMaterial({
|
|
color: 0x0000ff
|
|
});
|
|
|
|
var geometry = new THREE.Geometry();
|
|
geometry.vertices.push(new THREE.Vector3(x1, y1, 0));
|
|
geometry.vertices.push(new THREE.Vector3(x2, y2, 0));
|
|
|
|
var line = new THREE.Line(geometry, material);
|
|
my.scene.add(line);
|
|
my.debug_lines.push(line);
|
|
};
|
|
|
|
my.set_focus_robot = function(id){
|
|
my.target = id;
|
|
};
|
|
|
|
my.reset = function(){
|
|
for (var i in my.objects){
|
|
my.scene.remove(my.objects[i]);
|
|
}
|
|
delete my.objects;
|
|
my.objects = {};
|
|
|
|
for (i in my.robots){
|
|
my.scene.remove(my.robots[i]);
|
|
}
|
|
delete my.robots;
|
|
my.robots = {};
|
|
|
|
my.clear_debug();
|
|
|
|
for (i in my.labels){
|
|
my.labels[i].label.remove();
|
|
}
|
|
my.labels = [];
|
|
};
|
|
|
|
my.end_frame = function(){
|
|
|
|
};
|
|
|
|
my.shutdown = function(){
|
|
my.reset();
|
|
my.quit = true;
|
|
};
|
|
|
|
return my;
|
|
};
|