/** * Dynamic tracking with a delay. An illustration of how increasing delays * make control difficult. * *

Try to keep the red ball inside the blue target, using the mouse. * *

The red ball has momentum and is subject to drag. It is, in effect, * coupled to your mouse location by a spring, subject to a pipeline delay. * *

Initially the task is fairly easy. Use the keyboard * to increase complexity of the task by changing the dynamics of the * ball ( b and m), allowing the target to drift (t), and adding a delay between the * mouse and ball control (d). You can toggle display of your delayed * mouse location (s). You may need to click in the window to give * it focus before the controls work. * *

Get a feel for it, then crank the delay and drift up to 5 * and see how you fare. * *

Draws on Processing's easing, keyboard and arraylist examples. * *

Tom Fiddaman, Ventana Systems, 2009 */ float x=0; float y=0; float vx=0; float vy=0; float m=1; float k=.05; float b=1; float g = .1; float targetX, targetY; float easing = 1; color target = color(60,60,180); color ball = color(200,30,30); ArrayList mouseLocs; int delaySize=1; int wsize = 400; float tx = wsize/2; float ty = wsize/2; float tdx =0; float tdy=0; int drift = 0; // target drift rate float recenter = .05; // target recentering rate float drag = .2; // target damping PFont fontA; TextControl delayBar; TextControl driftBar; TextControl showBar; TextControl massBar; TextControl dragBar; void setup() { size(400, 400); // needs to be a # for export to size properly smooth(); noStroke(); mouseLocs = new ArrayList(); for(int i=0;i Create Font // to create a distributable bitmap font. // For vector fonts, use the createFont() function. fontA = loadFont("Tahoma-Bold-9.vlw"); // Set the font and its size (in units of pixels) textFont(fontA, 9); delayBar = new TextControl("d delay","d","_",10,0); driftBar = new TextControl("t target drift","t","_",5,0); showBar = new TextControl("s show delay","s","_",1,0); dragBar = new TextControl("b drag","b","_",2,1); massBar = new TextControl("m mass","m","_",2,2); frameRate(30); } void draw() { background( 51 ); // controls fill(200); text(delayBar.textBar(),4,10); text(driftBar.textBar(),4,22); text(showBar.textBar(),4,34); text(dragBar.textBar(),4,46); text(massBar.textBar(),4,58); // settings delaySize = 1+delayBar.setting*5; drift = driftBar.setting; m = .1+massBar.setting/2; b = .1+dragBar.setting/2; // target tdx = tdx+(random(drift)-drift/2)-drag*tdx; tdy = tdy+(random(drift)-drift/2)-drag*tdy; tx = tx + recenter*(wsize/2-tx) + tdx; ty = ty + recenter*(wsize/2-ty) + tdy; fill(target); noStroke(); ellipse(tx,ty,33,33); // ball targetX = mouseX; targetY = mouseY; mouseLocs.add(new Location(targetX,targetY)); while (mouseLocs.size() > delaySize) { mouseLocs.remove(0); } Location xy = (Location)mouseLocs.get(0); float dx = xy.x-x; float dy = xy.y-y; if (showBar.setting == 1) { stroke(ball); noFill(); ellipse(xy.x, xy.y, 16, 16); } /* float r2 = pow((x-wsize/2),2)+pow((y-wsize/2),2); float rx = (x-wsize/2); float ry = (y-wsize/2); */ vx = vx+k*dx/m-b*m*vx; vy = vy+k*dy/m-b*m*vy; x += vx * easing; y += vy * easing; fill(ball); ellipse(x, y, 16, 16); } void keyReleased() { delayBar.increment(key); driftBar.increment(key); showBar.increment(key); dragBar.increment(key); massBar.increment(key); }