This turned out absolutely beautiful.... wow.
ahmwma
Creator of
Recent community posts
I had something far less refined in mind to try to do with Patternshop but could never find the time to dig in, so this is really a delight. You're making such cool and useful tools, Missooni! It's really inspiring!
I'm looking forward to spending more time with this thing you made during the upcoming decker jam.
People who post their own versions of Wigglypaint without lying and stealing art are fine. Change logs for various versions of Wigglypaint actively encourage people to try tinkering with the program. Legit, free and honest modifications of Wigglypaint have always existed, and Internet-Janitor has answered questions helping people make their own modifications in the past
But when we're talking about scams we're talking about people lying about being "The Official Wigglypaint", sometimes pretending to be Internet-Janitor personally and stealing hundreds of people's artworks for their community galleries to look like a legit official website. These scammers are doing shady things to deceive new artists into giving them money, often tricking them into thinking that they're supporting the creator. That's why there's a scam warning here.
Internet-Janitor has written about how to modify the lineart brushes over on the Decker forums!
A simple option (with one moderate drawback) is that you can put all of your game script inside of a while loop inside of the on view do event. Basically like this:
on view do while 1 # your game stuff goes here end end
That should start it over from the beginning forever. The drawback is that we haven't given you an exit from the loop. If the game is totally done and you don't need to edit or test anything anymore then that might just work for you as it is.
If you're still editing and tweaking things you may need to stop the script (with the menu [Script > Stop]) though it will stop everything exactly where it is. That includes any dialogizer or puppeteer elements left hanging out on screen.
If you do need to do a stop like that you can force those two modules to clean themselves up on the current card by using the Listener [ Decker > Listener ] by using dd.close[] and pt.clear[]. In the Listener you'll need to hit Shift+Enter to run your code. Just mentioning that in case you haven't used the Listener before.
If the narrative doesn't specifically need to loop you could alternatively just send people back out to the title card (if one exists) and have them click play again, or have a "start" button which hides itself while the game is playing and then appears again after the story is done.
But this is definitely the simple answer to get it to loop (best applied cautiously when your game is otherwise finished).
If you want to take a slightly different approach that allows you to set up the auto-loop while still being able to test a single playthrough yourself you could put your dialogizer script inside a different event handler: a new one we're making up. We'll call it "cutscene".
on view do while 1 cutscene[] end end on cutscene do # your game stuff goes here end
Doing it this allows you to have it autoplay on the main card whenever it experiences a view event, but you can also set up a button on a another behind-the-scenes (or temporarily) card which will let you run through your game inside the cutscene event one time, and then automatically return to the other card with the tester button on it. This might be more useful if you're not finished tweaking things yet.
This is what that button script could look like:
on click do go[yourmaincard] deck.card.event["cutscene"] go["Back"] end
Though, of course, change the card name to whatever it's actually called.
But I hope one of these options makes sense and works for what you're doing!
Are you intending for it to loop automatically when they reach the end, or just for people to be able to restart from the beginning of they want to (like with a replay button)?
And I guess from a script perspective, are your dialogizer scenes currently coming from an "on view do" event handler on the card script?
Should be possible no matter what, I just want to make sure I understand what you need.
I'm a little sleepy, so I'm sorry if this doesn't totally make sense but I'll take a stab at writing out instructions anyway. If you get confused let me know with what part and I'll try to clear it up.
In both cases these are a kind of Decker resource called a Module. These are-written bundles of code that do specific things that you can transfer into your projects and it's all set up to be convenient and reusable.
You'll probably already have a copy of dialog.deck in the examples folder that comes with downloadable Decker. But you'll also want to download a copy of typetext.deck from the link above. Then you'll have the modules on your computer and you'll have an easier time transferring them to your project.
How to transfer resources
While you have your new project open (or an empty deck that might become your new project) use the menu at the top to go to File > Resources. Use the Choose button to select one of the decks files that you want to transfer a module from. This will create a list of all the transferrable resources on the left, and you can choose the ones you want and >> Copy >> them into your current project.
You'll want to get the "typetext" module from typetext.deck and the "dd"module from dialog.deck.
How to use typetext
When the typetext module is in your deck you can use it in scripts to make a section of text type out letter by letter into a text field. The easiest way to test it out is by putting your script in a button so you can click the button and see if things happen how you want them to.
I'm going to walk through the example code from the typetext module to explain what each part means, and then you can try playing around with it yourself.
Imagine that this is the little bit of code inside a button:
on click do typetext.typetext["hi there, look at this being typed out" targetfield 5 "" "lowpip"] end"on click do" and "end" are the basic structure of the usual click event code inside a button. Anything you want to happen when you click the button should go between those two lines.
The typetext.typetext part is just telling decker to look at the typetext module and use the typetext function (I think they're only the same word because this module only has one function).
Inside the brackets is where we put our arguments, meaning the instructions we want to give typetext about what to type, where to type it, etc.
The text inside the quotes ("hi there...") is the text that will be typed out typed out.
targetfield is a name I made up for a text field that we want the text to be typed into. (It doesn't need to be called that, it just need to exist and have the name of the field match the name in this part of the code)
5 is the speed, but specifically it's how long do you want typetext to pause to take between letters. In this case it's 5 frames. Try different numbers if you want!
The "" is an additional argument you can give it, if you want some text to be there already before the typing-out effect begins. You can leave this as two quotes with nothing in it if you don't want to use them.
"lowpip" is the sound effect that plays when this particular example runs. You'll need to transfer this sound effect from typetext.deck if you want to use it. It works just like how you got the module. You can also set up a different sound to use here or you can ignore this if you prefer silence.
My suggestion from here is to play around with it. :) And let me know if you run into any difficulties.
How to use Dialogizer
The Dialogizer example deck (examples/dialog.deck) is also full of instructions for how to use this module, but I'll write out a simple version so you can refer to this and the example deck and hopefully one or both of these explanations will make sense.
I'll use a simple button script example again:
on click do dd.open[deck] dd.say["Hello, World!"] dd.close[] endWhen this button is clicked the dd module is told to open[] (get itself ready, in a sense), then told to say[] ("Hello, World!" will appear in a dialog box) and then close[] itself, because it's done.
This is the basic code of Dialogizer, though there are some ways to make it even easier to write big scenes and also ways to style your dialog boxes which I'll explain next.
But to make sure things are set up right, just try putting that code up there in a button in your project and click it once. If the dialog box popped up on screen and displayed the text then we can move on.
Easier writing with Dialogizer
If we switch that code above to say dd.say[story.value] instead of dd.say["hello"] it can display a whole scene that's written in a more natural way inside of a Field widget.
story.value effectively tells dd to look at the contents of our field widget called story and dd.say[] will treat it as multiple lines of dialog if there are blank lines between lines of text.
Let's say this is the text inside of a Field widget named "story":
Me: Hello, World! World: Oh, hello there... Me: Aaah! The world is saying hello back!
This should make a series of dialog boxes appear until it finishes the whole scene written in the field. Hopefully this will all make sense if you give it a try.
Styling Dialogizer
This might seem a little more confusing at first.
We need to rewrite dd.open[deck] to add another argument: we need to tell it the name of a specific style that we're going to define. You can name your styles pretty much anything but I'll use the name st in this example because I want to create a style that has slow text.
I'm going to change our dd.open[deck] line to say dd.open[deck st] instead.
But we also need to define what st means. In a big project you'll probably want to put your style information 'higher up', maybe in the deck level script (happy to explain this later!) so any button or script in the project can look up and see what st means... but for this practice button we can define it in the same button where the dd script lives, just above the "on click do" event handler.
st:() st.speed:10 on click do dd.open[deck st] dd.say[story.value] dd.close[] end
Now when we click the button the text in our "story" will play out slowly. (It will take 10 frames per word. Lower numbers will be faster.)
There are a bunch of other ways to style a dialog box that are explained inside of dialog.deck, by the way! Once you understand the structure that the dd module uses it gets a lot easier to figure out what all the examples are doing, and you don't need to be able to write much code at all to start making things.
I'm sorry for being very rambly in this post but I hope this helps you get started playing with these two modules!
(And if you're interested in visual novel-type stuff, Dialogizer works very well with another module named Puppeteer which can handle character sprites.)
Hi there! Welcome!
I'm going to start with two existing resources which do similar things along these lines so check them both out let me know if either of them do the thing you want.
An option that can make text appear word-by-word in a dialog box: the Dialogizer module (specifically this page's demo which shows the text showing up word-by-word)
An option that can make text appear letter-by-letter in a text field: the Typetext module. (Demo on the main page)
Are either of these similar to what you're looking for? I can write out instructions for how to use either of them.
I am somehow delighted that the manifesto that discussed the creation of the anything jam is, itself, submitted into the jam.
A work in conversation with itself, and with all who check out one and then the other.
I'm not sure yet what kinds of things I might make during the jam that might end up submitted here (or not, who knows) but I really like the spirit of it and I hope some other folks enjoy the spirit of it too.
Adding more information about these scams:
Here is a google doc summary of these fake websites and their shady behavior. (Including Wigglypaint.com, .net, .org, .io, Wigglypaint and Jigglypaint apps, etc.)
Here is a spreadsheet of the known artworks that were stolen from artists here on itch.io by these various sites and apps -- please be patient while it loads, there are over 2000 entries. Artists can search their itch display names in the spreadsheet to see if their art ended up on any of these sites.
This is generic advice but hopefully it'll point you in the right direction.
In Decker Buttons (including checkboxes) have a .value attribute. The .value can be set to 1 or 0, true or false. If a checkbox is marked that means the value is 1 (true).
You can have code check whether or not a specific checkbox is marked and do different things depending on whether or not it is. For example:
if mycheckbox.value # some code goes here else # optionally you could put some other code that should happen if mycheckbox isn't marked end
If the checkbox is on a different card (for example, on another card that's named 'options') you may need to refer to it by a longer 'address'.
if options.widgets.mycheckbox.value # your code goes here end
Here's another resource about using if statements in Decker. I hope this helps a little!
A note about how to access the Wigglystash contraption, for people who aren't familiar!
Using the menu bar you can go into "Widgets mode" which lets you edit various things in the program. [ Tool > Widgets ]
And then use the new "Widgets" menu option to create a "New Contraption"
Pick "wigglyStash" and click create.
This will give you a little rectangle with "Stash" and "Recall" written on it. Position it where you want it to be with your mouse and then go back to interact mode with the menu. [ Tool > Interact]
You can now click "Stash" to save and "Recall" to load a wigglypaint image from the wigglyStash contraption. You can even have a bunch of them, if you want.
This isn't a replacement for saving your file if you're using Wigglypaint offline, this is just an extra way to temporarily store drawings-in-progress while you're working on something or trying out different ideas.
For the record this has been in progress for a while. I just saw your comment when I came back here to add the findings to the thread. Thank you for at least looking at things.
The research was actually the simple part. The great effort was in getting confirmations from large amount of artists that they didn't give permission for their art to be used. But I think that it was necessary to avoid a different kind of pedant commentary -- the "Well, are you sure the art was used without permission? Couldn't the people behind the sites have contacted these specific artists?" kind of nitpicking. And now I've spoken to enough artists whose work was taken to be very sure about the scale of art theft.
But in any case I'm not the developer of Wigglypaint and have no sway over the license. I'm just an artist and community member who noticed that the creative works of people here on itch being were used as materials to scam people elsewhere and I really didn't like that.
Hmm! Yeah, my example in the book only goes one way... I'll have to think about adjusting it.
But for now I'll explain some other ways to write that script here!
Because buttons can hold a binary value (0 or 1) you can set it to hold either of those values directly.
Or you can tell it to be "NOT the current value". This will toggle it between 0 and 1 depending on which value is currently stored.
"!" is the Lil operator for "NOT" so it could be written like this:
on click do
thebox.value: ! thebox.value
end
I hope this makes sense? And thank you very much for reading! I'm always happy to clarify things!
Sorry to get heavy in this thread but I have been looking into the fake Wigglypaint websites and I don't think there's any reason to make up stories about them being run by good-intentioned teenagers or people who "accidentally recreated Wigglypaint with an LLM" or whatever.
- The sites are often deceptive about who is running them: sometimes claiming to be IJ, sometimes just the "Wigglypaint Team".
- They aren't using an accidentally similar program, it's usually either Wigglypaint 1.3 or Wigglypaint 1.5 with IJ's title screen credit removed.
- Many of them are monetized with ads, subscriptions, apps and referral links to AI services.
- The vast majority of them stole artwork for their "community galleries". One has even used stolen artwork for their promotional screenshots in the app stores.
And there's a lot of stolen artwork. Overwhelmingly it was taken without permission from artists posting their work here on itch.io. If you posted a drawing on the wigglypaint page here on itch between December 2023 and September 2025 your doodle may have been scraped into one of these galleries. This includes some of our own Decker community folks and even bigger names around the site like Leafo and Kenney.
You can see the write-up here. (It's not perfect, it was written to be a broad collection of evidence and a summary of the issues for affected artists. )
Or this spreadsheet of known stolen artwork connected back to the artist's itch.io display names.
This covers: Wigglypaint.com, Wigglypaint.net, Wigglypaint.org, Wigglypaint.io (a.k.a. Jigglypaint.com and the Jigglypaint app), Wigglypaint.run, Wigglypaint.fun, Wigglypaint.art, Wigglypaint.co, Wigglypaint.online, Wiggly-paint.com and Wigglypaintgif.com.
There are others too, but without art theft or noteworthy lies they didn't make it into the writeup. Most of these sites appeared within a short period of time in mid-2025 when Wigglypaint had a spike of popularity on social media.
And I hope it's obvious (because this is the Decker forum) that the problem here isn't with modding Wigglypaint or taking it apart or learning from it. I've been helping people mod the program off and on and I will continue doing so as long as there's interest. Customizing the program for yourself is fun and easy to do.
The problem is people using a free program to run scams. Ripping off artists while using stolen work as the advertisements to lure them in.
Well, you've definitely got me thinking that it would be good to write up more beginner-friendly notes about how to use Puppeteer...
But since that hasn't been written yet, I'm happy to help with whatever you're having trouble with right now.
For example:
- setting things up in your project
- making the sprites appear
- making puppeteer and dialogizer work together
- making sprites move around
- something else?
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