Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Screwtapello

57
Posts
3
Topics
9
Followers
7
Following
A member registered Oct 02, 2017 · View creator page →

Creator of

Recent community posts

(2 edits)

You left Decker running for 24.8 days?

EDIT: Wait, no, I see what’s going on.

Native Decker computes sys.ms as a float, Web Decker takes a float from the browser and truncates it into a 32-bit integer.

I guess it shouldn’t matter if you’re using sys.ms for performance timing (duration:sys.ms - start) but it does make problems if you’re trying to divide the clock with a modulus operator.

This was my first jam - it’s been really interesting playing with all the submissions, and encouraging to get such lovely comments on mine.

Thanks to everyone who participated!

This was lovely. Very simple, but it’s fun to explore a new place, and this definitely gave me nostalgia for Myst and games like it.

I like the palette! Very moody and retrospective.

This has been my first ever jam of any kind, and I was thinking about doing more of them, so reading about your experiences on card10 was interesting, and has given me something to think about. Thanks!

This is pretty cool! Obviously Decker is not designed for this kind of thing, but that only makes it more cool. :)

I couldn’t get the metronome or the one-voice synthesiser to work, but the tutorial cards and mouse-tracking and even the tone generator worked fine.

As a proof-of-concept, I wasn’t expecting much beyond the addition example on the first card, but you clearly went a lot further than that! Well done!

This is very cute! The sound effects help a lot - are the barks also courtesy of Buddy the Dog?

You’re right, that was pretty dark, but in a dark-humour kind of way. The name/gender screens in the introduction were a fun way to introduce the subject matter, and all the pictures of Deo were really well drawn.

I played enough times to get a picture with Deo, and now I feel like I’m an accomplice to some kind of crime.

I learned about frogs, chickens, and the Philippines today! Thank you! And your drawings are extremely cute.

Those feelings are a bit outside my experience, but you express them well. The crumpled blank paper aesthetic makes me feel isolation and emptiness, which I think is what you were going for.

That’s some fun abuse of Decker widgets. I was particularly impressed by the sliders-as-toggles on the last card!

I think on loop is checked when you visit a new card, so that the new card has a chance to stop the loop, or start a new one. For example, if one card represents the player standing beside a waterfall, it would be more atmospheric if a loop of waterfall noise played whenever that card was visible. When the player visits that card, the loop should start immediately (even if some other loop was already part-way through playing) and when the player leaves that card, the loop should stop immediately (even if the waterfall noise was part-way through). Calling on loop on card transitions makes that kind of effect possible.

If your two songs are less than 10 seconds in total, you could combine them into one sound and loop that quite easily.

If your two songs are more than 10 seconds long in total, you might add a “last loop started at” field on the same card as the counter that switches between them. When you start playing a sound, update the counter, and set the “last loop started at” field to sys.ms (the current time in milliseconds). When on loop is called, it passes in the old sound - if the “last loop started at” time, plus the duration of the old sound in milliseconds (old.duration*1000, since the duration is in seconds), is nearly equal to sys.ms, then we’re probably looping because we got to the end of the sound. If the start time + the duration is greater than sys.ms, then the loop has been called early, probably because of a card change. If you return the original sound, it will continue playing it, rather than restarting it.

This is pretty handy!

As a tip, since the YouTube URL is always based on the base URL, the ID, and the timestamp, instead of creating it at insert time and adding it as an extra column, you can create it when the user clicks on the grid. That way, you get extra space on-screen for the description column, and if you edit the timestamp, you don’t also have to edit the URL to make it “stick”.

Also, that is a very cool video to use as the default example. :)

I love all the era-appropriate clip-art! The contrast between the wholesome pictures and the cynical tone is fun.

That’s a nice collection of photos, and the dithering makes them just a bit more surreal. I particularly like the way you’ve filled some parts with Decker patterns - a creepy door with a sky filled with cute polka-dots behind it just adds to the creepiness.

One minor issue: on the final card, the “END” text isn’t locked, so you can select it and type over it; I assume that’s unintended.

I just played through the current version. It was fun, even if the setting was a bit gruesome.

When I started playing, it took me a while to figure out I could click on the person in the other cell; I didn’t recognise it as the silhouette of a person at first.

In the “guess the ages of the children” puzzle, I got a bit annoyed that one of the clues was apparently “on the wall behind me”, but I couldn’t find a way to turn around; I actually rewound the game back to the previous section looking at the desk to see if there was a number on the wall I couldn’t remember. Turns out there wasn’t, and even if there had been a way to get that clue it wouldn’t have helped - it’s not necessary to solve the puzzle. I feel like it’s a distraction to mention it at all. On the other hand, I really liked the final clue - it was a great “But why would.. ohhh!” moment.

