redo with new anti-GLucose
[SugarCubes.git] / VincentSiao.pde
1 class VSTowers extends SCPattern {
2 private BasicParameter saturationParameter = new BasicParameter("SAT", 80, 0, 100);
3 private BasicParameter attackParameter = new BasicParameter("ATTK", 0.96, 0.1, 1.0);
4 private BasicParameter decayParameter = new BasicParameter("DECAY", 0.7, 0.1, 1.0);
5 private SawLFO hueLfo = new SawLFO(0, 360, 20000);
6
7 private Map<Tower, Boolean> towerOn;
8
9 class TowerFlash {
10 Tower t;
11 float value;
12 float maxVal;
13 float hue;
14 boolean hasPeaked;
15
16 TowerFlash() {
17 do {
18 t = model.towers.get(floor(random(model.towers.size())));
19 } while (towerOn.get(t));
20 towerOn.put(t, true);
21 hue = (hueLfo.getValuef() + 50*(random(2)-1.0f)) % 360;
22 value = 0.0;
23 maxVal = random(0.4) + 0.6;
24 }
25
26 boolean run(double deltaMs) {
27 if (!hasPeaked) {
28 float atk = attackParameter.getValuef();
29 float atkDuration = 10000 * (1/sqrt(atk) - 1.0f);
30 value = value + (float)deltaMs / atkDuration;
31 if (value >= maxVal) {
32 value = maxVal;
33 hasPeaked = true;
34 }
35 return false;
36 } else {
37 float dec = decayParameter.getValuef();
38 float decDuration = 10000 * (1/sqrt(dec) - 1.0f);
39 value = value - (float)deltaMs / decDuration;
40 return value <= 0;
41 }
42 }
43 }
44
45 public VSTowers(LX lx) {
46 super(lx);
47 addParameter(saturationParameter);
48 addParameter(attackParameter);
49 addParameter(decayParameter);
50 addModulator(hueLfo).trigger();
51 flashes = new LinkedList<TowerFlash>();
52 towerOn = new HashMap();
53 for (Tower t : model.towers) {
54 towerOn.put(t, false);
55 }
56 }
57
58 private List<TowerFlash> flashes;
59 private float accDelta = 0;
60
61 public void run(double deltaMs) {
62 accDelta += deltaMs;
63 float rate = lx.tempo.rampf();
64 float msPerFlash = 5000 * (1/sqrt(rate) - 1.0f);
65 if (accDelta >= msPerFlash) {
66 accDelta -= msPerFlash;
67 if (flashes.size() < model.towers.size()) {
68 flashes.add(new TowerFlash());
69 }
70 }
71 for (LXPoint p : model.points) {
72 if (random(1) < 0.2) {
73 colors[p.index] = 0;
74 }
75 }
76 for (TowerFlash tf : flashes) {
77 for (LXPoint p : tf.t.points) {
78 float towerHeight = model.yMin + tf.value * (model.yMax - model.yMin);
79 if (p.y <= towerHeight) {
80 colors[p.index] = lx.hsb(
81 (tf.hue + tf.value*50 - p.y/2) % 360,
82 saturationParameter.getValuef(),
83 tf.value*100);
84 }
85 }
86 if (tf.hasPeaked) {
87 float towerMaxHeight = model.yMin + tf.maxVal * (model.yMax - model.yMin);
88 Cube top = tf.t.cubes.get(tf.t.cubes.size()-1);
89 for (int i = tf.t.cubes.size()-1; i >= 0; --i) {
90 Cube c = tf.t.cubes.get(i);
91 float maxY = c.points.get(0).y;
92 for (LXPoint p : c.points) {
93 maxY = max(maxY, p.y);
94 }
95 if (towerMaxHeight < maxY) {
96 top = c;
97 }
98 }
99 for (LXPoint p : top.points) {
100 if (tf.value > 0.5) {
101 colors[p.index] = lx.hsb(0, 0, tf.value*100);
102 } else if (random(1) < 0.2) {
103 colors[p.index] = 0;
104 }
105 }
106 }
107 }
108 // Run flashes and remove completed ones
109 Iterator<TowerFlash> it = flashes.iterator();
110 while (it.hasNext()) {
111 TowerFlash flash = it.next();
112 if (flash.run(deltaMs)) {
113 towerOn.put(flash.t, false);
114 it.remove();
115 }
116 }
117 }
118 }
119