Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Lil Programming Questions Sticky

A topic by Internet Janitor created Oct 28, 2022 Views: 28,134 Replies: 446
Viewing posts 41 to 60 of 132 · Next page · Previous page · First page · Last page

Hello,

There's probably a trick for that, but I didn't find a way to create a single element dict:


("foo") dict ("bar") => {"f":"b", "o": "r"}



Whereas:

("foo", "baz") dict ("bar", "qux")


does the expected.


Developer

The straightforward way is to use the "list" operator, which wraps its argument in a length-1 list:

 (list "foo") dict (list "bar") 
{"foo":"bar"}

A fancier, more concise way (provided your keys are strings) is to perform an amending assignment to an empty list, like so:

 ().foo:"bar"
{"foo":"bar"}
(+1)

Thanks! very helpful!

Some cards in my deck have a field called "group" with a number in the text field.

In my deck, how would I go about selecting a random card that matches a specific group number and then send the player to that card?

Developer (1 edit)

To obtain a list of the cards with a particular group number you could use a query something like

c:extract value where value..widgets.group.text=2 from deck.cards

(Note that if a 'group' field doesn't exist it will behave the same as a card in group "0"; you probably want to count from 1 for your groups)

Given that list, you can pick a random item and navigate to some card like so:

go[random[c]]

Or, all at once,

go[random[extract value where value..widgets.group.text=2 from deck.cards]]

Does that make sense?

(+1)

Yes! Thank you.

(+1)

Is it possible to hide a column in a grid? I find myself having to use a lot of hidden grids and then selecting a subset of the columns into a visible grid. Which is fine enough, but I wonder if I'm misunderstanding the scope of variables or features of grids and maybe there's a way to not do this.

Developer

You can adjust the widths of the columns of a grid to hide trailing columns. In "Interact" mode, a small draggable handle appears between column headers:


You can reset the columns to their default uniform spacing with the "Reset Widths" button in grid properties.

Manually resizing column widths enforces a minimum size. You can set column widths to 0 programmatically via "grid.widths", but a 0-width column looks a bit odd; I'll make a note to fix that in the next release.

(+1)

Somehow I missed the grid.widths value in the grid interface. Thanks!

Developer

FYI i've patched the problem with 0-width columns in grids; that should now offer a fairly flexible option for visually suppressing columns without physically removing them from the underlying table. You can try it out now at the bleeding-edge source revision, and the fix will be incorporated into the v1.41 release; probably next week.

I'm having a hard time wrapping my head around arrays, maybe it's not what I actually need to be using. Basically I have two fields that I can enter text and I want to take each field and append them to an array that splits it all up by word. So "This is my text"  in field1 and "More text" in field2 would be ["This", "is", "my", "text", "More", "text"] that I could then manipulate.

Developer

Starting from the two fields you describe:

You can obtain the text of either field through its ".text" attribute. The "split" operator breaks a string on the right at instances of the string on the left and produces a list. Splitting one string on spaces gets us part of the way to what you're asking for. We can then use the comma operator to join a pair of lists.

" " split field1.text

The best way to experiment with this sort of thing is to use The Listener. Ask a "question", get an answer:

Another approach for gathering space-separated words from several fields would be to use an "each" loop:

Does that help point you in the right direction?

(+1)

This does! When looking at the docs I guess this made me think "split" and such were tied specifically to tables. But now I'm starting to wrap my head around this.

Developer (1 edit)

In general, for string manipulation the main tools Lil provides are:

  • drop, take, split, and parse for cutting strings apart into smaller pieces
  • fuse and format for gluing pieces together to make strings
  • like, in, <, >, and = for comparing and searching strings

...and a few of the more complicated utility functions functions in rtext do also apply to plain strings.

I may not understand fully how random works.

Say I have a table with 5 rows stored in 'temp'

random[temp,1] will usually get me a row with all the data, But sometimes it just results in the integer 1.


Why is that?
Developer

The Lil "comma" operator forms a list by combining the elements of its left and right arguments.

If you use this operator to combine a table and a number, the table will be coerced to its list interpretation (a list of the rows of the table, each a dictionary), and then combined with the number 1 (whose only element is itself), forming a list of several dictionaries and the number 1. Applied to such a list, random[] will occasionally choose the 1.

When you call a Lil function with multiple arguments, commas should not be placed between arguments. You probably meant

random[temp 1]

 Instead of

random[temp,1]

Furthermore, note that if you specify 1 as a second argument to random[] you will get a length-1 list as a result, whereas if you call random[] with only a single argument you will get a single value.

In preparing this post I have also observed that there is some inconsistency between native-decker and web-decker with respect to applying random[] to table values, which may have compounded the confusion; I'll have this fixed in the v1.41 release tomorrow. In the meantime the alternative is to explicitly crack the table into rows before making a random selection, like so:

random[(rows temp)]
(+1)

Thank you!

(+1)

Does random use a fixed seed? When I repeatedly run a lil script in lilt, random[range 15] returns 4 every time.

Developer

Lilt uses a fixed seed by default; this is a design decision inherited from K.

One simple way to randomize it would be something like

sys.seed:sys.ms

Note that Decker automatically randomizes the RNG seed at startup.

(+1)

Cool. Thanks!

What’s the best way to filter a list based on some predicate?

I was able to use “extract value where … from somelist” for some basic arithmetic, but when I throw a function into the predicate I get unexpected results (“value < f[value]” always seems to be true even though it definitely isn’t).

I’m wondering if I’ve misunderstood the “where” clause and it is only supposed to be used in table columns or something.

Developer(+1)

In the context of query clauses, column names refer to the entire column as a list. The "where" clause expects an expression which yields a list of boolean values. Arithmetic operators like =, <, and + conform over list-list and list-scalar arguments.

Depending on how a predicate is written, it might naturally generalize to operating on lists for the same reason. For example: 

on iseven x do 0=2%x end
iseven[5]
# 0
iseven[11,22,33]
# (0,1,0)
extract value where iseven[value] from 11,24,3,8
# (24,8)

If a predicate is only designed to operate on a single scalar value at a time, you can use the "@" operator to apply it to each element of a column, like so:

on seconde x do x[1]="e" end
extract value where seconde@value from "Lemon","Lime","Soda","Demon"
# ("Lemon","Demon")

This shorthand is semantically equivalent to

extract value where each v in value seconde[v] end from "Lemon","Lime","Soda","Demon"

(And of course in this particular case the "like" operator would be simpler:)

extract value where value like ".e*" from "Lemon","Lime","Soda","Demon"

Does that clear things up?

(+1)

Thanks! That does explain why it seemed to work sometimes and not others. I will give it another try. For the record, It looks like my skimming skills failed me, because I now see where this is explicitly noted in the docs:

When computing columns, you're working with lists of elements, and taking advantage of the fact that primitives like < and + automatically "spread" to lists. When performing comparisons, be sure to use = rather than ~! If you want to call your own functions- say, to average within a grouped column- write them to accept a list

It even calls out “where” in the next paragraph.

(+1)

Hi! I've been having a fun time messing around in Decker, and am now attempting something more game-y.

Specifically, I'd like to know if these are possible to do:

  • When Button X is clicked, have Button Y on a different card disappear/become hidden
  • When Button Z is clicked, unlock new dialogue on a different card (with the Dialogizer module)
I'm assuming it would be something like, "on click do: Button X = true"—but I'm not sure exactly what terms to use, so I would appreciate any help. Thanks!
Developer(+1)

Widgets have an attribute called "show" which controls their visibility; this can be "solid" (the default), "invert" (an alternate color-scheme), "transparent", or "none".

Suppose the button X is on card C1 and the button Y is on card C2.

You could give X a script for toggling Y's visibility:

on click do
 C2.widgets.Y.toggle["solid"]
end

Or a simpler version that just makes Y visible:

on click do
 C2.widgets.Y.show:"solid"
end

There are several other examples of doing this sort of thing in this thread.

To make clicking a button "unlock" dialogue or behavior elsewhere in the deck, you'll need to remember that the button has been clicked, and consult that record at a later time.

Checkboxes are just a special visual appearance for a button, so every button widget has a "value" attribute that can store a single boolean (0 or 1) value. Thus, we can use the button itself to keep track of whether it's been clicked. Suppose you've given the button Z on card C1 a script like so:

on click do
 me.value:1
end

A script on another card could reset Z's value,

C1.widgets.Z.value:0

Or test its value in a conditional:

if C1.widgets.Z.value
  # do something special
end

If you have lots of "flags" like this, it may be a good idea to centralize them in some kind of "backstage" card so you can keep track of them easily, and perhaps to give yourself a script for resetting the state of the deck.

Does that make sense?

(+1)

Makes sense! Thank you for the detailed walkthrough, that was all very helpful :)

