|
|
|
|
|
window.erasing_radius = 15; |
|
window.asset_size = 8; |
|
|
|
|
|
window.ground = []; |
|
window.ceiling = []; |
|
|
|
|
|
window.terrain = { |
|
ground: [], |
|
ceiling: [] |
|
}; |
|
|
|
|
|
window.align_terrain = { |
|
align: true, |
|
ceiling_offset: null, |
|
ground_offset: null, |
|
smoothing: null |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function init_game(cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, |
|
smoothing, creepers_type, ground, ceiling, align, zoom=null, scroll=null) { |
|
|
|
let agents = { |
|
morphologies: [], |
|
policies: [], |
|
positions: [] |
|
} |
|
|
|
|
|
if(window.game != null){ |
|
window.game.pause(); |
|
agents.morphologies = [...window.game.env.agents.map(a => a.morphology)]; |
|
agents.policies = [...window.game.env.agents.map(a => a.policy)]; |
|
agents.positions = [...window.game.env.agents.map(agent => agent.agent_body.reference_head_object.GetPosition())]; |
|
} |
|
window.game = new Game(agents, cppn_input_vector, water_level, creepers_width, creepers_height, |
|
creepers_spacing, smoothing, creepers_type, ground, ceiling, align); |
|
window.set_agent_selected(-1); |
|
window.asset_selected = null; |
|
|
|
if(zoom == null){ |
|
window.game.env.set_zoom(INIT_ZOOM); |
|
} |
|
else { |
|
window.game.env.set_zoom(zoom); |
|
} |
|
|
|
if(scroll == null){ |
|
window.game.env.set_scroll(window.agent_selected, INIT_SCROLL_X, 0); |
|
} |
|
else{ |
|
window.game.env.set_scroll(window.agent_selected, scroll[0], scroll[1]); |
|
} |
|
window.game.env.render(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getCreepersType() { |
|
return document.getElementById("creepersType").value == 'Swingable'; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
async function onLoadInit() { |
|
window.cppn_model = await tf.loadGraphModel('./js/CPPN/weights/same_ground_ceiling_cppn/tfjs_model/model.json'); |
|
window.init_default(); |
|
window.loadDefaultEnv(); |
|
window.langIntroSetUp(); |
|
} |
|
|
|
|
|
window.addEventListener("load", onLoadInit, false); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function convertPosCanvasToEnv(x_pos, y_pos){ |
|
let x = Math.max(-window.canvas.width * 0.01, Math.min(x_pos, window.canvas.width * 1.01)); |
|
let y = Math.max(0, Math.min(y_pos, window.canvas.height)); |
|
|
|
x += window.game.env.scroll[0]; |
|
y = -(y - window.game.env.scroll[1]); |
|
|
|
x = x / (window.game.env.scale * window.game.env.zoom); |
|
y = y / (window.game.env.scale * window.game.env.zoom); |
|
|
|
y += (1 - window.game.env.scale * window.game.env.zoom) * RENDERING_VIEWER_H/(window.game.env.scale * window.game.env.zoom) |
|
+ (window.game.env.zoom - 1) * (window.game.env.ceiling_offset)/window.game.env.zoom * 1/3 + RENDERING_VIEWER_H; |
|
|
|
return {x: x, y: y}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function convertPosEnvToCanvas(x_pos, y_pos){ |
|
let x = x_pos * window.game.env.scale * window.game.env.zoom - window.game.env.scroll[0]; |
|
let y = window.game.env.scroll[1] - (y_pos - RENDERING_VIEWER_H) * window.game.env.scale * window.game.env.zoom |
|
+ (1 - window.game.env.scale * window.game.env.zoom) * RENDERING_VIEWER_H |
|
+ (window.game.env.zoom - 1) * window.game.env.ceiling_offset * window.game.env.scale * 1/3; |
|
|
|
return {x: x, y: y}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function isPosInsideBody(pos, body){ |
|
let shape = body.GetFixtureList().GetShape(); |
|
|
|
if(shape.m_type == b2.Shape.e_circle){ |
|
let center = body.GetWorldCenter(); |
|
return Math.pow(center.x - pos.x, 2) + Math.pow(center.y - pos.y, 2) <= Math.pow(shape.m_radius, 2); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
function mousePressed(){ |
|
|
|
|
|
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el, index) => { |
|
let tooltip = bootstrap.Tooltip.getInstance(el); |
|
tooltip.hide(); |
|
}); |
|
|
|
|
|
if(mouseX >= 0 && mouseX <= window.canvas.width |
|
&& mouseY >= 0 && mouseY <= window.canvas.height){ |
|
|
|
|
|
window.prevMouseX = mouseX; |
|
window.prevMouseY = mouseY; |
|
|
|
|
|
if(window.is_drawing_circle()){ |
|
let mousePos = convertPosCanvasToEnv(mouseX, mouseY); |
|
window.game.env.create_circle_asset(mousePos, window.asset_size * 2 / window.game.env.scale); |
|
|
|
if(window.agent_selected != null){ |
|
window.agent_selected.is_selected = false; |
|
window.set_agent_selected(-1); |
|
} |
|
window.game.env.render(); |
|
} |
|
|
|
|
|
else if(!window.is_drawing()){ |
|
let mousePos = convertPosCanvasToEnv(mouseX, mouseY); |
|
|
|
|
|
let one_agent_touched = false; |
|
for(let i = 0; i < window.game.env.agents.length; i++){ |
|
let agent = window.game.env.agents[i]; |
|
|
|
|
|
let is_agent_touched = agent.agent_body.isPosInside(mousePos); |
|
|
|
|
|
if(is_agent_touched){ |
|
one_agent_touched = true; |
|
|
|
if(!agent.is_selected) { |
|
agent.is_selected = true; |
|
window.set_agent_selected(i); |
|
for (let other_agent of window.game.env.agents) { |
|
if (other_agent != agent) { |
|
other_agent.is_selected = false; |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
|
|
else { |
|
agent.is_selected = false; |
|
} |
|
} |
|
|
|
|
|
if(!one_agent_touched && window.agent_selected != null){ |
|
window.set_agent_selected(-1); |
|
} |
|
|
|
|
|
if(!one_agent_touched){ |
|
let one_asset_touched = false; |
|
for(let asset of window.game.env.assets_bodies){ |
|
|
|
|
|
let is_asset_touched = isPosInsideBody(mousePos, asset.body); |
|
|
|
|
|
if(is_asset_touched){ |
|
one_asset_touched = true; |
|
|
|
if(!asset.is_selected){ |
|
asset.is_selected = true; |
|
window.asset_selected = asset; |
|
for(let other_asset of window.game.env.assets_bodies){ |
|
if(other_asset != asset){ |
|
other_asset.is_selected = false; |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
|
|
else if(!is_asset_touched){ |
|
asset.is_selected = false; |
|
} |
|
} |
|
|
|
|
|
if(!one_asset_touched && window.asset_selected != null){ |
|
window.asset_selected = null; |
|
} |
|
} |
|
|
|
window.game.env.render(); |
|
} |
|
} |
|
} |
|
|
|
|
|
document.addEventListener('mousedown', (event) => { |
|
if(window.is_drawing() || window.is_drawing_circle()){ |
|
let canvas_id = "#" + window.canvas.canvas.id; |
|
|
|
|
|
let authorized_elements = [ |
|
document.querySelector(canvas_id), |
|
document.querySelector('#drawGroundButton'), |
|
document.querySelector('#drawCeilingButton'), |
|
document.querySelector('#eraseButton') |
|
]; |
|
|
|
|
|
if(authorized_elements.indexOf(event.target) == -1) { |
|
window.deselectDrawingButtons(); |
|
} |
|
} |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
function mouseDragged(){ |
|
|
|
|
|
if(mouseX >= 0 && mouseX <= window.canvas.width |
|
&& mouseY >= 0 && mouseY <= window.canvas.height) { |
|
|
|
|
|
if(window.is_drawing()) { |
|
|
|
|
|
let mousePos = convertPosCanvasToEnv(mouseX, mouseY); |
|
|
|
|
|
let y_offset = SCROLL_Y_MAX - window.game.env.scroll[1]; |
|
|
|
|
|
if(window.is_drawing_ground() && mousePos.x > (INITIAL_TERRAIN_STARTPAD - 1) * TERRAIN_STEP){ |
|
drawing_canvas.push(); |
|
drawing_canvas.stroke("#66994D"); |
|
drawing_canvas.strokeWeight(4); |
|
|
|
drawing_canvas.line(mouseX, mouseY + y_offset, window.prevMouseX, window.prevMouseY + y_offset); |
|
drawing_canvas.pop(); |
|
window.terrain.ground.push(mousePos); |
|
} |
|
|
|
|
|
else if(window.is_drawing_ceiling() && mousePos.x > (INITIAL_TERRAIN_STARTPAD - 1) * TERRAIN_STEP){ |
|
drawing_canvas.push(); |
|
drawing_canvas.stroke("#808080"); |
|
drawing_canvas.strokeWeight(4); |
|
|
|
drawing_canvas.line(mouseX, mouseY + y_offset, window.prevMouseX, window.prevMouseY + y_offset); |
|
drawing_canvas.pop(); |
|
window.terrain.ceiling.push(mousePos); |
|
} |
|
|
|
|
|
else if(window.is_erasing() && mousePos.x > INITIAL_TERRAIN_STARTPAD * TERRAIN_STEP){ |
|
|
|
|
|
trace_canvas.clear(); |
|
trace_canvas.noStroke(); |
|
trace_canvas.fill(255); |
|
trace_canvas.circle(mouseX, mouseY + y_offset, window.erasing_radius * 2); |
|
|
|
|
|
window.terrain.ground = window.terrain.ground.filter(function(point, index, array){ |
|
return Math.pow(point.x - mousePos.x, 2) + Math.pow(point.y - mousePos.y, 2) > Math.pow(window.erasing_radius / (window.game.env.scale * window.game.env.zoom), 2); |
|
}); |
|
window.terrain.ceiling = window.terrain.ceiling.filter(function(point, index, array){ |
|
return Math.pow(point.x - mousePos.x, 2) + Math.pow(point.y - mousePos.y, 2) > Math.pow(window.erasing_radius / (window.game.env.scale * window.game.env.zoom), 2); |
|
}); |
|
|
|
|
|
drawing_canvas.erase(); |
|
drawing_canvas.circle(mouseX, mouseY + y_offset, window.erasing_radius * 2); |
|
drawing_canvas.noErase(); |
|
} |
|
|
|
|
|
else{ |
|
cursor(MOVE); |
|
window.game.env.set_scroll(null, window.game.env.scroll[0] + window.prevMouseX - mouseX, window.game.env.scroll[1] + mouseY - prevMouseY); |
|
|
|
|
|
window.refresh_drawing(); |
|
y_offset = SCROLL_Y_MAX - window.game.env.scroll[1]; |
|
} |
|
|
|
|
|
window.game.env.render(); |
|
image(drawing_canvas, 0, -y_offset); |
|
image(trace_canvas, 0, -y_offset); |
|
image(forbidden_canvas, 0, -y_offset); |
|
} |
|
|
|
|
|
else{ |
|
cursor(MOVE); |
|
|
|
|
|
for (let agent of window.game.env.agents) { |
|
|
|
|
|
if (agent.is_selected) { |
|
|
|
|
|
let terrain_length; |
|
if (agent.agent_body.body_type == BodyTypesEnum.CLIMBER) { |
|
terrain_length = window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x; |
|
} |
|
else if (agent.agent_body.body_type == BodyTypesEnum.WALKER) { |
|
terrain_length = window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x; |
|
} |
|
else if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ |
|
terrain_length = Math.max(window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x, |
|
window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x); |
|
} |
|
|
|
|
|
let mousePos = convertPosCanvasToEnv(mouseX, mouseY); |
|
let x = Math.max(0.02, Math.min(0.98, mousePos.x / terrain_length)) * terrain_length; |
|
|
|
|
|
window.game.env.set_agent_position(agent, x, mousePos.y); |
|
window.game.env.render(); |
|
window.is_dragging_agent = true; |
|
break; |
|
} |
|
} |
|
|
|
|
|
for(let asset of window.game.env.assets_bodies){ |
|
|
|
|
|
if (asset.is_selected && !window.is_dragging_agent) { |
|
let terrain_length = Math.max(window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x, |
|
window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x); |
|
|
|
|
|
let mousePos = convertPosCanvasToEnv(mouseX, mouseY); |
|
mousePos.x = Math.max(0.02, Math.min(0.98, mousePos.x / terrain_length)) * terrain_length; |
|
|
|
|
|
window.game.env.set_asset_position(asset, mousePos); |
|
window.game.env.render(); |
|
window.is_dragging_asset = true; |
|
} |
|
} |
|
|
|
|
|
if(!window.is_dragging_agent && !window.is_dragging_asset){ |
|
|
|
|
|
if(window.agent_followed != null){ |
|
window.set_agent_followed(-1); |
|
} |
|
window.game.env.set_scroll(null, window.game.env.scroll[0] + window.prevMouseX - mouseX, window.game.env.scroll[1] + mouseY - prevMouseY); |
|
window.game.env.render(); |
|
} |
|
} |
|
} |
|
|
|
|
|
else if(window.is_dragging_agent |
|
&& mouseY >= 0 && mouseY < window.canvas.height){ |
|
|
|
if(mouseX < 0){ |
|
window.dragging_side = "left"; |
|
} |
|
else if(mouseX > window.canvas.width){ |
|
window.dragging_side = "right"; |
|
} |
|
|
|
cursor(MOVE); |
|
|
|
|
|
for (let agent of window.game.env.agents) { |
|
|
|
|
|
if (agent.is_selected) { |
|
|
|
|
|
window.game.env.set_scroll(null); |
|
|
|
|
|
let terrain_length; |
|
if (agent.agent_body.body_type == BodyTypesEnum.CLIMBER) { |
|
terrain_length = window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x; |
|
} |
|
else if (agent.agent_body.body_type == BodyTypesEnum.WALKER) { |
|
terrain_length = window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x; |
|
} |
|
else if(agent.agent_body.body_type == BodyTypesEnum.SWIMMER){ |
|
terrain_length = Math.max(window.game.env.terrain_ground[window.game.env.terrain_ground.length - 1].x, |
|
window.game.env.terrain_ceiling[window.game.env.terrain_ceiling.length - 1].x); |
|
} |
|
|
|
|
|
let mousePos = convertPosCanvasToEnv(mouseX, mouseY); |
|
let x = Math.max(0.02, Math.min(0.98, mousePos.x / terrain_length)) * terrain_length; |
|
|
|
|
|
window.game.env.set_agent_position(agent, x, mousePos.y); |
|
window.game.env.render(); |
|
break; |
|
} |
|
} |
|
|
|
|
|
return false; |
|
} |
|
|
|
window.prevMouseX = mouseX; |
|
window.prevMouseY = mouseY; |
|
} |
|
|
|
|
|
|
|
|
|
function mouseReleased(){ |
|
cursor(); |
|
window.is_dragging_agent = false; |
|
window.is_dragging_asset = false; |
|
window.dragging_side = null; |
|
} |
|
|
|
|
|
|
|
|
|
function mouseMoved(){ |
|
|
|
|
|
if(window.is_drawing_circle()){ |
|
trace_canvas.clear(); |
|
if(mouseX >= 0 && mouseX <= window.canvas.width |
|
&& mouseY >= 0 && mouseY <= window.canvas.height) { |
|
trace_canvas.noStroke(); |
|
trace_canvas.fill(136, 92, 0, 180); |
|
trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.asset_size * 4 * window.game.env.zoom); |
|
} |
|
window.game.env.render(); |
|
image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
} |
|
|
|
|
|
else if (window.is_erasing()) { |
|
trace_canvas.clear(); |
|
if (mouseX >= 0 && mouseX <= window.canvas.width |
|
&& mouseY >= 0 && mouseY <= window.canvas.height) { |
|
trace_canvas.noStroke(); |
|
trace_canvas.fill(255, 180); |
|
trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.erasing_radius * 2); |
|
} |
|
window.game.env.render(); |
|
image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function mouseWheel(event){ |
|
if(mouseX >= 0 && mouseX <= window.canvas.width |
|
&& mouseY >= 0 && mouseY <= window.canvas.height) { |
|
|
|
trace_canvas.clear(); |
|
|
|
|
|
if(window.is_drawing_circle()){ |
|
window.asset_size = Math.max(3, Math.min(window.asset_size - event.delta / 100, 30)); |
|
trace_canvas.noStroke(); |
|
trace_canvas.fill(136, 92, 0, 180); |
|
trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.asset_size * 4 * window.game.env.zoom); |
|
window.game.env.render(); |
|
image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
} |
|
|
|
|
|
else if(window.is_erasing()){ |
|
window.erasing_radius = Math.max(5, Math.min(window.erasing_radius - event.delta / 100, 30)); |
|
trace_canvas.noStroke(); |
|
trace_canvas.fill(255, 180); |
|
trace_canvas.circle(mouseX, mouseY + SCROLL_Y_MAX - window.game.env.scroll[1], window.erasing_radius * 2); |
|
window.game.env.render(); |
|
image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
image(trace_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
} |
|
|
|
|
|
else { |
|
window.game.env.set_zoom(window.game.env.zoom - event.delta / 2000); |
|
|
|
window.game.env.set_scroll(null, window.game.env.scroll[0], window.game.env.scroll[1]); |
|
|
|
|
|
if(window.is_drawing()){ |
|
window.refresh_drawing(); |
|
window.game.env.render(); |
|
image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
} |
|
else{ |
|
window.game.env.render(); |
|
} |
|
|
|
} |
|
|
|
|
|
return false; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function keyPressed(){ |
|
|
|
if(keyCode == DELETE){ |
|
if(window.agent_selected != null){ |
|
window.delete_agent(agent_selected); |
|
window.agent_selected(null); |
|
return false; |
|
} |
|
else if(window.asset_selected != null){ |
|
window.game.env.delete_asset(window.asset_selected); |
|
window.asset_selected = null; |
|
window.game.env.render(); |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
function windowResized(){ |
|
|
|
let canvas_container = document.querySelector('#canvas_container'); |
|
|
|
|
|
RENDERING_VIEWER_W = canvas_container.offsetWidth; |
|
INIT_ZOOM = RENDERING_VIEWER_W / ((TERRAIN_LENGTH + INITIAL_TERRAIN_STARTPAD) * 1.05 * TERRAIN_STEP * SCALE); |
|
THUMBNAIL_ZOOM = RENDERING_VIEWER_W / ((TERRAIN_LENGTH + INITIAL_TERRAIN_STARTPAD) * 0.99 * TERRAIN_STEP * SCALE); |
|
|
|
|
|
resizeCanvas(RENDERING_VIEWER_W, RENDERING_VIEWER_H); |
|
drawing_canvas.resizeCanvas(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); |
|
trace_canvas.resizeCanvas(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); |
|
forbidden_canvas.resizeCanvas(RENDERING_VIEWER_W + SCROLL_X_MAX, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); |
|
|
|
|
|
if(is_drawing()){ |
|
window.refresh_drawing(); |
|
window.game.env.render(); |
|
image(drawing_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
image(forbidden_canvas, 0, -SCROLL_Y_MAX + window.game.env.scroll[1]); |
|
} |
|
|
|
else{ |
|
window.init_default(); |
|
} |
|
} |
|
|
|
window.downloadObjectAsJson = (exportObj, exportName) => { |
|
let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj)); |
|
let downloadAnchorNode = document.createElement('a'); |
|
downloadAnchorNode.setAttribute("href", dataStr); |
|
downloadAnchorNode.setAttribute("download", exportName + ".json"); |
|
document.body.appendChild(downloadAnchorNode); |
|
downloadAnchorNode.click(); |
|
downloadAnchorNode.remove(); |
|
} |
|
|
|
window.strUcFirst = (a) => { |
|
return (a+'').charAt(0).toUpperCase()+a.substr(1); |
|
} |
|
|
|
window.draw_forbidden_area = () => { |
|
forbidden_canvas.clear(); |
|
forbidden_canvas.stroke("#FF0000"); |
|
forbidden_canvas.strokeWeight(3); |
|
forbidden_canvas.fill(255, 50, 0, 75); |
|
let w = convertPosEnvToCanvas((INITIAL_TERRAIN_STARTPAD - 1) * TERRAIN_STEP, 0).x; |
|
forbidden_canvas.rect(0, 0, w, RENDERING_VIEWER_H + 2 * SCROLL_Y_MAX); |
|
} |
|
|