If you use "Card -> Copy Card" from the menu, Decker will store a text-based serialization of the card, its widgets, and any fonts or contraption prototypes those widgets reference in the clipboard. This also works with "Edit -> Copy Widgets" for a group of widgets. As in the examples in The Contraption Bazaar, this can be a handy way of sharing a chunk of a project that Decker users can immediately paste into their own deck and try out. Here's how that might look for your example:
%%CRD0{"c":{"name":"card1","script":"local s: \"abcdef\"\non view do\n if ! sys.frame < next_frame.text\n canvas.clear[]\n local t: flip (list \"\" split s),(list random[2 count s])\n local y: \"\" fuse each u in t if u[1] \"%u\" else \"%s\" end format u[0] end\n canvas.text[y (50,50, 200,100)]\n next_frame.text: sys.frame + 5\n end\n go[card]\nend","widgets":{"canvas":{"type":"canvas","size":[100,100],"pos":[206,121],"volatile":1,"scale":1},"next_frame":{"type":"field","size":[100,20],"pos":[63,128],"volatile":1}}},"d":{}}
(Note that sometimes the itch.io WYSIWYG editor will scramble code that it confuses for embedded HTML; this can be quite annoying, but is not a bug in Decker.)
I have marked the canvas as "volatile" to keep the snippet smaller, since the script clears and repaints it constantly.
There are a few ways we can simplify and improve the script:
- Instead of using a "next_frame" field to keep track of the most recent refresh, we could repaint when sys.frame modulo 5 is 0; then there's no extra state to worry about. This also avoids the latent problem that saving a deck (and thus serializing the field) may mean that the number in that field is much larger than sys.frame on the next work session, causing the animation to appear to "freeze" for an arbitrary amount of time before playing. This can be avoided (as in the snippet above) by also making the next_frame field volatile.
- By marking the canvas as "animated", Decker will automatically send "view" events to the canvas, allowing us to move the script within the canvas and make it self-contained, referring to itself as "me". Using a card-level event pump may be easier in some cases; use whatever approach you prefer.
- If you want to "zipper" a pair of lists into a list of pairs, you can use the Lil "join" operator instead of transposing a pair of lists:
(1,2,3) join "ABC" ((1,"A"),(2,"B"),(3,"C")) local s: "abcdef" s join random[2 count s] (("a",0),("b",1),("c",0),("d",0),("e",0),("f",0))
- In this situation, however, we don't actually need to build that list of pairs; we could instead randomly choose a case-formatting string while iterating over the letters. The random[] function can be called with any list, producing a random choice from that list:
random["%u","%l"] "%u" random["%u","%l"] "%l"
- canvas.text[], like many functions in Lil which expect a string argument, will implicitly fuse lists of strings together, so you don't need to do so explicitly.
- Assuming the goal was to center the string within the canvas, you can do this generically by using the third "anchor" parameter for canvas.text[].
With these tweaks, the script would be:
local s: "abcdef" on view do if !5%sys.frame local y:each c in s random["%u","%l"] format c end me.clear[] me.text[y me.size/2 "center"] end end
If we wanted to "code golf" there are a few more ways we could shorten this script, but whether you'd consider them improvements is subjective:
- The "local" keyword for variable declarations is optional; we only need it explicitly as documentation of intent to human readers and to force Lil to shadow, rather than inherit, variable declarations of the same name in a higher scope. In this situation it doesn't change the semantics of the program.
- The variable "s" is now used only once, so we can inline its value.
- Likewise the variable "y" is now used only once, so we can inline the entire loop into its use site.
on view do if !5%sys.frame me.clear[] me.text[ each c in "abcdef" random["%u","%l"] format c end me.size/2 "center" ] end end
And as a widget snippet attached to a volatile canvas:
%%WGT0{"w":[{"name":"canvas","type":"canvas","size":[100,100],"pos":[206,121],"animated":1,"volatile":1,"script":"on view do\n if !5%sys.frame\n me.clear[]\n me.text[\n each c in \"abcdef\" random[\"%u\",\"%l\"] format c end\n me.size/2 \"center\"\n ]\n end\nend","scale":1}],"d":{}}
Does that help?