is it possible to have something special unlocked only when two buttons are checked at once?🤔...

Developer(+1)

That would be a logical "and", produced with the & operator:

if C1.widgets.Z.value & C1.widgets.W.value
 # ...
end

hey, I'm completely new to lil and decker and I can't crack the random command. I want to make a widget that sends me to a random card from a selection of say ten cards. is it even possible? I feel like it should be, but I just end up sending myself off to the home card. 

Developer

The "random[]" function can be called in several different ways to produce different kinds of random values. In your case, you want to select a random value from a list of possibilities and then supply that value to the "go[]" function.

The "go[]" function can navigate to cards by index (a number), by name (a string), or by value (a Card interface). We'll go with the latter. Within a script, all the cards of the deck are available as variables of the same name. Commas (,) between values are used to form a list. If we have cards named "cardA", "cardB", and "cardC", and we wish to navigate to one of those cards randomly when a button is clicked, we could give it a script like:

on click do
 go[random[cardA,cardB,cardC]]
end

Does that help?

You might also find some of the examples in this tutorial illustrative: /t/3593043/make-your-own-chicken-generator

(+1)

I'm trying to figure out format strings, specifically to get a slider to show its max value. Is %v what I want, and if so how do I use it? Or is this even possible without additional scripting?

Developer (2 edits) (+1)

