First pattern - asking for timing help

Hello - I’ve made my first pattern.

It’s a dim colour shift with a bright white non-repeating random white bulb.

However, I need help with the beforeRender/delta to understand how to slow it down / speed it up with a variable. This is a different way of thinking compared with my old Arduino controller, so I’m having a bit of trouble with it.

You may like my non-repeating random code…

nonRepeatingRandom = array(pixelCount) //ToDo: maybe split total pixels into a number of repeats

for (range = 0; range < pixelCount; range++) {
  nonRepeatingRandom[range] = range
}
// Random shuffle, so, randomTable[0]=38, randomTable[1]=13.. etc..
for (shuffle = 0; shuffle < pixelCount - 1; shuffle++) {
  myrand = shuffle + random(pixelCount - shuffle);
  save = nonRepeatingRandom[shuffle];
  nonRepeatingRandom[shuffle] = nonRepeatingRandom[myrand];
  nonRepeatingRandom[myrand] = save;
}

eyePosition = 0

export function beforeRender(delta) {
  eyePosition = eyePosition + 1
  if (eyePosition  == pixelCount) {
    eyePosition = 0
  }
  t1 = time(.1)
}

export function render(index) {
  if (index == nonRepeatingRandom[(eyePosition + index) % pixelCount]) {
    hsv(0.0, 0, 1)
  } else {
    hsv(t1, 1, 0.1)
  }
}

Hi @MarkEMark,
Nice! It takes a little adjustment, but once you have that there are tons of benefits, like a consistent animation speed regardless of number of pixels or FPS.

OK so delta can be used to make something change more when more time passes, or less when less time passes.

In your code, you have this line:

eyePosition = eyePosition + 1

This moves the position by a fixed speed (1) for every animation frame, regardless of how much time elapsed between those frames. To make it relative to time, use delta instead of a fixed value. Delta is given in units of milliseconds, so we’ll need a smaller number, so we can multiply it by a coefficient to bring the speed to something usable.

This will increase eyePosition by smaller amounts over time consistently, but it will also no longer always be a whole integer, so the end position test needs to change in case it is not exactly equal.

  eyePosition = eyePosition + delta * .005
  if (eyePosition >= pixelCount) {
    eyePosition = 0
  }

You can change the .005 coefficient above to get the speed/effect you are looking for.

1 Like

This is great, Wizard! Thanks!

I’ve made the 0.005 a slider variable so I can change the speed.

I’ve one last request, if you don’t mind…

I’ve made the Hue shift speed a slider variable:

hsv(t1 * colourChangeSpeed, 1, 0.1)

But when I slide it down, it only get so far though the colour wheel before restarting.

How could I make it just slow/speed up the colour shift?

I think when I’ve got this clear in my head, I will be able to do everything else that I wish to do.

Thanks!

You’d need to change the input to time() that generated the value in t1 - otherwise like you are seeing, the hue input is going have a smaller range than the full spectrum. Given that t1 ranges from 0-1 at a set rate, multiplying it by 0.5 will make it go from 0-0.5 at the same rate. That would kind of work if it was an integer, e.g. multiplying by 2 would cause it to range from 0-2 at the same rate, but hue “wraps” at each integer value so effectively cycles twice.

Putting arguments to time() in a slider will work, though it tends to jump the animation around while you are sliding. Another way to do the same is to accumulate t1 based on delta and a variable speed coefficient. e.g.

/*
This pattern is based on the default scrolling rainbow and has a slider to control speed.
It uses an accumulation based on delta instead of time() so that changes in speed do not cause the animation to jump.
The downsides is slightly more code, and this pattern won't be synchronized with other Pixelblazes through firestorm.
*/

var speedRange = 1/1000 // this scales the milliseconds back to a usable range. shown here, the max rate is 1Hz
var speed = speedRange // controlled by slider

export function sliderSpeed(s) {
  speed = s*s * speedRange // square it to give better control at lower values, then scale it
}

var t1
export function beforeRender(delta) {
  t1 = (t1 + delta * speed) % 1 // accumulate time in t1, and wrap it using modulus math to keep it between 0-1
}

export function render(index) {
  h = t1 + index/pixelCount
  s = 1
  v = 1
  hsv(h, s, v)
}

Example_ Smooth Speed Slider.epe (10.5 KB)

1 Like

Thanks Wizard, Your code helped me a lot. Your recent code spreads a rainbow across the string, but I worked out how to make it a single colour (basically 1/pixelcount instead of index/pixelcount)

However, I like to keep the options open, so I’ve made that depend on a slider too.

I’ve still a lot to do before it matches the pattern that I have in mind, and also a lot more patterns to do.

If you are interested, here is my Android Wallpaper that shows off the patterns

It’s fairly old now, but shows all the patterns that I have written and am going to port over.

Also, here’s my latest code (eyeSize doesn’t do anything yet):

var eyePosition = 0
export var eyeSize = 1
var t1
var speedRange = 1/500 // this scales the milliseconds back to a usable range. shown here, the max rate is 1Hz
var colourChangeSpeed = speedRange // controlled by slider
var strobeSpeed = 0.5
export var colourSpread = 1

nonRepeatingRandom = array(pixelCount) //ToDo: maybe split total pixels into a number of repeats

for (range = 0; range < pixelCount; range++) {
  nonRepeatingRandom[range] = range
}
// Random shuffle, so, randomTable[0]=38, randomTable[1]=13.. etc..
for (shuffle = 0; shuffle < pixelCount - 1; shuffle++) {
  myrand = shuffle + random(pixelCount - shuffle);
  save = nonRepeatingRandom[shuffle];
  nonRepeatingRandom[shuffle] = nonRepeatingRandom[myrand];
  nonRepeatingRandom[myrand] = save;
}

export function sliderEyeSize(v) {
    eyeSize = 1 + (v * 19)
}

export function sliderStrobeSpeed(v) {
    strobeSpeed = v
}

export function sliderColourChangeSpeed(s) {
  colourChangeSpeed = s*s * speedRange // square it to give better control at lower values, then scale it
}

export function sliderColourSpread(v) {
    colourSpread = v / 50.0
}

export function beforeRender(delta) {
eyePosition = eyePosition + delta * strobeSpeed * 0.1
  if (eyePosition >= pixelCount) {
    eyePosition = 0
  }
  t1 = (t1 + delta * colourChangeSpeed) % 1 // accumulate time in t1, and wrap it using modulus math to keep it between 0-1
}

export function render(index) {
  if (index == nonRepeatingRandom[(eyePosition + index) % pixelCount]) {
    hsv(0.0, 0, 1)
  } else {
    h = t1 + (1 +  (colourSpread * index * pixelCount))/pixelCount
    hsv(h, 1, 0.1)
  }
}
2 Likes