I used two hints on “guess the occupation” and one hint on “guess the number of the safe”, but I made it through.

There’s a certain audacity in publishing a photo album as a series of low-resolution, dithered black-and-white images, and I really admire it. They look great!

I know a lot of Decker projects are just people trying to make a cool little thing, so I don’t expect a credit, but “Screen melt transitions by Screwtapello” would be nice.

Are you using a .deck file (which you have to load into a program running on your desktop or laptop) or a .html file (which you run in a web browser)?

If you are using a .deck file, you don’t need to replace it. You can replace the old Decker.exe with a new one downloaded from Itch, and it will be up-to-date.

If you are using a .html file in a web browser, it contains both your deck and a copy of Decker that runs in the browser. To update that version of Decker, you can:

  • go to https://beyondloom.com/decker/tour.html which always has the latest HTML version of Decker
  • from the File menu, choose “Open…”
  • you should be prompted for a deck to open; choose the deck you want to update
  • your deck should now be running in the updated Decker in the browser
  • from the File menu, choose “Save As…”
  • when asked, choose a filename that ends in .html and click Save
  • your browser should start downloading a file with the name you chose; it will be your deck wrapped in an updated version of Decker

Thanks!

When you assign a value to a name in an event handler, like this:

on view do
 p:1+2
end

…when Decker decides the thing is being viewed:

  • it calls the view event handler
  • it creates a new name p inside that event handler
  • it assigns the value 3 to p
  • the event handler ends
  • p vanishes along with it

If you have some other event handler somewhere else, like on click do ... end, that event handler does not have access to p, it can’t use the value. If you say p:2*3 in that event handler, it will have its own p that will also vanish when the event handler completes.

In the first code block in your comment, you have:

on view do   
p:"%p" parse "%e" format sys.now  utc_offset:1  
p.hour:24%utc_offset+p.hour  b:(p.hour)
me.text:"%f:" format b      
end

That creates a p with date-time information in it, it adjusts the hour part of that date time, it uses the p for some text formatting, and then the event handler ends and that p is lost.

In your second code-block, which I assume is from a button’s on click do ... event handler, you have:

...
p:"%p" parse "%e" format sys.now
...
if (p.hour=12)&(p.minute=13) 
...

Because that’s a separate event handler, that’s a separate and unrelated p, and its p.hour has not been modified. Every event handler where you want to use the modified time, you need to modify it again.

Also, a little further down:

...
elseif ((p.hour) <10) & ((p.hour) >20) 
...

I don’t think the hour can be less than ten and greater than 20. Perhaps you wanted to switch those around to be “greater than 10 and less than 20”?

Assuming that’s what you want, here’s a button that behaves that way (although it uses Decker’s built-in alert[] rather than the dd.say[] module):

%%WGT0{"w":[{"name":"timelock","type":"button","size":[95,20],"pos":[226,161],"script":"on click do\n p:\"%p\" parse \"%e\" format sys.now  utc_offset:1  \n p.hour:24%utc_offset+p.hour\n\n if ((p.hour) >10) & ((p.hour) <20)\n  alert[\"###ACCES AUTORISE ENTRE 20H ET 10H###\"]\n else\n  alert[\"###ACCES INTERDIT ENTRE 10H ET 20H###\"]\n end\nend","text":"Attempt Unlock"}],"d":{}}

Copy that text to the clipboard, then in Decker you should be able to switch to the widget-editing mode and use Edit → Paste Widgets to add the button to the current card, where you can poke at it.

I was having a rough day yesterday, and having something so beautiful and cheerful and playful to look through absolutely brightened my day!

I did find some minor problems:

On the card “lockeddecks”, the label “How to lock a deck” is editable, and I think it shouldn’t be?

On the card “gridscale”, it says Decker’s Fat Bits mode was named after “a program that magnified the screen on classic Macs”, but it links to a program for OS/2, not for classic Macs, and the program came out six years after MacPaint was released with a Fat Bits mode.

I think the real reason Decker has a “Fat Bits” mode is because somebody somewhere had the experience of using HyperCard (or MacPaint), seeing “Fat Bits” mode in a menu, enabling it out of curiosity, and then (after a moment’s confusion) realising it was a super-power for making even better art. “Zoom” is a thing you find in professional software like Microsoft Word and Photoshop, “Fat Bits” is playful discovery and better suited to Decker.