You can find documentation for format strings in Lil, The Formatting Language.

The format string of a slider widget is only given its value, which would usually be displayed as an integer (%i) or a floating-point number (%f); the rest of the string could, for example, provide units, like "%f degrees". In this way you *could* hardcode a maximum into the format string, like "%i/20" for an integer between 1 and 20 to be displayed like "7/20".

Extending the current behavior of sliders to make min/max and possibly other attributes of the widget available for formatting could be an interesting feature; I'll mull it over. For now, including that sort of information would require scripting. If you need this functionality in more than one place, perhaps you could use The Enum Contraption as a starting point?

(+1)

Okay, thanks. The description of the "v" pattern type in the Lil docs made me think I could maybe insert any variable using just format strings. It's not too bad to just hardcode it and update it with a script whenever I change the max, though.

Hi there, I noticed an odd behaviour, not sure if it has been flagged before. It relates to having a button widget with a script. If the button already has a script, and you go to the Action area to add a sound or pick a card etc. it overwrites the old script with the new action instead of just adding it into any existing script. Possibly there are good reasons for that, but thought I'd point it out just in case!

Developer

When you open the "Action..." dialog, Decker will attempt to "unpack" any script already attached to the button and reflect it in the settings you see in that dialog, and when you confirm it writes an entirely new script. This dialog exists purely as a convenience for composing simple scripts without writing code, and is not intended to manipulate or append to arbitrary user-generated scripts.

(+1)

Makes sense, thank you!

(1 edit)

I think I've seen somewhere that it is possible to build a personal website using Decker as the "frontend".  So for example, I could have a GitHub Pages repo with the Web Decker HTML file as index.html and a data file (e.g. a CSV at first) to have a certain degree of decoupling between the data and the app. Is it possible and if so, how can I programmatically (in Lil, e.g. when the main deck loads or when a particular button is pressed) import an external CSV file in the Web-based Decker so I can display it as a table (for a start)?

I hope that my problem is clear and thank you.

Developer

