Szenenscript für "Lava-Lampe"

Das folgende Szenenscripts eignet sich für SmartLED-Leuchten wie die p44torch (in der Selbstbau- wie auch in der fertig gekauften Variante). Es verwendet die LEDs, die in einer Fläche angeordnet sein sollten (bei der p44torch in ca. 22 Reihen mit je 11 LEDs), um eine Lavalampen-ähnliche Animation anzuzeigen.

Wie ein Szenenscript eingeben?

Eine detaillierte Anleitung, wie ein Szenenscript auf einem P44-DSB oder P44-LC-Gerät erstellt wird, gibt es hier.

Benötigt Firmware 2.7.0 / 2.7.0.34 oder neuer

Dieses Beispiel benötigt die zum Zeitpunkt des Schreibens als öffentliche Beta verfügbare Version 2.7.0.34 oder neuer. Erst diese Version erlaubt das Scrollen mit Subpixel-Auflösung, das die Illusion von kontinuierlicher Bewegung erzeugt, und kein Pixelweises "Hüpfen".

Zusätzliche "Lampe" erstellen

Als Basis braucht das Szenenscript eine Fläche, auf dem die Animation angezeigt werden kann. Dieses einzurichten funktioniert genau gleich wie bei der "Fackel"-Animation, also so wie hier im Detail beschrieben, mit der Ausnahme dass im letzten Feld "Feature config" nicht "torch" sondern "stack" stehen muss. Ein "stack" ist ein zunächst leerer View, auf dem dann mit dem Szenenscript die sich bewegenden Blasen- (blob-)Views plaziert und animiert werden.

Szenenscript eingeben

Das folgende Skript kann 1:1 kopiert und in das Feld "Script to execute..." im Szenenedit-Dialog eingegeben werden, aber natürlich auch nach Bedarf angepasst werden.

// "Lava-Lamp"

// remove all existing subviews (blobs from previous runs)
view.clear()
view.configure({
  framing: 'repeatX|clipY',
  bgcolor: '#001608', // yellow orange
})

// get the frame of the area to display the "lava" animation
var area = ledchaincover()

// the sea view is a slightly "waving" bottom
var sea = {
  type: 'lightspot',
  label: 'sea',
  extent_x: 5,
  extent_y: 5,
  color: '#480',
  bgcolor: '0000',
  alpha:255,
  z_order: 1000,
  // finetuning
  brightness_gradient: -1,
  hue_gradient: 0.34,
  saturation_gradient: 0,
  brightness_mode: 'linear|oscillating|unlimited',
  hue_mode: 'linear|oscillating|unlimited',
  saturation_mode: 'linear|oscillating|unlimited',
  radial: false,
  orientation: 'up',
}
sea += area
sea.dy = 5
var s = makeview(sea)
s.set('fullframe', true)
view.addview(s)
// make it "rocking" a bit with a continuously running back-and-forth animation of the rotation parameter
s.animator('rotation').repeat(-1,true).step(0.05,1).from(-15).runto(15,20)

var blobcount = 0
var currentblobs = 0

while (true) {

  var blob = {
    type: 'lightspot',
    extent_x: 5,
    extent_y: 5,
    color: hsv(random(15, 90, 1)), // orange to yellow
    bgcolor: '0000', // transparent background (important)
    alpha:200,
    z_order: 900,
    // finetuning
    brightness_gradient: -1,
    hue_gradient: 0,
    saturation_gradient: 0,
    brightness_mode: 'linear|oscillating|unlimited',
    hue_mode: 'linear|oscillating|unlimited',
    saturation_mode: 'linear|oscillating|unlimited',
    radial: true,
  }
  blob += area
  blobcount++
  blob.label = format("blob_%d", blobcount)

  var v = makeview(blob)
  v.fullframe()
  v.content_x = 5
  v.content_y = 5
  v.framing = 'repeatX|clipY' // wrap around tube in X-direection

  v.x = random(0, area.dx, 1) // random position somewhere around the tube
  view.addview(v)

  // further "life" of the blob view (moving up, sinking down again) now happens in a concurrent thread
  concurrent passing v {
    currentblobs++
    // move up
    threadvar a = v.animator('scroll_y').function('easeinout').from(10).runto(-area.dy+6,random(15,22))
    await(a)
    // sink down again
    a = v.animator('scroll_y').function('easeinout').runto(10,random(18,30))
    await(a)
    // that's it for this blob, remove it
    v.remove()
    currentblobs--
    log('%s removed, now=%d',v.label, currentblobs)
  }

  // wait a bit before creating another blob
  delay(random(4,15))
  while (currentblobs>=3) {
    // wait longer when we already have 3 or more blobs
    delay(20)
  }
}

Weitere Infos