Created
July 3, 2025 20:47
-
-
Save MateusAquino/fc1f5df74a9e0c15a79aa7213a340d98 to your computer and use it in GitHub Desktop.
Revisions
-
MateusAquino created this gist
Jul 3, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,155 @@ import processing.serial.*; import static javax.swing.JOptionPane.*; import java.nio.file.*; import processing.data.JSONArray; import processing.data.JSONObject; Serial myPort; // Configurable params final int frameInterval = 33; // ~30 fps | NOTE: lower is faster final boolean WARN_RESERVOIR = true; final boolean UI_MODE = true; // Grid dimensions final int GRID_WIDTH = 14; final int GRID_HEIGHT = 8; final int WINDOW_WIDTH = 700; final int WINDOW_HEIGHT = 400; // Electrode & locked‑block state boolean[][] electrodes = new boolean[GRID_WIDTH][GRID_HEIGHT]; // State ArrayList<boolean[][]> frames; int currentFrame = 0; int lastFrameTime = 0; void setup() { noLoop(); // pause draw while we init serial + UI // —— serial init —— String[] ports = Serial.list(); if (ports == null || ports.length == 0) { showMessageDialog(null, "No serial ports found. Connect your device and retry.", "Serial Port Error", ERROR_MESSAGE); exit(); } myPort = new Serial(this, ports[0], 115200); delay(100); // —— initial board fill —— initialTransmit(); if (WARN_RESERVOIR) showMessageDialog(null, "This is an inverted grid. Fill the board (except the reservoir) with liquid *now*, then press OK.", "Initial setup", 2); // —— game init —— if (UI_MODE) windowResize(WINDOW_WIDTH, WINDOW_HEIGHT); frameRate(60); setupFrames(); loop(); } void setupFrames() { for (int x = 0; x < GRID_WIDTH; x++) for (int y = 0; y < GRID_HEIGHT; y++) electrodes[x][y] = true; transmit(); loadFrames(); } void loadFrames() { JSONArray raw = loadJSONArray("bad_apple_14x8.json"); frames = new ArrayList<boolean[][]>(); for (int f = 0; f < raw.size(); f++) { JSONArray frame = raw.getJSONArray(f); boolean[][] buf = new boolean[GRID_WIDTH][GRID_HEIGHT]; for (int y = 0; y < GRID_HEIGHT; y++) { JSONArray row = frame.getJSONArray(y); for (int x = 0; x < GRID_WIDTH; x++) { buf[x][y] = row.getInt(x) == 1; } } frames.add(buf); } } void draw() { // drop piece if (millis() - lastFrameTime > frameInterval) { lastFrameTime = millis(); displayFrame(frames.get(currentFrame)); currentFrame = (currentFrame + 1) % frames.size(); transmit(); } if (UI_MODE) renderGrid(); } void initialTransmit() { // fill all electrodes on for (int x = 0; x < GRID_WIDTH; x++) for (int y = 0; y < GRID_HEIGHT; y++) electrodes[x][y] = true; byte[] packet = new byte[32]; packet[0] = 0; for (int x = 0; x < GRID_WIDTH; x++) { int b = 0; for (int y = 0; y < GRID_HEIGHT; y++) if (electrodes[x][y]) b |= 1<<y; packet[x+1] = (byte)b; } packet[GRID_WIDTH+1] = 0; for (byte pb : packet) myPort.write(pb); } void transmit() { byte[] packet = new byte[32]; packet[0] = (byte)0xFF; for (int x = 0; x < GRID_WIDTH; x++) { int b = 0; for (int y = 0; y < GRID_HEIGHT; y++) if (electrodes[x][y]) b |= 1<<y; packet[x+1] = (byte)b; } packet[GRID_WIDTH+1] = (byte)0xFF; for (byte pb : packet) myPort.write(pb); } void renderGrid() { int cellW = width / GRID_WIDTH; int cellH = height / GRID_HEIGHT; stroke(80); for (int x = 0; x < GRID_WIDTH; x++) { for (int y = 0; y < GRID_HEIGHT; y++) { fill(electrodes[x][y] ? color(0,200,0) : 50); rect(x*cellW, y*cellH, cellW-2, cellH-2); } } } void displayFrame(boolean[][] f) { // copy into electrodes for (int x = 0; x < GRID_WIDTH; x++) for (int y = 0; y < GRID_HEIGHT; y++) electrodes[x][y] = f[x][y]; } void dispose() { // clear electrodes on exit if (myPort != null) { byte[] clear = new byte[32]; for (byte b: clear) myPort.write(b); delay(50); myPort.stop(); } super.dispose(); }