It is not possible for an unmodified copy of web-decker to programmatically fetch external files hosted e.g. somewhere on github pages, make http requests, etc. Doing this sort of thing would require adding custom javascript extensions to web-decker. An example of how such an extension might be written can be found in this subthread.

In general, decks should be self-contained objects pre-packed with any data they require to operate. A deck is a database, with grid widgets for storing tables and Lil for querying and manipulating them.

Lilt can be used to import or export data to or from a .deck or .html file in an automated fashion. If you insist on storing some dataset independently from a deck that uses it, it might be possible to use Lilt as part of a continuous integration pipeline or "build script" to bake out an updated web-decker build when an associated csv file is changed.

(+1)

Is it possible to render text and widgets in a color other than black?

Developer(+2)

Many widgets will render in white-on-black instead of black-on-white if you set them to "Show Inverted".

If you set widgets to "Show Transparent" you can draw underneath them and have it show through, and thus provide background colors or patterns. The same trick is also handy for making buttons that appear to have an icon instead of text: draw the icon underneath!

Canvases can be drawn on in any color or pattern; you can use these directly or within Contraptions to make colorful variations on normal widgets. The fancy button contraptions I made recently can be configured with color images.

Finally, you can customize Decker's palette, substituting some different color globally for white and/or black.

(3 edits)

hey ij!

is there a way to write a single line of command to copy and paste more than one widget from one card to another?

i have widgets X, Y and Z stored in card A, and so far i can import each of them separately to card B by writing

card.add[deck.cards.A.widgets.X]
card.add[deck.cards.A.widgets.Y] 
card.add[deck.cards.A.widgets.Z]

but i can't really nail a way to import all three of them with a single line (unless i call all three lines with an .eval[]).

i saw in the decker manual that you can use the .add[] command to import a list or dictionary of widgets from another card, but i don't see how.

thank you!

(+4)

Hi, I'm not IJ but I did some experimentation and I think I've figured it out - it seems the card.copy and card.paste commands let you copy multiple widgets at once.

So you'd do like this:

card.paste[A.copy[A.widgets.X,A.widgets.Y,A.widgets.Z]]

