From: Vincent Siao Date: Sun, 24 Nov 2013 00:51:57 +0000 (-0800) Subject: AsanaThankshackathon/VSTowers X-Git-Url: https://git.piment-noir.org/?p=SugarCubes.git;a=commitdiff_plain;h=20e7c94f16a8f2449bf978052c090eab872ecded AsanaThankshackathon/VSTowers --- diff --git a/SugarCubes.pde b/SugarCubes.pde index 40f9a76..6651e18 100644 --- a/SugarCubes.pde +++ b/SugarCubes.pde @@ -66,6 +66,9 @@ LXPattern[] patterns(GLucose glucose) { new TimSpheres(glucose), + + // Vincent + new VSTowers(glucose), // Toby new GlitchPlasma(glucose), diff --git a/VincentSiao.pde b/VincentSiao.pde new file mode 100644 index 0000000..48a368e --- /dev/null +++ b/VincentSiao.pde @@ -0,0 +1,119 @@ +class VSTowers extends SCPattern { + private BasicParameter saturationParameter = new BasicParameter("SAT", 80, 0, 100); + private BasicParameter attackParameter = new BasicParameter("ATTK", 0.96, 0.1, 1.0); + private BasicParameter decayParameter = new BasicParameter("DECAY", 0.7, 0.1, 1.0); + private SawLFO hueLfo = new SawLFO(0, 360, 20000); + + private Map towerOn; + + class TowerFlash { + Tower t; + float value; + float maxVal; + float hue; + boolean hasPeaked; + + TowerFlash() { + do { + t = model.towers.get(floor(random(model.towers.size()))); + } while (towerOn.get(t)); + towerOn.put(t, true); + hue = (hueLfo.getValuef() + 50*(random(2)-1.0f)) % 360; + value = 0.0; + maxVal = random(0.4) + 0.6; + } + + boolean run(double deltaMs) { + if (!hasPeaked) { + float atk = attackParameter.getValuef(); + float atkDuration = 10000 * (1/sqrt(atk) - 1.0f); + value = value + (float)deltaMs / atkDuration; + if (value >= maxVal) { + value = maxVal; + hasPeaked = true; + } + return false; + } else { + float dec = decayParameter.getValuef(); + float decDuration = 10000 * (1/sqrt(dec) - 1.0f); + value = value - (float)deltaMs / decDuration; + return value <= 0; + } + } + } + + public VSTowers(GLucose glucose) { + super(glucose); + addParameter(saturationParameter); + addParameter(attackParameter); + addParameter(decayParameter); + addModulator(hueLfo).trigger(); + flashes = new LinkedList(); + towerOn = new HashMap(); + for (Tower t : model.towers) { + towerOn.put(t, false); + } + } + + private List flashes; + private float accDelta = 0; + + public void run(double deltaMs) { + accDelta += deltaMs; + float rate = lx.tempo.rampf(); + float msPerFlash = 5000 * (1/sqrt(rate) - 1.0f); + if (accDelta >= msPerFlash) { + accDelta -= msPerFlash; + if (flashes.size() < model.towers.size()) { + flashes.add(new TowerFlash()); + } + } + for (LXPoint p : model.points) { + if (random(1) < 0.2) { + colors[p.index] = 0; + } + } + for (TowerFlash tf : flashes) { + for (LXPoint p : tf.t.points) { + float towerHeight = model.yMin + tf.value * (model.yMax - model.yMin); + if (p.y <= towerHeight) { + colors[p.index] = lx.hsb( + (tf.hue + tf.value*50 - p.y/2) % 360, + saturationParameter.getValuef(), + tf.value*100); + } + } + if (tf.hasPeaked) { + float towerMaxHeight = model.yMin + tf.maxVal * (model.yMax - model.yMin); + Cube top = tf.t.cubes.get(tf.t.cubes.size()-1); + for (int i = tf.t.cubes.size()-1; i >= 0; --i) { + Cube c = tf.t.cubes.get(i); + float maxY = c.points.get(0).y; + for (LXPoint p : c.points) { + maxY = max(maxY, p.y); + } + if (towerMaxHeight < maxY) { + top = c; + } + } + for (LXPoint p : top.points) { + if (tf.value > 0.5) { + colors[p.index] = lx.hsb(0, 0, tf.value*100); + } else if (random(1) < 0.2) { + colors[p.index] = 0; + } + } + } + } + // Run flashes and remove completed ones + Iterator it = flashes.iterator(); + while (it.hasNext()) { + TowerFlash flash = it.next(); + if (flash.run(deltaMs)) { + towerOn.put(flash.t, false); + it.remove(); + } + } + } +} +