/** * Shape class by subpixel (http://subpixels.com) *
Last modified: 2009-01-09 10:47
*/ public class Shape { public Vector2D p; // position, in pixels public Vector2D v; // velocity, in pixels per second public Vector2D a; // acceleration in pixels per second per second public boolean showEdge; public boolean showFill; public color edgeColor; public float edgeWeight; public color fillColor; public color bgColor; // background colour (if any) protected Vector2D prev; // previous position protected Vector2D d; // delta (move) since last frame protected boolean wrapped; // did we wrap over an edge when moving this frame? public Shape() { this(new Vector2D()); } public Shape(float x, float y) { this(new Vector2D(x, y)); } public Shape(Vector2D position) { this.p = position; edgeColor = color(255, 255, 255, 255); fillColor = color(127, 127, 127, 255); bgColor = color(63, 63, 63, 127); edgeWeight = 1; showFill = false; showEdge = true; this.prev = new Vector2D(position); this.d = new Vector2D(); wrapped = false; } public String str() { return "Shape{p:" + p.str() + ",v:" + v.str() + ",a:" + a.str() + "}"; } public void useBasicColor() { PGraphics pg = layer[LAYER_DRAW]; if (showFill) pg.fill(fillColor); else pg.noFill(); if (showEdge) { pg.stroke(edgeColor); pg.strokeWeight(edgeWeight); } else { pg.noStroke(); } } public void animTick(int ms) { float frac = ms * 0.001; // fraction of 1 second prev.x = p.x; prev.y = p.y; // Accelerate v.x += frac * a.x; v.y += frac * a.y; //TODO: damping: probably want to precalc the exponent in the caller //v.x *= pow(dampingConstant, frac); //v.y *= pow(dampingConstant, frac); // Move d.x = frac * v.x; d.y = frac * v.y; p.x += d.x; p.y += d.y; // Wrap to screen bounds if (p.x < 0) { wrapped = true; p.x += width; } else if (p.x >= width) { wrapped = true; p.x -= width; } else { wrapped = false; } if (p.y < 0) { wrapped = true; p.y += height; } else if (p.y >= height) { wrapped = true; p.y -= height; } else { wrapped = false; } } public void draw() { trace(); if (showConstructionLines && showConstructionLinesLevel >= 2) { PGraphics cunder = layer[LAYER_CNSTR_UNDER]; cunder.stroke(constructionLinesColor); cunder.strokeWeight(constructionLinesWeight); // Target lines to edge of screen cunder.line(p.x, 0, p.x, height - 1); cunder.line(0, p.y, width - 1, p.y); } } public void trace() { if (showTrace) { PGraphics pg = layer[LAYER_TRACE]; pg.stroke(traceColor); pg.strokeWeight(traceLinesWeight); pg.noFill(); // Draw to current point pg.line(int(p.x - d.x), int(p.y - d.y), int(p.x), int(p.y)); // If we'd wrapped around an edge this frame when moving, draw the // trace from the previous point in the direction of the move // Note: if the shape has wrapped both X and Y boundaries in the same step, // there should be a third trace line that cuts across a corner. Since this // isn't going to happen to often, is tricky to work out and won't leave // a stem of trace line that doesn't reach the edge, don't worry about it. if (wrapped) { // Draw from previous point pg.line(int(prev.x), int(prev.y), int(prev.x + d.x), int(prev.y + d.y)); } } } }