It’s hard to squeeze all that into a little “why is zoom called fat bits” aside, though. :/

Still, this is an amazing resource. There was a lot of stuff in there I didn’t already know (especially about the art side of things) and probably things I didn’t know I needed yet - but at least now I can look them up easily. I will definitely be showing it to people who want to know about Decker!

As somebody coming from a Python background, it’s taking me a while to adjust to making the most use of Decker’s strengths. So far, I’ve found the “Cards are Workbenches” to be the most empowering thing - where in Python I might write a suite of unit-tests, in Decker I can drop down some sliders and a canvas, wire them up, and see the thing I’m working on updating at 60fps. And once I’ve gotten the thing to work the way I want, other cards can just read the values of those sliders.

I discovered a bunch of things from that post, including:

  • making a button transparent, and then drawing a custom icon behind it
  • there’s a navigation history so that go["Back"] always does the right thing
  • the correspondence between foo.key and foo["key"] is not just for dicts (as in JavaScript) but you can also do card.event.reset instead of card.event["reset"] to invoke an event handler
  • I had thought about “cards as objects”, but didn’t realise it could be so ergonomic to use them that way; the link between cards and contraptions seems even stronger

Thanks for writing it!

I love the intro animation where the letters teleport in, Mega Man style. Very cool!

You’re almost there, but unfortunately Decker doesn’t allow you to add a pressed attribute to a button like that. If you want to keep track of a flag like “treasure taken”, the easiest thing would be to make a button in the puzzle-room called treasuretaken, configure it to be a checkbox, and “Show None”. Then the button that takes the treasure can do:

on click do
 treasuretaken.value:1
end

(note that you have to say 1, not true: Decker’s scripting language Lil does not recognise true and false specially, and treats them both as undefined variables)

…and the button that checks for taken treasures can do:

on click do
if puzzleroom1.treasuretaken.value & puzzleroom2.treasuretaken.value
 dd.open[deck]
 dd.say["You successfully stolen all treasures!"]
 dd.close[]
 go["end"]
else
 alert["You must collect all treasures to leave!"]
end
end

(note that the way to say “both these things must be true” is & not and - Lil does not recognise and either)

Ah, here’s what I see:

  • when I start the game, no sound
  • when I click on the background, the background loop plays once
  • when I click on the “next” button, there’s still no background music
  • if I press the left-arrow key on the keyboard to go back to the first card, the background loop begins playing, and loops properly

From the documentation, under Web-Decker and Native-Decker:

Most web browsers do not allow programs to play audio until the user has interacted with a page, so any play[] commands issued before a user has clicked, tapped, or pressed a keyboard key will have no effect.

I think this is what you’re bumping into, since your deck tries to play audio when the first card appears. The simplest workaround would be to also start looping the sound on the second card, so that whether somebody’s using Web Decker or Native Decker, they get the background loop eventually. A more complex solution would be to add a pre-title card that the user has to click through to get to the title card.

Does looping work for you in the official All About Sound deck? In my browser (Firefox on Linux) I can click “Start Loop” and it runs for at least 11 loops (that’s when I got bored).

What browser are you using, on what platform?

How long is the sound that you’re looping?

How long does it pause for?

(1 edit)

When you use go[] with a transition, the transition animation needs two Images to animate between, so it sends the view[] event to the target card to see what it’s going to look like. Then, when the transition is complete and the new card is visible, it gets another “view” event like normal.

So no, you’re not doing something wrong, that’s just how Decker works.

If you’re struggling to get the solutions in that other thread working, here’s another alternative: by default, a transition takes 30 frames (half a second), so if view gets called twice within the same second, it’s probably because of a transition, and we can ignore the second one.

If you put a field named lastview on your card, you can use it to keep track of the last time view was called, like this:

on view do
 # If the current frame is more than
 # 60 frames (one second) since
 # the last time view[] was called,
 # call realview[].
 if sys.frame > lastview.data + 60
  realview[]
 end

 # Log that view[] was called
 show["viewed" card.name]

 # Update our records for next time
 lastview.data:sys.frame
end

on realview do
 show["real view"]
end

You should make the lastview field invisible and locked so that players don’t accidentally mess with it.

If you go to this card without a transition, in the Listener you should see the log messages:

"real view"
"viewed" card1

If you go to this card with a transition, you should see the log messages:

"real view"
"viewed" card1
"viewed" card1

realview[] was called for the first view, but the second view happened so soon afterwards, that it skipped calling realview[] the second time.

