/** * Food Triad * *

Elie Zananiri
* silentlyCrashing::net
* Feb 2010

*

Drag the points to set the corresponding parameter.
* Press 's' to save a new entry.

*/ static final int TASTE = 0; static final int HEALTH = 1; static final int COST = 2; static final String[] LABELS = { "taste", "health", "cost" }; static final int[] ANGLES = { 270, 150, 30 }; int centerX; int centerY; PFont font; Param[] params; Param selected; float[][] history; int currEntry; int lastEntry; void setup() { size(400, 400, P3D); noStroke(); font = createFont("alex.ttf", 36); textFont(font, 20); textAlign(CENTER, CENTER); centerX = width/2; centerY = height/2 + 35; // set up parameters params = new Param[3]; params[TASTE] = new Param(ANGLES[TASTE], 0xFFDB1818); params[HEALTH] = new Param(ANGLES[HEALTH], 0xFF4F6401); params[COST] = new Param(ANGLES[COST], 0xFFFAE11E); selected = null; reload(); } void draw() { background(255); // update the offset for the selected parameter, if any if (selected != null) { selected.off = min(max(Param.MIN, dist(centerX, centerY, mouseX, mouseY)), Param.MAX); selected.update(); saveEntry(); } // draw the text labels smooth(); fill(0); text(LABELS[TASTE], width/2, params[TASTE].y - 20); text(LABELS[HEALTH], params[HEALTH].x, params[HEALTH].y + 20); text(LABELS[COST], params[COST].x, params[COST].y + 20); // draw the parameter handles noSmooth(); for (int i=0; i < params.length; i++) { params[i].draw(); } smooth(); beginShape(TRIANGLES); { // draw the current polygon for (int i=0; i < params.length; i++) { fill(params[i].col, map(params[i].off, Param.MIN, Param.MAX, 10, 255)); vertex(params[i].x, params[i].y); } } endShape(); noFill(); beginShape(TRIANGLES); { // draw the old polygons for (int j=0; j < currEntry; j++) { stroke(0, (j+1)/(currEntry*1.f) * 255); for (int i=0; i < history[j].length; i++) { vertex(calcX(history[j][i], radians(ANGLES[i])), calcY(history[j][i], radians(ANGLES[i]))); } } } endShape(); noStroke(); } void saveEntry() { history[lastEntry][TASTE] = params[TASTE].off; history[lastEntry][HEALTH] = params[HEALTH].off; history[lastEntry][COST] = params[COST].off; } void reload() { String lines[] = loadStrings("entries.txt"); history = new float[lines.length+1][3]; lastEntry = currEntry = lines.length; for (int i=0; i < lines.length; i++) { String[] vals = split(lines[i], ","); history[i][TASTE] = float(vals[TASTE]); history[i][HEALTH] = float(vals[HEALTH]); history[i][COST] = float(vals[COST]); } saveEntry(); } void saveAllAndReload() { String[] data = new String[history.length]; for (int i=0; i < data.length; i++) { data[i] = history[i][TASTE] + "," + history[i][HEALTH] + "," + history[i][COST]; } saveStrings("data/entries.txt", data); reload(); } void mousePressed() { for (int i=0; i < params.length; i++) { if (params[i].contains(mouseX, mouseY)) { currEntry = lastEntry; selected = params[i]; } } } void mouseReleased() { selected = null; } void keyPressed() { if (key == CODED) { if (keyCode == LEFT) { if (currEntry > 0) { currEntry--; for (int i=0; i < params.length; i++) { params[i].tweenTo(history[currEntry][i]); } } } else if (keyCode == RIGHT) { if (currEntry < lastEntry) { currEntry++; for (int i=0; i < params.length; i++) { params[i].tweenTo(history[currEntry][i]); } } } } else if (key == 's') { saveAllAndReload(); } } float calcX(float _off, float _ang) { return (centerX + _off * cos(_ang)); } float calcY(float _off, float _ang) { return (centerY + _off * sin(_ang)); }