import rwmidi.*; MidiOutput output; static final int X_CELLS = 32; static final int Y_CELLS = 32; static final int CELL_SIZE = 12; // 12 pixels x 12 pixels for each cell boolean cells[][] = new boolean[X_CELLS][Y_CELLS]; int beatsPerSecond = 4; int fps = 0; boolean gameStarted = false; void setup() { size(X_CELLS * CELL_SIZE + 3, Y_CELLS * CELL_SIZE + 3); for (int x = 0; x < X_CELLS; x++) { for (int y = 0; y < Y_CELLS; y++) { cells[x][y] = false; } } MidiOutputDevice devices[] = RWMidi.getOutputDevices(); // for (int i = 0; i < devices.length; i++) { // println(i + ": " + devices[i].getName()); // } output = RWMidi.getOutputDevices()[2].createOutput(); frameRate(25); fps = 0; } void drawCell(int x, int y) { if (cells[x][y]) { fill(255); stroke(0); rect(x * CELL_SIZE + 1, y * CELL_SIZE + 1, CELL_SIZE, CELL_SIZE); } } int cellNeighbors(int x, int y) { int result = 0; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { int newX = x + i; int newY = y + j; // don't count the current cell if (newX == x && newY == y) continue; // check grid boundaries if (newX >= 0 && newY >= 0 && newX < X_CELLS && newY < Y_CELLS) { if (cells[newX][newY]) result++; } } } return result; } void updateGameOfLife() { boolean newCells[][] = new boolean[X_CELLS][Y_CELLS]; for (int x = 0; x < X_CELLS; x++) { for (int y = 0; y < Y_CELLS; y++) { int neighbors = cellNeighbors(x, y); newCells[x][y] = cells[x][y]; if (neighbors < 2) { newCells[x][y] = false; notoutputCell(x, y); } else if (neighbors > 3) { newCells[x][y] = false; notoutputCell(x, y); } else if (neighbors == 3 && !cells[x][y]) { newCells[x][y] = true; outputCell(x, y); } } } cells = newCells; } int scale[] = new int[] { 0, 2, 3, 5, 7, 8, 10, 12 }; int pitchValue(int x, int y) { return scale[cellValue(x, y)] + (x + y) % 3 * 12 + 40; } void outputCell(int x, int y) { output.sendNoteOn(0, pitchValue(x, y), 100); } void notoutputCell(int x, int y) { output.sendNoteOff(0, pitchValue(x, y), 100); } static final int NUM_VALUES = 8; int valueColors[] = new int[] { color(0, 255, 0), color(255, 0, 0), color(0, 0, 255), color(255, 255, 0), color(0, 255, 255), color(255, 0, 255), color(255), color(127) }; int cellValue(int x, int y) { return (x + y) % NUM_VALUES; } void beat() { updateGameOfLife(); } int curCellX = -1; int curCellY = -1; boolean curDrawMode = false; void keyPressed() { if (key == ' ') { gameStarted = !gameStarted; } } void draw() { if (gameStarted) { fps++; if (fps > (frameRate / beatsPerSecond)) { beat(); fps = 0; } } background(0); fill(0); stroke(255); rect(0, 0, CELL_SIZE * X_CELLS + 2, CELL_SIZE * Y_CELLS + 2); if (mousePressed) { int x = floor((float)(mouseX - 1) / (float)CELL_SIZE); int y = floor((float)(mouseY - 1) / (float)CELL_SIZE); if (x < X_CELLS && y < Y_CELLS) { if (curCellX != x || curCellY != y) { if (curCellX == -1) { if (cells[x][y]) { curDrawMode = false; } else { curDrawMode = true; } } cells[x][y] = curDrawMode; curCellX = x; curCellY = y; } } } else { curCellX = -1; curCellY = -1; } for (int x = 0; x < X_CELLS; x++) { for (int y = 0; y < Y_CELLS; y++) { // draw square value color c = valueColors[cellValue(x, y)]; fill(c); stroke(c); rect(x * CELL_SIZE + 1 + CELL_SIZE / 2, y * CELL_SIZE + 1 + CELL_SIZE / 2, 1, 1); drawCell(x, y); } } }