(As a side note, if you're referring to a card in a script you can just use the card's name, you don't need the deck.cards in front of it)

Let me know if this works for you!

(+1)

oooooooooo!!! thank you so much, millie! i'll try as soon as i can!

(+1)

worked like a charm <3 thank you once again!

Developer(+4)

Just to build on this, if the only widgets on card A are X, Y, and Z, you can copy them all with:

A.copy[A.widgets]

And here's one other slightly more concise way to select a bunch of widgets by name:

A.copy[A.widgets @ "X","Y","Z"]
(+1)

i learned so much today!

i think i used "on view" scripts on too many widgets, and now my deck is kinda sluggish. are there lighter ways to make widgets receive information from other widgets without having them wait for signals on every frame?

for example, since i'm building a clicker game, i use on view scripts to keep information flowing between cards. things such as updating numbers and detecting clicks. 

is it lighter to make one widget be the animated one running all the code, or to make many widgets animated running smaller bits of code?

Developer(+1)

There would be somewhat less overhead to having a single animated "pump" which is responsible for updating everything else on a card.

Have you tried enabling the script profiler (Decker -> Script Profiler) to confirm that it's scripts which are slowing things down? Having a large number of widgets shown at any given time (or particularly large canvases) can also start to stack up.

If you're updating large numbers of widgets individually- like lots of separate fields displaying stats- you might find that it's more efficient to replace them with multi-line rich-text fields or grid widgets, both of which can be useful for displaying formatted bulk data. There's no hard-and-fast rule about the best way to approach things; you may need to experiment. If you find any particular operation which seems unusually slow, and you can provide me with a minimized example, I can investigate and possibly improve Decker's performance.

Hey there! I've been redoing The Steppe code, following your suggestions on cohost, but I made a minor modification that seemed to have broken something.

So, there was an invisible field "counter" that would have its numeric text altered according to what card you came from, starting from 1. Then, there was a screen-sized invisible button that would take you to another card based on a giant "if... elseif" code. Your suggestion to simplify it would be to use lists. This was the example given:

cards:(card2,card3,card4,card5,card6,card7,card8)
trans:("n/a","WipeUp","Dissolve","Dissolve","Wink","Dissolve","CircleIn")
go[cards[counter.text-1] trans[counter.text-1]]

It was working well, but then I thought "maybe I could make the counter start from 0, instead of 1, so it would align with the list index on the 'go' and I can remove the -1". So I rewrote all the code for counter to go from 0 to 7 instead 1 to 8, and changed the "[counter.text-1]" to just "[counter.text]".  Except now the button doesn't work properly, it just goes back to the home screen no matter the text in the field counter.

However, if put a +0, it works again. So, right now, it's like this:

cards:(card2,card3,card4,card5,card6,card7,card8) 
trans:("n/a","WipeUp","Dissolve","Dissolve","Wink","Dissolve","CircleIn") 
go[cards[counter.text+0] trans[counter.text+0]]

What I want to know is... am I doing something wrong? Is there another way to use counter.text as an index that I'm missing? I've been messing around with it for quite a while, but can't seem to solve this. 

Developer

The .text attribute of a Field is a string. Performing any sort of arithmetic operation on a string coerces it to a number (as a convenience), and in many places a string like "23" is fully interchangeable with the number 23:

 100+"23"    # 123

Unfortunately, indexing into lists isn't one of those places:

 foo:"Alpha","Beta","Gamma"
 foo[1]      # "Beta"
 foo["1"]    # 0
 foo[0+"1"]  # "Beta"

Part of the reason Lil draws a hard line here is that indexing lists by strings is one way to force them to "promote" to dictionaries when you assign through them; trying to parse strings into numbers could lead to some very nasty ambiguity:

 foo["z"]:"Delta"    # {0:"Alpha",1:"Beta",2:"Gamma","z":"Delta"}

I apologize for the confusion stemming from my suggestions.

One possible alternative would be to make "counter" a Slider widget instead of a Field; The value of a Slider is always a number.

(+1)

Ah, don't worry, you have nothing to apologize for! I thought this could be the case, but that might have had another workaround I wasn't figuring it out.

The code works perfectly now, so I'll keep it as-is with the +0 and write a small note that field.text is always a string, so I don't forget. Thanks for the help!

(1 edit)

hey, ij and fellow deckheads! 

i've been using the rect module to detect the cursor hovering over buttons and having a field widget display information on that button. so far i can only do this by having every button being animated and having a rect.overlaps[pointer me] command. 

what i really wish i could do was having the rect module detect the widget type. like rect.overlaps[pointer <button>] (this doesn't work) and then specify the button by its text. 

is it feasible?

thank you!

Developer (2 edits)

The rect module (which, for those unfamiliar, is included in the "All About Draggable" example deck) includes functions like rect.overlaps[] and rect.inside[] for manipulating "rectangles", which can either be a dictionary containing pairs with the keys "pos" and "size" or any Decker interface value that happens to have those fields- widgets, for example.

The pointer interface has a .pos field, but no .size field. Using an invalid index into an interface type returns 0, so the pointer interface kinda fulfills the contract and sort of works as an argument to these utility functions (as if it were a rectangle of size 0), if only by coincidence/accident.

I whipped up a little test, and sure enough this seems to work fine given an animated button:

on view do
 field1.toggle["solid" rect.inside[pointer button1]]
end


(Note that "tooltips" like this won't work properly on multitouch devices, since such input devices do not update the pointer position while a user's finger happens to be hovering above the display; this is why Decker doesn't have any sort of tooltip functionality built in.)

The same script body ought to work just fine from a centralized event pump rather than having every object with a tooltip be individually animated. I don't really follow what you mean in terms of the rect module "detecting the widget type".

thank you for the answer! this already opens up a lot of possibilities, actually.

what i meant was if there was a way of having, for example, an animated field widget that displayed text whenever the pointer went over a button. and i figured the way to do this was such field having something like:

on view do
 if rect.overlaps[pointer (((any button)))]
  me.text:"pointer over some button"
 else
  me.text:"pointer over any other thing"
 end

(it just occurred to me that i can name a group of widgets that are buttons and do this, but i'm thinking of a less manual approach)

(1 edit)

So, I'm trying to add import options to the image importer/exporter contraption I'm building. So far, this is the interface and everything seems to be working fine. "Extra Options" just makes everything disappear, keeping only itself and the Import/Export buttons.


Only one of the checkbox buttons can be selected at a time (I'm using a basic "if" to check the value of each one and unmark the other 2 if is true).

Here's how the images look when imported in the order of the checkboxes.




So, erm, I think the issue is clear. The Gray Import isn't importing in grays, but rather in a psychedelic way.  Funny enough, the Dither Import relies on the Gray Import to use transformation, otherwise it just completely breaks too. But even so, the Dither result is noisier than just dragging and dropping an image into Decker.

It's worth noting the image is a jpeg, so I'm not sure why it's getting animated with the Gray Import.

Here's the code in the Import button:

on click do
    if colorbutton.value=1
        i:read["image"]
        card.image.paste[i 0,0,card.size]
    end
    if graybutton.value=1
        i:read["image" "gray"]
        card.image.paste[i 0,0,card.size]
    end
    
    if ditherbutton.value=1
        i:read["image" "gray"]
        i.transform["dither"]
        card.image.paste[i 0,0,card.size]
    end
end

I tested it with a canvas, and also did some testing in the Listener, but I can't figure out what's going on, if there should be some other sort of conversion happening before, or something like that.

Developer

This is working as designed. 256-gray images are not directly displayable within Decker, since Decker's color palette does not contain 256 colors and patterns; only 48:

 

A grayscale image must be converted into a proper paletted image before it can be displayed; otherwise the grayscale values are effectively randomly mapped to entries in the above table, and any higher indices appear as white. The image.transform["dither"] function is one way to produce a 1-bit dithered image from a 256-gray image, using Bill Atkinson's algorithm. Rescaling a dithered image will considerably reduce its quality. The correct order of operations to prepare a dithered image therefore must be:

  1. obtain or otherwise create a 256-gray image.
  2. perform any desired palette adjustments to the 256-gray image, like adjusting white/black points or contrast.
  3. scale and crop the 256-gray image to the desired final size.
  4. dither the 256-gray image, resulting in an image consisting exclusively of patterns 0/1.
(4 edits)

I was talking about this on cohost and millie also told me about Decker not being able to display the 256 grays which... makes complete sense tbh, as you yourself explained the palette limitation (which I actually know but didn't connect the dots, so I'm a bit embarrassed). Funny enough people liked the result, so I think I'll rename the option and leave it there for them to use and give life to fever dreams. 

And the order for the dithered image makes sense now, I'll rewrite its import code and see if I can get it right then. Thanks a lot!

Edit: the dithering improved a lot now!

Still on the same contraption as before, I'm having trouble finding a solution for a thing that might be beyond what I understand at the moment: paste the background of a contraption into the card's background without having to use the Listener or create a widget button in the card.

What I mean is, I can copy and paste into the card the image that was imported into the contraption with the following code, for example:

importer.image.paste[importer.widgets.Importer1.image.copy[]]

Where "importer" is the card name and "Importer1" is the name of the contraption. I also use some variations, depending if I'm in the same card as the contraption or not. However, having to rewrite this by changing the card's name every time isn't that practical, so I wanted to make the contraption itself paste its image on the card it's over (kinda like a "stamp"). But, from inside the contraption, I can't seem to get the image to be pasted anywhere else.

I tried messing around with the attributes, but that doesn't seem useful in this situation since no widget is trying to access or modify the contraption's content. Making a script with the generic "card." followed by the rest doesn't work, I guess because contraptions work like cards themselves from what I understood, so the command is ambiguous? I tried using a canvas too, instead of the contraption's background, thinking it would be easier to access, but it also didn't work.

So, am I overlooking something obvious? Or to do what I want, it requires Lil's more complex stuff to deal with prototypes/contraptions also being "cards"?

Developer

From inside a contraption instance, "card" refers to the contraption instance itself; this is handy if you want to send events to the "external" scripts on the contraption or inspect default properties like .locked, .show, or .font.

If you want to refer to the card within which a contraption resides, you can generally use "deck.card". Strictly speaking, "deck.card" is the active card on the deck; the card the user is looking at. This will only be distinct from the contraption's parent card if the contraption is being sent a synthetic event from some external script.

A different angle to consider would be prompting the user for a destination card when importing an image. You could, for example, use alert[] in "choose" mode to select cards from the deck by name, using the current card as a default:

alert["pick a destination card:" "choose" deck.cards deck.card.name]


The downside to the above is that if a user hasn't given cards logical names they're "picking blind", which can be error prone. Every design problem is fractal in nature...

Using "deck.card" worked, hooray! The contraption is now working as intended with all the features I wanted, I'll just do some testing in the next few days and upload it to the jam.

I decided to avoid the "alert" route because, at least for my usage, I need it to just behave like a "stamp", copying the contraption background (which uses Decker full screen) and pasting it exactly like it's shown in the card below. Then one can delete the contraption and work straight on top of the "stamped" image with other widgets, including invisible ones. And I figured being pasted into the background allows image manipulation/editing/painting too.

Now, this whole thing led me to 2 other questions:

 - I'm using this code in a button to paste the contraption background into the card:

deck.card.image.paste[deck.card.widgets.deckstamp1.image.copy[]]

Is there a way to make the "deckstamp1" be a string pulled straight out of the contraption's own name field? This way, the script would always "autocomplete" and the button wouldn't stop working if someone changed the contraption name, for example. I did some testing with various syntaxes, but as always, not sure if I'm doing something wrong or if it's not possible.

- Is there a way to access a contrast adjustment, like the one with "j" and "k" that works only after dragging an image into Decker? I looked around and didn't find anything. I figured that if there is, it would be cool to have a contrast slider and a button to update the image, even if it works just with the dithered import.

(+1)

I'm just starting with decker, and I feel like my question is absolutely basic and stupid, but I swear I've been digging at the documentation and examples and can't find the issue.
I have a button on a card that has the following script:

on click do
 key: 1
 go[bednokey]
end

The idea being that you pick up the key and it leads you to an identical card of the same location with no key.

On a previous card, I have the following script on a button, to avoid going to the card with the key once it's been picked up already:

on click do
 if key=0
  go["fieldbed" "SlideUp"]
 else
  go["fieldbednokey" "SlideUp"]
 end
end

And it won't work at all. It always goes to the card with the key. I tried reversing the conditions, using other symbols, no dice. What's the proper way to do this check?

Developer(+1)

Anything that you want to "remember" across event handlers needs to be stored in a widget. A true/false flag, for example, could be stored in a hidden checkbox. If we had a card named "flags" with a checkbox widget named "hasKey" your scripts might look something like

on click do
 flags.widgets.hasKey.value:1
 go[bednokey]
end
...
on click do
 if flags.widgets.hasKey.value
  go[bednokey "SlideUp"]
 else
  go[bed "SlideUp"]
 end
end

If the widget happens to be on the same card as the script which references it you can shorten paths like "flags.widgets.hasKey.value" to just "hasKey.value".

If you want to show or hide objects on a card, you may find it more flexible to use a transparent Canvas widget containing an image of the key. You can show, hide, or reposition canvases at will, sort of like a sprite object:

myCanvas.show:"solid"
myCanvas.show:"transparent" 
myCanvas.show:"none"
myCanvas.toggle["solid" booleanExpression]
myCanvas.pos:otherWidget.pos

This may also remove the need for a separate "flag" widget; the canvas itself will remember its visibility setting:

if bed.widgets.keyCanvas.show~"none"
 # ...
end

Does that help answer your question? There are lots of other examples of doing this sort of thing in this thread and elsewhere on the forum.

(+1)

This absolutely goes above and beyond answering my question, thanks! I'll try all these out right away.

Viewing posts 41 to 60 of 132 · Next page · Previous page · First page · Last page