import SpringGUI.*; // This code has been ported back and forth many times and contains so much goo and so many hacks it's not even funny. // Stop shaking your head already! :) SpringGUI gui; // all final int sHeight = 150; final int sWidth = 150; final int zoom = 2; // LiquidCell float DECAY = 0.48f; float SPREAD = 0.101f; float ENERGYTHRESHOLD = 0.35f; // threshold zur Bildung einer neuen Zelle float SPAWNCONSUME = 0.1f; // Energiekonsum bei Bildung // Zelltod float DEATHVALUE = 0.0002f; // Schwelle bei der die Zelle stirbt float NUTRIENTVALUE = 0.48f; // Erhöhung des N-Wertes bei Zelltod float CONNECTIVE_TENDENCY = 2f; // Rate der Energie die eine Zelle abgibt. float ENERGYDEPLETE = 0.48f; // Wieviel Energie des Kästchens verbraucht sie? boolean SHARE = false; float LOWERTHRESHOLD = 0.0005f; boolean ISTHRESHOLD = false; float ANTIALIASING = 0.3f; // LiquidMatrix float SPILLAMOUNT = 1; // LifeCell // Zellbildung float TURNTHRESHOLD = 25f; // threshold zur Bildung einer neuen Zelle // Energieleitung durch Zellen float ENERGYCONSUME = 1f; // Wieviel Energie kann die Zelle aufnehmen? LifeMatrix lifeMat; LiquidMatrix liquidMat; int[] sPixels; boolean spilling; int xM, yM; boolean displayCells; boolean displayLiquid; final int baseCol = 0xFF000000 | 24<<16 | 48 << 8 | 64; void setup() { size(sWidth*zoom,sHeight*zoom+305, P3D); PFont font = loadFont("AllstarsSquareCompressed-13.vlw"); textFont(font); gui = new SpringGUI(this); lifeMat = new LifeMatrix(); liquidMat = new LiquidMatrix(); lifeMat.liquid = liquidMat; liquidMat.life = lifeMat; spilling = false; displayCells = true; displayLiquid = true; background(222,236,247); fill(0,0,0); int offset = 55; text("preset", 15, 317); gui.addChoice("preset", 10, 320, 135, 25); gui.addItem("preset", "Standard"); gui.addItem("preset", "Crashing Waves"); gui.addItem("preset", "Pond / Flower"); gui.addItem("preset", "Instability"); gui.addItem("preset", "Plasma"); gui.addItem("preset", "Fingerprint"); gui.addItem("preset", "Thunderstorm"); gui.addItem("preset", "Electric Ave"); gui.addItem("preset", "Cells"); gui.addItem("preset", "Step-Dance"); gui.addItem("preset", "Macro"); gui.addItem("preset", "Sunburn"); gui.addItem("preset", "Cabbage"); gui.addItem("preset", "Cyclic 2"); gui.addItem("preset", "Strange Blinker"); gui.addItem("preset", "Erosion"); gui.addItem("preset", "haXX0r01"); gui.addItem("preset", "haXX0r02"); gui.selectItem("preset", "Standard"); gui.setSize("preset", 135, 25); text("display", 160, 317); gui.addChoice("display", 155, 320, 135, 25); gui.addItem("display", "all"); gui.addItem("display", "only liquid"); gui.addItem("display", "only cells"); gui.selectItem("display", "all"); gui.setSize("display", 135, 25); text("Liquid: Decay", 15, 317+offset); gui.addTextField("decay", "", 10, 320+offset, 135, 25); text("Liquid: Spread", 160, 317+offset); gui.addTextField("spread", "", 155, 320+offset, 135, 25); text("Cellspawn: Threshold", 15, 362+offset); gui.addTextField("csThreshold", "", 10, 365+offset, 135, 25); text("Cellspawn: Cost", 160, 362+offset); gui.addTextField("cost", "", 155, 365+offset, 135, 25); text("Cell-Death: Threshold", 15, 407+offset); gui.addTextField("cdThreshold", "", 10, 410+offset, 135, 25); text("Cell-Death: Liquification", 160, 407+offset); gui.addTextField("liquification", "", 155, 410+offset, 135, 25); text("Connective Tendency", 15, 452+offset); gui.addTextField("connective", "", 10, 455+offset, 135, 25); text("Liquid Depletion", 160, 452+offset); gui.addTextField("depletion", "", 155, 455+offset, 135, 25); gui.addCheckbox("share", "cells share energy", 10, 485+offset, 200, 25); gui.addButton("clear", "Clear Screen", 10, 520+offset, 135, 25); gui.addButton("accept", "Apply changes!", 155, 520+offset, 135, 25); gui.setAllBackgrounds(222,214,227); gui.setBackground("share", 222,236,247); gui.setText("decay", "0.48"); gui.setText("spread", "0.101"); gui.setText("csThreshold", "0.35"); gui.setText("cost", "0.1"); gui.setText("cdThreshold", "0.0002"); gui.setText("liquification", "0.48"); gui.setText("connective", "2"); gui.setText("depletion", "0.48"); gui.setState("share", false); } void handleEvent(String[] parameters) { // --------------------------------------------------- // Clear Button if ( parameters[1].equals("clear") && parameters[2].equals("mouseClicked") ) { liquidMat.reset(); lifeMat.reset(); } // --------------------------------------------------- // change display if ( parameters[1].equals("display") && parameters[2].equals("selected") ) { String dis = gui.getSelectedItem("display"); if (dis.equals("all")) { displayCells = true; displayLiquid = true; } else if (dis.equals("only liquid")) { displayCells = false; displayLiquid = true; } else if (dis.equals("only cells")) { displayCells = true; displayLiquid = false; } } // --------------------------------------------------- // param preset if ( parameters[1].equals("preset") && parameters[2].equals("selected") ) { String selected = gui.getSelectedItem("preset"); if (selected.equals("Standard")) { gui.setText("decay", "0.48"); gui.setText("spread", "0.101"); gui.setText("csThreshold", "0.35"); gui.setText("cost", "0.1"); gui.setText("cdThreshold", "0.0002"); gui.setText("liquification", "0.48"); gui.setText("connective", "2"); gui.setText("depletion", "0.48"); gui.setState("share", false); } else if (selected.equals("Crashing Waves")) { gui.setText("decay", "0"); gui.setText("spread", "0.198"); gui.setText("csThreshold", "0.3"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.00001"); gui.setText("liquification", "0.05"); gui.setText("connective", "0.5"); gui.setText("depletion", "0.05"); gui.setState("share", false); } else if (selected.equals("Pond / Flower")) { gui.setText("decay", "0.9"); gui.setText("spread", "0.03"); gui.setText("csThreshold", "0.2"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.0002"); gui.setText("liquification", "0"); gui.setText("connective", "30000"); gui.setText("depletion", "0"); gui.setState("share", false); } else if (selected.equals("Plasma")) { gui.setText("decay", "0.9"); gui.setText("spread", "0.025"); gui.setText("csThreshold", "0.5"); gui.setText("cost", "0"); gui.setText("cdThreshold", "1e-30"); gui.setText("liquification", "0"); gui.setText("connective", "900000"); gui.setText("depletion", "0.2"); gui.setState("share", false); } else if (selected.equals("Fingerprint")) { gui.setText("decay", "0.55"); gui.setText("spread", "0.09"); gui.setText("csThreshold", "0.1"); gui.setText("cost", "0.2"); gui.setText("cdThreshold", "0.1"); gui.setText("liquification", "0.2"); gui.setText("connective", "40"); gui.setText("depletion", "0.2"); gui.setState("share", false); } else if (selected.equals("Thunderstorm")) { gui.setText("decay", "0.48"); gui.setText("spread", "0.11"); gui.setText("csThreshold", "0.35"); gui.setText("cost", "0.05"); gui.setText("cdThreshold", "0.0002"); gui.setText("liquification", "0.2"); gui.setText("connective", "15"); gui.setText("depletion", "0.6"); gui.setState("share", false); } else if (selected.equals("Cells")) { gui.setText("decay", "0.8"); gui.setText("spread", "0.04"); gui.setText("csThreshold", "0.3"); gui.setText("cost", "0.5"); gui.setText("cdThreshold", "0.000001"); gui.setText("liquification", "0.1"); gui.setText("connective", "1"); gui.setText("depletion", "0"); gui.setState("share", false); } else if (selected.equals("Macro")) { gui.setText("decay", "0.58"); gui.setText("spread", "0.081"); gui.setText("csThreshold", "0.1"); gui.setText("cost", "1"); gui.setText("cdThreshold", "0.1"); gui.setText("liquification", "0.02"); gui.setText("connective", "1000"); gui.setText("depletion", "0.5"); gui.setState("share", false); } else if (selected.equals("Sunburn")) { gui.setText("decay", "0.6"); gui.setText("spread", "0.1"); gui.setText("csThreshold", "1e-30"); gui.setText("cost", "1"); gui.setText("cdThreshold", "0.1"); gui.setText("liquification", "0"); gui.setText("connective", "1"); gui.setText("depletion", "0"); gui.setState("share", false); } else if (selected.equals("Cyclic 2")) { gui.setText("decay", "0.6"); gui.setText("spread", "0.08"); gui.setText("csThreshold", "0.3"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.2"); gui.setText("liquification", "0"); gui.setText("connective", "5"); gui.setText("depletion", "0"); gui.setState("share", false); } else if (selected.equals("Strange Blinker")) { gui.setText("decay", "0.59"); gui.setText("spread", "0.081"); gui.setText("csThreshold", "0.001"); gui.setText("cost", "1"); gui.setText("cdThreshold", "0.1"); gui.setText("liquification", "0.02"); gui.setText("connective", "1000"); gui.setText("depletion", "0"); gui.setState("share", false); } else if (selected.equals("Erosion")) { gui.setText("decay", "0.9"); gui.setText("spread", "0.02"); gui.setText("csThreshold", "0.15"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.00002"); gui.setText("liquification", "0.05"); gui.setText("connective", "10"); gui.setText("depletion", "0"); gui.setState("share", false); } else if (selected.equals("Instability")) { gui.setText("decay", "0"); gui.setText("spread", "0.198"); gui.setText("csThreshold", "0.25"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.0001"); gui.setText("liquification", "0.03"); gui.setText("connective", "0.18"); gui.setText("depletion", "0.05"); gui.setState("share", true); } else if (selected.equals("Electric Ave")) { gui.setText("decay", "0"); gui.setText("spread", "0.2"); gui.setText("csThreshold", "0.15"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.8"); gui.setText("liquification", "0.1"); gui.setText("connective", "4"); gui.setText("depletion", "0"); gui.setState("share", true); } else if (selected.equals("Step-Dance")) { gui.setText("decay", "0.85"); gui.setText("spread", "0.023"); gui.setText("csThreshold", "0.2"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.000001"); gui.setText("liquification", "90"); gui.setText("connective", "-1"); gui.setText("depletion", "0"); gui.setState("share", true); } else if (selected.equals("Cabbage")) { gui.setText("decay", "0.85"); gui.setText("spread", "0.024"); gui.setText("csThreshold", "0.1"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.3"); gui.setText("liquification", "1000"); gui.setText("connective", "0.1"); gui.setText("depletion", "0"); gui.setState("share", true); } else if (selected.equals("haXX0r01")) { gui.setText("decay", "-0.1"); gui.setText("spread", "0.26"); gui.setText("csThreshold", "-0.1"); gui.setText("cost", "0"); gui.setText("cdThreshold", "0.6"); gui.setText("liquification", "-1"); gui.setText("connective", "-1"); gui.setText("depletion", "0"); gui.setState("share", false); } else if (selected.equals("haXX0r02")) { gui.setText("decay", "0.9"); gui.setText("spread", "0.025"); gui.setText("csThreshold", "0.5"); gui.setText("cost", "-1"); gui.setText("cdThreshold", "1e-30"); gui.setText("liquification", "0"); gui.setText("connective", "-1"); gui.setText("depletion", "-0.2"); gui.setState("share", true); } applyChanges(); } // --------------------------------------------------- // apply changes if ( parameters[1].equals("accept") && parameters[2].equals("mouseClicked") ) { applyChanges(); } // --------------------------------------------------- // correct TextField input on key press if (parameters[0].equals("TextField") && ( parameters[2].equals("textChanged") ) ) { // || parameters[2].equals("keyTyped") ) ) { String txt = gui.getText(parameters[1]); boolean change = false; for (int i=0; i57)) { // invalid char txt = txt.substring(0,i)+txt.substring(i+1, txt.length()); i--; change = true; } } int j; j = txt.indexOf("."); // only one point if (j!=-1) { while (txt.indexOf(".", j+1)!=-1) { int k = txt.indexOf(".", j+1); txt = txt.substring(0,k)+txt.substring(k+1, txt.length()); change = true; } } j = txt.indexOf("e"); // only one e if (j!=-1) { while (txt.indexOf("e", j+1)!=-1) { int k = txt.indexOf("e", j+1); txt = txt.substring(0,k)+txt.substring(k+1, txt.length()); change = true; } } j = txt.indexOf("-"); // max 2 "-" (e.g.: -5e-10) if (j!=-1) { j = txt.indexOf("-", j+1); if (j!=-1) { while (txt.indexOf("-", j+1)!=-1) { int k = txt.indexOf("-", j+1); txt = txt.substring(0,k)+txt.substring(k+1, txt.length()); change = true; } } } if (change) { gui.setText(parameters[1], txt); } ( (TextComponent) (gui.getComponentByName(parameters[1])) ).setCaretPosition(txt.length()); } } void applyChanges() { String tf; float val; tf = gui.getText("decay"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("decay","0"); } DECAY = val; tf = gui.getText("spread"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("spread","0"); } SPREAD = val; tf = gui.getText("csThreshold"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("csThreshold","0"); } ENERGYTHRESHOLD = val; tf = gui.getText("cost"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("cost","0"); } SPAWNCONSUME = val; tf = gui.getText("cdThreshold"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("cdThreshold","0"); } DEATHVALUE = val; tf = gui.getText("liquification"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("liquification","0"); } NUTRIENTVALUE = val; tf = gui.getText("connective"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("connective","0"); } CONNECTIVE_TENDENCY = val; tf = gui.getText("depletion"); try { val = Float.valueOf(tf).floatValue(); } catch (NumberFormatException e) { val = 0; gui.setText("depletion","0"); } ENERGYDEPLETE = val; SHARE = gui.getState("share"); } void draw() { loadPixels(); if (spilling) { liquidMat.spill(xM, yM); } liquidMat.process(); lifeMat.process(); int pixel = 0; int pos = 0; float val; int mX, mY, sY, sX, cr,cg,cb, col, offset; for (mY = 0; mY < sHeight; mY++) { for (mX = 0; mX < sWidth; mX++) { if (displayCells&&lifeMat.isCell(pos)) { col = 0xFFFFFFFF; for (sY = (zoom-1); sY>=0; sY--) { offset = sY*width; for (sX = (zoom-1); sX>=0; sX--) { pixels[pixel+sX+offset] = col; } } } else if (displayLiquid) { val = liquidMat.getValue(pos); if (val > 1f) val = 1f; if (val > 0.1f) { cr = (int) (231f*val); cg = (int) (143f*val*val); cb = (int) (63f*val); col = baseCol + (cr<<16 | cg << 8 | cb); for (sY = (zoom-1); sY>=0; sY--) { offset = sY*width; for (sX = (zoom-1); sX>=0; sX--) { pixels[pixel+sX+offset] = col; } } } else { cr = (int) (231f*val); cg = (int) (143f*val*val); cb = (int) (63f*val); col = baseCol + (cr<<16 | cg << 8 | cb); for (sY = (zoom-1); sY>=0; sY--) { offset = sY*width; for (sX = (zoom-1); sX>=0; sX--) { pixels[pixel+sX+offset] = col; } } } } else { col = baseCol; for (sY = (zoom-1); sY>=0; sY--) { offset = sY*width; for (sX = (zoom-1); sX>=0; sX--) { pixels[pixel+sX+offset] = col; } } } pixel+=zoom; pos++; } pixel += width*(zoom-1); } updatePixels(); } void mousePressed() { xM = mouseX/zoom; yM = mouseY/zoom; spilling = true; } void mouseReleased() { spilling = false; } void mouseDragged() { xM = mouseX/zoom; yM = mouseY/zoom; spilling = true; } int getCoord(int x, int y) { if (x < 0) x = sWidth + x; if (x >= sWidth) x -= sWidth; if (y < 0) y = sHeight + y; if (y >= sHeight) y -= sHeight; return y*sWidth+x; } class LifeMatrix { float[] energy; boolean[] processed; int numberOfCells; LiquidMatrix liquid; LifeMatrix() { numberOfCells = sHeight*sWidth; energy = new float[numberOfCells]; processed = new boolean[numberOfCells]; for (int i = 0; i < numberOfCells; i++) { energy[i] = 0; processed[i] = false; } } void process() { float deathvalue = DEATHVALUE; float nutrientvalue = NUTRIENTVALUE; float energyconsume = ENERGYCONSUME; float energydeplete = ENERGYDEPLETE; for (int i = 0; i 1) energy[i] = 1; } int which = 0; for (int y = 0; y < sHeight; y++) { for (int x = 0; x < sWidth; x++) { // sterben? if (isCell(which) && energy[which] < deathvalue && !processed[which]) { energy[which] = 0; liquid.spill(x,y, nutrientvalue); } if (isCell(which) && !processed[which]) { // Energie abgleichen float energyValue = energy[which]; float thisCell = getEnergyValue(x,y); energyValue *= thisCell*energyconsume; float addTimesEnergy = -(CONNECTIVE_TENDENCY*energyValue); // energy[which] = energyValue-addTimesEnergy; int nextPosition = which; LiquidCell t = liquid.getCell(which); t.setValue(t.getValue()*energydeplete); // nächste Position float nextEnergy = 0; int nextCoord = which; boolean claim; // optimize this stuff...? nextEnergy = getEnergyValue(x,y-1)+addTimesEnergy; nextCoord = getCoord(x,y-1); claim = (getLowestNeighbor(x, y-1) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } nextEnergy = getEnergyValue(x+1,y-1)+addTimesEnergy; nextCoord = getCoord(x+1,y-1); claim = (getLowestNeighbor(x+1, y-1) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } nextEnergy = getEnergyValue(x+1,y)+addTimesEnergy; nextCoord = getCoord(x+1,y); claim = (getLowestNeighbor(x+1, y) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } nextEnergy = getEnergyValue(x+1,y+1)+addTimesEnergy; nextCoord = getCoord(x+1,y+1); claim = (getLowestNeighbor(x+1, y+1) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } nextEnergy = getEnergyValue(x,y+1)+addTimesEnergy; nextCoord = getCoord(x,y+1); claim = (getLowestNeighbor(x, y+1) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } nextEnergy = getEnergyValue(x-1,y+1)+addTimesEnergy; nextCoord = getCoord(x-1,y+1); claim = (getLowestNeighbor(x-1, y+1) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } nextEnergy = getEnergyValue(x-1,y)+addTimesEnergy; nextCoord = getCoord(x-1,y); claim = (getLowestNeighbor(x-1, y) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } nextEnergy = getEnergyValue(x-1,y-1)+addTimesEnergy; nextCoord = getCoord(x-1,y-1); claim = (getLowestNeighbor(x-1, y-1) >= energyValue); if (!isCell(nextCoord)&&nextEnergy>thisCell&&claim) { nextPosition = nextCoord; thisCell = nextEnergy; } energy[which] = 0; /* if (SHARE) { energy[nextPosition] = energyValue-addTimesEnergy; } else {*/ energy[nextPosition] = energyValue; // } processed[nextPosition] = true; // --- } which++; } } } float getCellEnergy(int where) { return energy[where]; } float getCellEnergy(int x, int y) { return energy[getCoord(x,y)]; } void spawn(int x, int y) { int where = getCoord(x,y); energy[where] = 1; } void spawn(int where) { energy[where] = 1; } boolean isCell(int x, int y) { int where = getCoord(x,y); if (energy[where] > 0) { return true; } else return false; } boolean isCell(int where) { if (energy[where] > 0) { return true; } else return false; } private float getLowestNeighbor(int x, int y) { int[] n = new int[8]; n[0] = getCoord(x, y-1); n[1] = getCoord(x+1, y-1); n[2] = getCoord(x+1, y); n[3] = getCoord(x+1, y+1); n[4] = getCoord(x, y+1); n[5] = getCoord(x-1, y+1); n[6] = getCoord(x-1, y); n[7] = getCoord(x-1, y-1); float lowest = 1000; for (int i = 0; i < 8; i++) { if (isCell(n[i]) && !processed[n[i]] && (energy[n[i]] 1) newValue = 1; } if (newValue < LOWERTHRESHOLD) newValue = 0; if (value > ENERGYTHRESHOLD) { turn++; } else turn = 0; } final public void swap() { value = newValue; } } class LiquidMatrix { LiquidCell[] cells; int numberOfCells = sHeight*sWidth; LifeMatrix life; LiquidMatrix() { cells = new LiquidCell[numberOfCells]; for (int i = 0; i < numberOfCells; i++) { cells[i] = new LiquidCell(); } for (int y=0; y= turnthreshold) { c.turn = 0; life.spawn(i); c.setValue(c.getValue()*spawnconsume); } } } void spill(int x, int y) { float spillamount = SPILLAMOUNT; float spillantialiasing = ANTIALIASING * SPILLAMOUNT; if (x < sWidth && y < sHeight) { int c = getCoord(x, y); cells[c].setValue(cells[c].getValue()+spillamount); c = getCoord(x-1, y); cells[c].setValue(cells[c].getValue()+spillamount); c = getCoord(x+1, y); cells[c].setValue(cells[c].getValue()+spillamount); c = getCoord(x, y-1); cells[c].setValue(cells[c].getValue()+spillamount); c = getCoord(x, y+1); cells[c].setValue(cells[c].getValue()+spillamount); c = getCoord(x-1, y+1); cells[c].setValue(cells[c].getValue()+spillantialiasing); c = getCoord(x+1, y-1); cells[c].setValue(cells[c].getValue()+spillantialiasing); c = getCoord(x-1, y-1); cells[c].setValue(cells[c].getValue()+spillantialiasing); c = getCoord(x+1, y+1); cells[c].setValue(cells[c].getValue()+spillantialiasing); } } void spill(int x, int y, float f) { float spillantialiasing = f*ANTIALIASING; if (x < sWidth && y < sHeight) { int c = getCoord(x, y); cells[c].setValue(cells[c].getValue()+f); c = getCoord(x-1, y); cells[c].setValue(cells[c].getValue()+f); c = getCoord(x+1, y); cells[c].setValue(cells[c].getValue()+f); c = getCoord(x, y-1); cells[c].setValue(cells[c].getValue()+f); c = getCoord(x, y+1); cells[c].setValue(cells[c].getValue()+f); c = getCoord(x-1, y+1); cells[c].setValue(cells[c].getValue()+spillantialiasing); c = getCoord(x+1, y-1); cells[c].setValue(cells[c].getValue()+spillantialiasing); c = getCoord(x-1, y-1); cells[c].setValue(cells[c].getValue()+spillantialiasing); c = getCoord(x+1, y+1); cells[c].setValue(cells[c].getValue()+spillantialiasing); } } float getValue(int x, int y) { return cells[getCoord(x, y)].getValue(); } float getValue(int i) { return cells[i].getValue(); } LiquidCell getCell(int x, int y) { return cells[getCoord(x, y)]; } LiquidCell getCell(int i) { return cells[i]; } void reset() { for (int i = 0; i < numberOfCells; i++) { cells[i].newValue = 0; cells[i].setValue(0); } } }