#VRML V2.0 utf8 PROTO ScaredCritter [ field SFVec3f position 0 0 0 field SFFloat speed 1 field SFVec3f obstacle 0 0 1 eventIn SFVec3f set_obstacle ] { Group { children [ DEF MOVEME Transform { translation IS position children Shape { appearance Appearance { material DEF MAT Material {} } geometry Box { size .5 .5 .5 } } } DEF HEART TimeSensor { loop TRUE } # update direction and position when receive "heartbeats" DEF SCRIPT Script { eventIn SFTime beat eventIn SFVec3f set_obstacle IS set_obstacle eventIn SFBool touched eventOut SFVec3f position_changed eventOut SFColor color_changed field SFVec3f direction 0 0 1 field SFVec3f position IS position field SFVec3f goal 0 0 0 field SFFloat speed IS speed field SFTime lastBeat 0 field SFVec3f obstacle IS obstacle field SFBool first TRUE field SFFloat repulse 5 field SFFloat attract 1 field SFFloat power 1 field SFInt32 touches 0 field SFBool run TRUE url "vrmlscript: function touched(val) { if(val) { ++touches; color_changed = new SFColor(Math.random(), Math.random(), Math.random()); } if(touches > 2) { if(run) { run = FALSE; } else { run = TRUE; } touches = 0; } } function repulseForce() { v = position.subtract(obstacle); ods = repulse * 1/Math.pow(v.length(), power); return v.normalize().multiply(ods); } function calcDirection() { // compute force of attraction towards goal gforce = goal.subtract(position).normalize().multiply(attract); rforce = repulseForce(); if(!run) { rforce = rforce.multiply(-1); } force = gforce.add(rforce); direction = force.normalize(); } function set_goal(val) { goal = val; // calcDirection(); } function beat(val) { if(first) { // initialize lastBeat on first heartbeat lastBeat = val; first = FALSE; } else { timeElapsed = val - lastBeat; calcDirection(); position = position.add(direction.multiply(speed*timeElapsed)); position_changed = position; lastBeat = val; } } function set_obstacle(val) { obstacle = val; } " } DEF TOUCH TouchSensor {} ] } ROUTE HEART.time TO SCRIPT.beat ROUTE SCRIPT.position_changed TO MOVEME.translation ROUTE TOUCH.isActive TO SCRIPT.touched ROUTE SCRIPT.color_changed TO MAT.diffuseColor }