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: 25,330 Replies: 405
Viewing posts 121 to 126 of 126 · Previous page · First page
(1 edit)

I want to use a slider in X card to copy # canvas image in Y then paste it in X canvas. Here's the code:

on change val do
   if me.value = #
      X.paste[deck.Y.widget.#.copy[]]
   end
end

But it doesn't work when I chage the slider value. Am I doing something wrong?

Developer

"#" is not a valid Lil identifier; it is used in Lil scripts to indicate a comment, which ignores the remainder of the line. Lil identifiers are described in the Lil Reference Manual as follows:

Variable and function names may contain any alphanumeric characters (as well as ? and _), but must not start with a digit. 

If you give a widget a name which is not a valid identifier, it will not be automatically available as a local variable, but it can be accessed by name from the card's ".widgets" dictionary:

card.widgets["#"]

Your description of what you're trying to do is inconsistent and unclear. If the idea is to- for example- index into images stored in a rich-text field named Y and paste the image corresponding to the value of the slider ("me") onto a canvas named X, you could use something like:

on change val do
 X.paste[Y.images[val]]
end
(1 edit)

I'm using a slider to switch between images that I want to copy from one set of canvases into a single canvas. I'm not using a ritch text field.

Developer (1 edit)

Presuming the canvases are on the same card and have a naming convention like "c1", "c2", "c3", "c4" and the slider is set to an integer range between 0 and 3 you could write something like

on change val do
 canvases:c1,c2,c3,c4
 X.paste[canvases[val].copy[]]
end

I ended up using a field anyways, lol.

That said, I got a new question, how do I script a button to add or subtract from the existing value of the slider?

Developer(+1)

Presuming a slider named "slider1", you could give a button a script like

on click do
 slider1.value:slider1.value + 1
end

This situation is very similar to one of the examples in The Decker Guided Tour and one of the examples in the introductory primer in the Lil Reference Manual.

(+1)

Thank you.

on click do
 slider1.value:slider1.value - 1
 slider1.event.change[val]
end

I tried using this code to change the value of the slider and execute this script:

on change val do
 Sphere.paste[Assets.images[val]]
 if me.value = 0
    button1.show:"solid"
    button2.show:"solid"
 else
    button1.show:"none"
    button2.show:"none"
 end
end

There is a range from 0 to 4 for the images in a field going down. But, for some reason, the 0th image gets pasted and not the third in the field.

I want it to paste the images in the order of values in the slider with each click and not skip to zero.

(+2)

I think you need to send the event to slider1 in a slightly different way:

slider1.event["change" val]

There's another post on the forums explaining more here.

And you'll also need to define what val is in this context. That could be in either script.

For now I put both changes in button script:

on click do
 slider1.value:slider1.value - 1
 val: slider1.value
 slider1.event["change" val]
end
(+1)

Thank you!

I'm trying to make it so that in my current project of a little visual novel, that if you aren't comfortable with specific content, it boots your back to the 1st card, and if you're okay with said content, it moves to the third page. I have it set up as a boolean, but there may be better ways to go about it, any help I can get with this?

adult_ok:true
on view do
 dd.open[deck]
 dd.say["This game may contain adult themes not suitable for all audiences"]
 r:dd.ask[
  "If you're okay with these terms, proceed forward:"
  ("YES", "NO")
 ]
 if r~0
  adult_ok:true
  dd.say["Then, the Contract has been Sealed."]
 else r~1
  adult_ok:false
  dd.say["Then, the World was covered in Darkness."]
 end
 dd.close[]
end
# later in the game, after the dialog
if not adult_ok
 go["home"]
else
 # continue game normally
end
(+1)

The basic logic you have there is sound, but I can spot a few problems that are likely to trip you up.

The most basic is, Decker doesn’t have true and false constants - those are just variable names and are nil by default, so if true alert["hello"] end will never show an alert, unless you happen to have defined true:1 somewhere else. Where you would write true and false, just change them to 1 and 0 respectively.

The next problem you’re likely to hit is that the value of the adult_ok variable is not preserved between events. If you want to store that value somewhere, you need to store it in something - in this case, probably a button with the “Checkbox” appearance on a card somewhere. If you don’t already have a card to store the state of the game, you can make a new one called, say “gamestate”, put a button named adult_ok on it, give it the “Checkbox” appearance, and then in your code you can do:

gamestate.widgets.adult_ok.value:alert["Are you OK with seeing adult content?" "bool" "Yes"]

…to ask the user and store the resurt in gamestate.widgets.adult_ok.value. Then you can later check it:

if gamestate.widgets.adult_ok.value
 go["adultcontent"]
else
 go["nextmorning"]
end

Of course, that’s assuming you actually want to store the answer and adjust the game accordingly. If you just want to make a disclaimer and only proceed to the actual game if the player clicks “yes”, then you don’t actually need to store that anywhere: if the player winds up anywhere but the first two cards, you can assume they must have clicked “yes” at some point in the past. Then you can just write:

if alert["Are you OK with seeing adult content?" "bool" "Yes"]
 go["thesagabegins"]
else
 go["titlescreen"]
end

…and never worry about it again.

(1 edit) (+1)

Are there in-built functions for reading arrays from image interfaces? I have an interest in adding a 'save as .png' and 'save as .cur' to my deck, minart, but I'm not sure where to start when it comes to image conversion. Is this something that should be done externally?

Developer (1 edit) (+2)

That's a rather expansive question!

Exporting GIF images with write[] and asking users to convert them to other image formats as desired will generally be the simplest approach. Decker natively supports GIF because it's a simple and universally-supported format that is also a good match for Decker's paletted-color model.

If you decide to dig deeper, the image interface has a .pixels attribute which, when read, will give you the pixel values of that image as a list of lists of numbers (a matrix).

These numbers will be Decker pattern indices, so you'd need to do some work to "flatten out" 1-bit patterns and animated patterns (if applicable) and then look up the corresponding RGB colors from Decker's active palette. The internals of the PDF module might be a useful reference.

In principle, you could use an Array interface to construct your own PNG encoder in pure Lil, but this could be a significant amount of work! The CUR format is a bit simpler than PNG and (so far as I'm aware) builds on BMP, which is also relatively straightforward. An encoder is, at least, quite a bit simpler than a decoder, since you can avoid implementing all the features and options you don't need for your intended application.

If you only care about PNG export from web builds of your tools, you could also consider writing a module that uses the danger zone to call some JavaScript from Lil and use ordinary web APIs to perform the conversion. See The Forbidden Library for examples of doing this kind of JS/Lil interop.

Does any of that point you in the right direction?

(+1)

This response gave me more than enough information to work off of - thank you! ^^ I'll most likely look into BMP first and see if I can move my way up from there.

(+2)

show[52 % 2] returns '2' instead of '0' - is that expected behavior for the modulo operation?

Developer (1 edit) (+2)

In Lil, the modulus is the left argument; the opposite order of many other programming languages:

range 15
# (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14)
2 % range 15
# (0,1,0,1,0,1,0,1,0,1,0,1,0,1,0)
(+1)

Im very confused as to how I am meant to do something like a basic inventory, or even a basic variable to keep track of progression?

Im going over the documentation and it feels like it's getting way too in depth with things way too quick, but I cant for the life of me figure that out?

So i assume i need to have a card at the beginning that has variables, so i tried setting some in the on-click of the "start" button i made for my game, but then i tried referencing it and it doesnt seem like it does anything?


is there a good example of something like this setup with more full context than the "primer" in the documentation? one that actually shows all of the relevant scripts, and where they need to go in order for this to work right?

(+2)

If you’re used to other programming languages, Decker is a bit unusual. In most languages, if you wanted to set up a score counter on-screen, you might do something like this:

# Executed at startup
score:0

# In some kind of button
on click do
 score:score+1
end

# Called to redraw the screen
on view do
 canvas.text[score 0,0]
end

This doesn’t work in Decker, because Lil variables do not persist. If you set up a variable inside a function, it’s forgotten when the function returns. If you set up a variable in the top-level of a script (as in the example above), it gets re-executed every time any event is triggered.

Instead, if you want to store state, you need to use widgets. Put a text-field on your card, name it score, position it where you want the score to be visible on-screen, lock it so that the player can’t just edit it. Then you can do:

# In the "New Game" button
on click do
 score.text:0
end

# In some kind of button
on click do
 score.text:score.text+1
end

Instead of the on-screen display being the result of some rendering and calculation, it’s The Actual Thing. If you want to have state that isn’t displayed to the player (things like “has the player opened the doorway hidden behind the bookcase”), you can make them “Show None”, or put them on an entirely different card (sometimes called backstage) that the player can’t get to, and then scripts on other cards can refer to backstage.widgets.score.text.

(+3)

Thank you so much, while I was able to eventually figure this out on my own, I genuinely feel like this little breakdown would have introduced me to the way of doing things in Lil a lot better than what I was able to find in the documentation myself


the specific vernacular of "(cardname).(widgets).(widgetName).text" in particular just completely eluded me in the documentation for some reason

(+3)

One thing that I also find useful for variables is to have one card for all your variables and to write this line of code on the script of your deck:

var:variables.widgets

That way, you don't have to write variables.widgets every time and simply write var.myvariable.value for exemple.

Viewing posts 121 to 126 of 126 · Previous page · First page