I've been learning Processing for the last week or two, and I've made a couple of little 'desktop toy' type apps like this one that I'm quite pleased with. However, it just occurred to me today to look at the activity monitor while my app was running, and I was unpleasantly surprised – nobody wants a desktop toy that's consuming more resources than anything else on the system.
So far throughout my coding education/experience I've been told not to worry about optimisation 'yet', and haven't really been offered much guidance re: efficient coding (faculty are mainly interested in code that's easy to mark).
Here's what the app is presenting to the user:
Versus the resources it's consuming:
The source is in two parts: the main .pde and another containing the 'Gua' (hexagram) class.
yijingClock.pde
PGraphics mins;
PGraphics hrs;
float fadeAmount;
static final float fadeMax = 1440; //1440 means 1 step per frame takes 1 minute at 24fps
void setup() {
size(500, 500);
colorMode(RGB, 255, 255, 255, fadeMax);
background(255);
imageMode(CENTER); // All images in the sketch are drawn CENTER-wise
frameRate(24); // Affects the smoothness and speed of fade();
mins = createGraphics(width, height);
hrs = createGraphics(width, height);
noFill();
stroke(100);
//polygon(5, width/2, height/2, width / 4 * 3, height / 4 * 3, -PI / 2); // Draw a static pentagon as the background
fill(0);
fadeAmount = 0;
} // end setup()
void draw() {
//let's fade instead of redrawing the background to expose change over time
fadeAmount = map(System.currentTimeMillis() % 60000, 0, 60000, 1, fadeMax); // new way explicitly ties the fade amount to the real current second
//println(fadeAmount);
fade(fadeAmount);
drawMins();
drawHrs();
}// end draw()
void drawMins() {
Gua gua = new Gua(minute());
mins = gua.drawGua(color(0, 0, 0, constrain(fadeAmount*2, 100, fadeMax)));
image(mins, width/2.0, height/2.0, width/2.5, height/2.5);
}// end drawMins()
void drawHrs() {
float angle = TWO_PI / 5; // To arrange them in a pentagon
float startAngle = -PI / 2; // To put the first point at the top
String binHr = binary(hour(), 5); // Use modulo 12 if we want 12 hour time, but that's a waste of bits imo
char[] binHrArr = reverse(binHr.toCharArray()); // We're reversing this to match the endianness of the yijing, and the arrangement of a clock.
hrs = createGraphics(width, height); // Clearing the previous state
hrs.beginDraw();
hrs.clear(); // Trying to make the background transparent so we can layer things
hrs.imageMode(CENTER);
for (int i = 4; i >= 0; i--) {
PGraphics bit = hourBit(binHrArr[i]);
hrs.image(bit, width/2 + (width/2.1) * cos(startAngle + angle * i),
height/2 + (height/2.1) * sin(startAngle + angle * i),
25, 25);
} // end for
hrs.endDraw();
image(hrs, width/2, height/2, (width/4)*3, (height/4)*3);
}// end drawHrs()
// Returns a full circle for true and a hollow one for false
PGraphics hourBit(char state) {
PGraphics bit = createGraphics(40, 40);
bit.beginDraw(); // Start drawing to this buffer...
bit.imageMode(CENTER);
//bit.clear();
bit.stroke(0);
// Fill colour based on state, 1 = filled.
if (state == '1') {
bit.fill(0, fadeAmount); // They fade in
} else {
bit.fill(255);
} // end if
bit.ellipse(20, 20, 30, 30);
bit.endDraw();
return bit;
} // end hourBit()
/**
Copypasted from https://processing.org/tutorials/anatomy/
Originally i was drawing a pentagon but mainly i just needed to learn
how to get the coordinates of the points.
**/
void polygon(int n, float cx, float cy, float w, float h, float startAngle) {
float angle = TWO_PI/ n;
// The horizontal "radius" is one half the width,
// the vertical "radius" is one half the height
w = w / 2.0;
h = h / 2.0;
beginShape();
for (int i = 0; i < n; i++) {
vertex(cx + w * cos(startAngle + angle * i),
cy + h * sin(startAngle + angle * i));
}
endShape(CLOSE);
}
/**
Draws a semitransparent background, which fades everything on
screen by a given amount
**/
void fade(float amount) {
fill(255, amount); // hardcoding bc 1. im lazy, and 2. this sketch should always be b/w
rectMode(CENTER);
rect(width/2, height/2, width, height);
}// end fade
Gua.pde
class Gua {
int[] yao = new int[6];
PImage img;
int intValue = 0; // Used to cast the binary to base 10 to represent the hexagram that way
static final int height = 300; // Need a good alternative to using these constants here...
static final int width = 300;
static final int lineHeight = height / 12; // the height of a line; voids are equal height to lines
static final int segmentSize = width / 5; // Used to determine the ratio of line to white in yin line; must be an odd number to allow middle to be empty
private int x = 0; // remember that (0,0) is the top left corner. Not using x really.
private int y = 0; // Used when moving down the hexagram while drawing it
/**
Default constructor instantiates a random hexagram. This hexagram exists in the memory,
and must be drawn to the canvas in a seperate operation.
**/
Gua() {
for (int i = 0; i < 6; i++) {
yao[i] = round(random(0, 1));
//print(yao[i]);
}
//println();
} // end Gua()
// Construct a hexagram with a given (base 10) value.
Gua(int value) {
String binary = binary(value, 6);
//println("parsed binary: " + binary);
for (int i = 0; i < binary.length(); i++) {
yao[i] = Character.getNumericValue(binary.charAt(i));
//print(yao[i]);
}
//println();
} // end Gua(int)
// Convenience version comes in black
PGraphics drawGua() {
return drawGua(color(0,0,0));
} // end drawGua()
/** Draw a gua of a given colour **/
PGraphics drawGua(color col) {
PGraphics pg = createGraphics(width, height); // the image buffer we will return
pg.beginDraw();
//pg.clear();
pg.noStroke();
pg.fill(col);
//pg.background(255, alpha(col));
int i = 5; // we have to read them backwards because tradition places the "smallest bit" at the top
for (y = 0; y <= 250; y = y + 50) {
if (yao[i] == 0) { // yin
pg.rect(x, y, (segmentSize * 2), lineHeight); // left side
pg.rect(segmentSize * 3, y, (segmentSize * 2), lineHeight); // right side
//println("-- --");
} // end if
else { // yang
pg.rect(x, y, width, lineHeight);
//println("-----");
} // end else
i--;
} //end for
pg.endDraw();
return pg;
}// end drawGua(colour)
String toString() {
return join(str(yao), "");
}// end toString()
int toInt() {
return unbinary(toString());
}// end toInt()
} // End Gua
I probably don't need to point out that I'm a total beginner, so please, even the most obvious optimisation tips would be appreciated. If the answer is that I've written everything totally wrong and should start over, honestly that would be even better, as I feel I need to start developing good habits ASAP.