Ah, yeah. The “margins” of a prototype also divide up the prototype background into a 3x3 grid. When a contraption is resized: the top-left tile of the prototype is drawn at the top-left corner of the contraption; the top-centre tile of the prototype is tiled horizontally across the top of the contraption; the top-right tile of the prototype is drawn at the top-right corner of the contraption, and so forth.

The default introduction/tutorial deck you get when you launch Decker has a page on “contraptions”, and one of the examples is a “resizable decorative border” contraption that demonstrates the behaviour nicely.

If you want to draw the background with code, you’ll need a canvas widget if only because the Image protocol you get from card.image doesn’t provide a lot of drawing primitives. You can use a “hidden” canvas widget, draw the background you want, then do card.image:canvas.copy[0,0 canvas.lsize] to paste it onto the contraption background, or (much easier) just make the canvas widget cover the area of your prototype, and Decker’s default resize behaviour (with the margins and such) will make sure it stays in place as the contraption is resized.

Lil’s vector-handling made more sense to me when I learned that it was inspired by a language called K, which was inspired by a language called APL, which was designed (among other things) to be a more modern alternative to traditional mathematical notation. Mathematicians will use + to represent addition of integers or complex numbers or matrixes or anything other random thing that obeys the algebraic laws of addition, and APL (and eventually Lil) uses + in a similar way.

If you think about vectors in the way they’re normally handled in languages that weren’t designed around the concept (like Python or Fortran), then yeah, you’re not going to get the full benefit. I also have found Lil to be a bit mind-bending (I came up with 1+0*range 5 for what I’ve now learned is more idiomatically expressed as 5 take 1), but it’s still so much more approachable than APL or even K, and there’s this whole cool retro-themed multimedia sketchpad tool built around it.

If you can provide an example contraption that exhibits the behaviour you describe, that would help. If you can set it up in a new deck, you can select the contraption, do Edit → Copy Widgets, and then paste the result into a reply here. That’s what I did to create the examples in my reply - if you copy a contraption, Decker even includes its prototype.

Is there ANY way to resize an internal canvas(es) on a contraption resize?

If you make your prototype “resizable” (when you’re editing a prototype, from the “Prototype” menu make sure the last item “Resizable” is ticked), then you should be able to resize the contraption when you add it to a card. If you also tick “Show Margins” in the Prototype menu, you’ll also get four little handles you can use to mark the left, right, top and bottom margins of the prototype: any part of a widget that is between the edge of the prototype and the margins will stay at that fixed distance from the edge, any part of a widget that is in the middle will be proportionally resized as the contraption is resized.

%%WGT0{"w":[{"name":"prototype11","type":"contraption","size":[98,91],"pos":[86,66],"def":"prototype1","widgets":{"canvas1":{"size":[81,41]}}}],"d":{"prototype1":{"name":"prototype1","size":[100,100],"resizable":1,"margin":[0,25,0,0],"widgets":{"canvas1":{"type":"canvas","size":[83,46],"pos":[8,9]}}}}}

If you paste the above widget definition into a card, you’ll get a contraption with a canvas in the top half of it. The top edge of the canvas is between the top edge of the prototype and the top margin, so it stays at a fixed distance from the top of the contraption as it is resized. The bottom edge of the canvas is between the top and bottom margins, so it moves proportionally as the contraption is resized.

If you are trying to write code to reposition widgets in a deck, that should work, but it may be overidden by the “built in” resizing behaviour described above? I’m not sure, I haven’t tried it.

But, then that raises another question, I am uncertain where to initialize long term state on a card or contraption.

The best place to put long-term state on a card or contraption is in a widget. Widgets don’t have to be in the centre “white” part of a prototype, you can stash them in the dark-grey border area - but make sure they’re locked so the user can’t accidentally interact with them. For most data types (numbers, strings, lists, dicts, tables) you can just use a regular field, and read and write its .data property. If you want to store a bunch of images (such as sprites), the best way is to use a rich-text field; you can paste the images in, and access them from code by reading the .images property.

Also, is there a working example of get_ and set_ for prototypes?

If you edit a prototype and choose “Script…” from the Prototype menu, you can enter a handler like this:

on get_foo do
 "here's a foo"
end

Then, let’s say you make a contraption from this prototype, called mycontraption. If you say mycontraption.foo, that will evaluate to the string "here's a foo". Here’s a pasteable example of that in action:

