Created
July 3, 2025 20:47
-
-
Save MateusAquino/fc1f5df74a9e0c15a79aa7213a340d98 to your computer and use it in GitHub Desktop.
OpenDrop - Bad Apple!!
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 characters
| 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(); | |
| } |
This file has been truncated, but you can view the full file.
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 characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment