I have a 240-LED strip connected to the PB and it has three “sprites” that move along its length. The thing is, sometimes the sprites ‘hiccup’ - jump back and forth a little. When I watch the variable “tailV” - which is supposed to be a scalar - it changes to a multi-member array and this coincides with the ‘hiccups’. I don’t think my code should make it an array so I’m wondering what’s up.
Here’s the complete code:
// arrays of sprite parameters
acc = [0.0, 0.0, 0.0]; // acceleration
vel = [0.0, 0.0, 0.0]; // velocity
var pos = [100, 0, 0]; // position
lowIndex = [0.0, 0.0, 0.0]; // the index in the pixel array of the low end of the sprite (always an int)
centerIndex = [0.0, 0.0, 0.0]; // index in the pixel array of the center of the sprite (float)
highIndex = [0.0, 0.0, 0.0]; // the index in the pixel array of the high end of the sprite (always an int)
relPos = [0.0, 0.0, 0.0]; // fraction from 0-1 of proximity to low index of the center
var spriteHue = [1.0, 0.66, 0.33]; // the colors of the sprites
var k = 1.0; // spring constant for all sprites
// arrays of hsv values for display
var h = array(240);
var s = array(240);
var v = array(240);
// function for overlapping sprites
// adds the values mod 1
function addMod(x, y) {
var val = x + y;
if (val > 1.0) {
return val - 1;
} else {
return val;
}
}
// another function for overlapping sprites
// adds the values and caps at 1
function addMax(x, y) {
var val = x + y;
if (val > 1.0) {
return 1.0;
} else {
return val;
}
}
// another function for overlapping sprites
// averages the value if the first one is non-zero
function addAvg(x, y) {
if (x > 0) {
return (x + y)/2.0;
} else {
return y;
}
}
export function beforeRender(delta) {
// do the diff eq math to move the sprite
// oddly, deltas are negative
dt = (-1) * delta/40000;
// because coupling is complex, pull accelerations out of the loop
acc[0] = (-1*(k * pos[0])) + (0.1 * pos[2]);
acc[1] = (-1*(k * pos[1])) + (0.1 * pos[0]);
acc[2] = (-1*(k * pos[2])) + (0.1 * pos[1]);
// x is the sprite index
for (x = 0; x < acc.length; x++) {
// move the sprite
//acc[x] = - (k * pos[x]);
vel[x] = vel[x] + (acc[x] * dt);
pos[x] = pos[x] + (vel[x] * dt);
// find the two adjacent points that determine the sprite's location
// as well as center (for doing the fade outs)
// relPos = 0 if at low; 1 if at high
// and map from -120 to +120 to 0 to 240
lowIndex[x] = (floor(pos[x]) + 120);
centerIndex[x] = pos[x] + 120;
highIndex[x] = (ceil(pos[x]) + 120);
relPos[x] = centerIndex[x] - lowIndex[x];
}
// first, clear the display
for (i = 0; i < 240; i++) {
// default is black
h[i] = 0.0;
s[i] = 0.0;
v[i] = 0.0;
}
// now, draw in the sprites
// x is sprite index
for(x = 0; x < acc.length; x++) {
var tailV = 1 - (centerIndex[x] - lowIndex[x]); // 0-1 for the sprite's proximity to low dot
var i = 0;
while (tailV > 0.001) {
h[lowIndex[x] + i] = addAvg(h[lowIndex[x] + i], spriteHue[x]);
s[lowIndex[x] + i] = 1.0;
v[lowIndex[x] + i] = addMax(v[lowIndex[x] + i], tailV);
i = i - 1; // low end tail goes in - direction
tailV = tailV * 0.1; // tail fades out
}
tailV = 1 - (highIndex[x] - centerIndex[x]); // 0-1 for sprite's proximity to high dot
i = 0;
while (tailV > 0.001) {
h[highIndex[x] + i] = addAvg(h[highIndex[x] + i], spriteHue[x]);
s[highIndex[x] + i] = 1.0;
v[highIndex[x] + i] = addMax(v[highIndex[x] + i], tailV);
i = i + 1; // high end tail goes in + direction
tailV = tailV * 0.1; // tail fades out
}
}
}
export function render(index) {
hsv(h[index], s[index], v[index]);
}