%%WGT0{"w":[{"name":"mycontraption","type":"contraption","size":[100,100],"pos":[86,66],"def":"prototype1","widgets":{}},{"name":"button1","type":"button","size":[84,20],"pos":[93,40],"script":"on click do\n alert[mycontraption.foo]\nend","text":"Gimme a foo"}],"d":{"prototype1":{"name":"prototype1","size":[100,100],"margin":[0,0,0,0],"script":"on get_foo do\n \"here's a foo\"\nend","widgets":{}}}}

Setting works the same way: define on set_foo val do ... end and it will be called when code does mycontraption.foo:somevalue.

If you want to be able to get and set values interactively, rather than just through code, you can also use “attributes”, but that’s an optional, additional layer on top of get_foo and set_foo that you don’t have to worry about otherwise.

That’s a good point, thanks!

I’m working on a deck right now, using my laptop, and I’ve been using the arrow keys to quickly switch between cards. I gave it to a friend (who is unfamiliar with Decker) to test on their phone, and their very first comment was “when I swipe left to go to the next card, it takes me to the previous card instead”.

I want to address this, but I’m not sure how.

  • I could say “that’s just how it is, deal with it”, but I imagine other people will get tripped up by this too
  • I could override the navigate event to work “backwards”, which will make touch-screens feel more natural, but then arrow-key navigation is weird
  • I could override the navigate event to do nothing, which prevents a convenient shortcut but also prevents confusion

I already have “back” and “next” buttons on every card, as well as a table-of-contents card, so losing the navigation shortcuts wouldn’t be the worst thing in the world, and that is probably what I’ll go for.

Are there any other alternatives?

The “Patterns Interface” section of the Decker docs describes the animated patterns as:

A list of up to 256 pattern indices for animated patterns.

You can include solid “red” and “black” in the animated sequence because they have pattern indices (35 and 1). But if you want a pattern pattern, those are described as:

An 8x8 image interface comprised of patterns 0 and 1.

So actual patterns can’t have red in them, only patterns 0 and 1, which are (by default) white and black. You could set palette 32 to be red instead of white to get red-and-black animations, but that would make every white pixel red, which probably isn’t what you want.

How did you get the decks to have custom icons in the file manager?

(1 edit)

For your first question, a canvas gets the click event on mouse-down, and the release event on mouse-up, so you can make the canvas change colour while the button is held down:

on click pos do
 me.pattern:colors.red
 me.rect[0,0 me.lsize]
end

on release pos do
 me.pattern:colors.white
 me.rect[0,0 me.lsize]
end

(obviously you can do fancier painting than that if you want)

The release event also gives you the position of the pointer at the time the button was released, relative to the top-left corner of the canvas. If the position is below and to the right of the top-left corner, and above and to the left of the bottom-right corner, then it’s within the canvas, and you can do whatever the canvas-button is supposed to do:

if min (pos>0,0),(pos<me.lsize)
 alert["whatever I'm supposed to do"]
end

For your second question, I can’t easily spot an error (though I’m pretty sure you don’t need set); in this situation I’d wrap show[] around different parts of the code to double-check that the values being calculated were the ones I expected. show[] takes a sequence of expressions, logs them to the Listener, and returns the first one, so you can wrap it around expressions without changing how your code runs. So, this code will run exactly the same as the example above:

if min show[(pos>0,0) "<-- to the bottom right"],show[(pos<me.lsize) "<-- to the top left"]
 alert["whatever I'm supposed to do"]
end

…but produces this output in the Listener:

(1,1) "<-- to the bottom right"
(0,1) "<-- to the top left"

For your third question, the floor operator drops the fractional part of a number:

 floor 1.0,1.4,1.5,1.6,2.0
(1,1,1,1,2)

If you want round-to-nearest rather than always-round-down, you can add 0.5 before hand:

 floor 0.5+(1.0,1.4,1.5,1.6,2.0)
(1,1,2,2,2)

It looks like it does! Thanks!

I had hoped I could check "card"=typeof card.parent to see if contraption was being used on a card (in which case, the button needs to be moved out of the way) or if the prototype was being edited (in which case, leave the button where it is so we can edit it). Unfortunately it seems like a prototype’s parent is always some card, even if that card does not contain any contraptions.

Still, if I really need to, I can still bring the button back on-screen by setting its position in the Listener.

To be clear, I do have a clickable button, it’s just that I’m using a canvas so I can get the click event as well as the release event. I figured that, like regular buttons, it would be nice to support shortcuts as well as clicks.

I’m not currently targeting Web Decker, but it’s cool that getting key-down events is at least sometimes possible. Thanks for letting me know!