import javax.swing.event.EventListenerList; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; // TODO: Loads of threads in this class, make sure everything is thread safe. public class PunchingBag implements Runnable { private byte[] rawLeds = new byte[6 * 8]; private Colour[][] leds = new Colour[9][20]; private byte[] ledGridIntensities = new byte[6]; private boolean[][] buttons = new boolean[8][19]; private ArrayList runningEffects = new ArrayList(); enum Colour { None, Red, Yellow, Green }; private EventListenerList buttonListenerList = new EventListenerList(); private EventListenerList ledListenerList = new EventListenerList(); public PunchingBag() { new Thread(this).start(); } /** * Adds an ActionListener to the button. * * @param l * the ActionListener to be added */ public void addButtonListener(ButtonListener l) { buttonListenerList.add(ButtonListener.class, l); } public void addLEDChangeListener(LEDListener l) { ledListenerList.add(LEDListener.class, l); } public void setLED(int i, int j, Colour colour) { leds[i][j] = colour; } void CircleExpand(int x, int y, int delay, Colour colour) { // TODO: Adam correct CircleExpand constructor, or this method? //runningEffects.add(new CircleExpand(x,y,delay,colour)); } class Effect implements Runnable { boolean stop = false; int refreshRate = 60; // Times per second to refresh public void stop() { stop = true; } public void run() { while (!stop) { draw(); try { Thread.sleep(1000 / 60); } catch (InterruptedException e) { e.printStackTrace(); } } runningEffects.remove(this); } private void draw() { } } class CircleExpand extends Effect { double currentWidth; final byte x; final byte y; byte intensity; boolean drawnSomething = true; public CircleExpand(byte x, byte y, byte intensity) { this.x = x; this.y = y; this.intensity = intensity; new Thread(this).start(); } public void draw() { Colour colour; if (intensity >= 10) { colour = Colour.Red; } else if (intensity >= 5) { colour = Colour.Yellow; } else { colour = Colour.Green; } drawnSomething = false; for (double i = 0; i < 360; i++) { // int x = x + (int) Math.round(currentWidth * Math.cos(i)); // int y = y + (int) Math.round(currentWidth * Math.sin(i)); if (x >= 0 && x <= 8 && y >= 0 && y <= 19) { setLED(x, y, colour); drawnSomething = true; } } currentWidth += 0.1 + (currentWidth / 10); if (!drawnSomething) stop = true; } } public void DrawEllipse(int x, int y, int radx, int rady, Colour colour) { if (radx == 0 && rady == 0) { setLED(x, y, colour); return; } int dx = 0, dy = rady; /* first quadrant from top left to bottom right */ int a2 = radx * radx, b2 = rady * rady; int err = b2 - (2 * rady - 1) * a2, e2; /* error value in the first step */ do { setLED(x + dx, y + dy, colour); /* I. Quadrant */ setLED(x - dx, y + dy, colour); /* II. Quadrant */ setLED(x - dx, y - dy, colour); /* III. Quadrant */ setLED(x + dx, y - dy, colour); /* IV. Quadrant */ e2 = 2 * err; if (e2 < (2 * dx + 1) * b2) { dx++; err += (2 * dx + 1) * b2; } if (e2 > -(2 * dy - 1) * a2) { dy--; err -= (2 * dy - 1) * a2; } } while (dy >= 0); while (dx++ < radx) { /* correction for flat ellipses (b=1) */ setLED(x + dx, y, colour); setLED(x - dx, y, colour); } } private void calculateRawLeds() { for (int y = 0; y <= 18; y++) { for (int x = 0; x <= 6; x++) { if ((y % 2) == 0) { if (leds[x][y] == Colour.Green || leds[x][y] == Colour.Yellow) { rawLeds[(int) Math.floor(y / 4)] = (byte) (rawLeds[(int) Math .floor(y / 4)] | (1 << (7 - x))); } } else { if (leds[x][y] == Colour.Red || leds[x][y] == Colour.Yellow) { rawLeds[(int) Math.floor(y / 4)] = (byte) (rawLeds[(int) Math .floor(y / 4)] | (1 << (7 - x))); } } } } int x = 7; // TODO: Complete and test, or rethink the following? for (int startY = 0; startY <= 4; startY++) { for (int y = 0; y <= 3; y++) { if (leds[x][startY + (y * 4)] == Colour.Red || leds[x][startY + (y * 4)] == Colour.Yellow) { rawLeds[(5 * 8) + startY] = (byte) (rawLeds[(int) Math .floor(y / 4)] | (1 << (7 - x))); } if (leds[x][y] == Colour.Green || leds[x][y] == Colour.Yellow) { rawLeds[(int) Math.floor(y / 4)] = (byte) (rawLeds[(int) Math .floor(y / 4)] | (1 << (7 - x))); } } } } /* Clears the led grid and stops all running effects */ public void clearLEDGrid() { for (Iterator iter = runningEffects.iterator(); iter.hasNext(); ) { ((Effect) iter.next()).stop(); } Arrays.fill(leds, Boolean.FALSE); } public void setLEDGridIntensity(byte grid, byte intensity) { ledGridIntensities[grid] = intensity; } public void setLEDIntensities(byte intensity) { Arrays.fill(ledGridIntensities, intensity); } public void run() { } }