Automadraw is a new experimental app I made for my Constraint Systems project. It lets you draw and evolve your drawing using cellular automata using two keyboard controlled cursors.
I think there are two main uses for Automadraw:
I had originally planned to use just one cursor, and have it shift between draw mode and “act” (run automata) mode. As I experimented I found that usually for act mode I wanted to cover a large area and draw mode a smaller one. Having to resize when switching between modes ruined the flow, so I split the cursors up.
Splitting them up opened up some new possibilities. I realized I could set it up so that I could use each cursor’s actions (draw or act, respectively) regardless of which one was in focus. This set up a couple of interactions I really liked:
This set-up is uniquely suited to keyboard cursor controls, where each cursor’s position is fully visible and fully predictable (versus a touch interface where you would have to use multiple fingers and the fingers themselves would obscure your view of the changes taking place). I use Vim-like keyboard controls because I honestly prefer them. My suspicion is that they may enable modes of interaction other methods do not. I was happy to find an interaction that fit them so well. I’m looking forward to seeing how even more multiple cursors feel in future experiments.
Stamp is a different example of the possibilities of multiple cursors: two cursors across two canvases.
Part of the reason the two cursor interaction is interesting is because of an accident of keyboard event handling. A lot of the Constraint System experiments let you hold down multiple keys. This is tricky to handle in Javascript for everything except modifier keys. The main issue is that if you’re holding down one key, and start holding an additional one, the new one will take over the keyDown
event. The solution is to make a keymap object, store each key on keyDown
and remove it on on keyUp
. You then use the keymap object for the source of truth about what is pressed on each keyDown
event.
This technique mostly just works, but there turns out to be an issue, arguably a bug, that makes things like the “sweep” technique I discussed above possible. If you are pressing one key, add another key, then let up on the second key, keyDown
events stop firing. For Automadraw, this behavior enables this interaction:
This interaction was a happy accident, and I’m looking forward to thinking about how to expand and support it more in future experiments.
I had been wanting to experiment with cellular automata and a drawing app for a long time. For this experiment, I needed to really scope things down in order to get started. I restricted the drawing app colors to 1-bit (on or off). This usefully limited the number of cellular automata I could use and the number of interactions I needed to support. I also made the app ‘pixels’ large, at 16 actual pixels. This makes drawing quick and the automata actions more legible, but also restricts the fidelity of the final image. Someday I would like to build a cellular automata app more focused on image editing, where you could evolve parts of an image at a higher fidelity. That would also involve using automata that use color information, there are some interesting examples of those in this CA Lab demo video.
The code for Automadraw is avaliable on github.
I built the early Constraint Systems experiments using React, but have moved off of it to vanilla Javascript for the most recent ones. I do find myself recreating a lot of the set-up of React. I’ve found out firsthand that a lot of the React boilerplate I questioned is in there to work around the constraints of Javascript itself. I may switch back to React sometime, but right now I’m still enjoying experimenting on my own. It is also true that a lot of the benefits of React don’t mesh well with HTML canvas, which is where most of the action for this app takes place.
This was the first project where I used ES6 modules. It was nice to be able to organize the code into sections like keyboard
and state
. I’ll continue to use them and refine my organization going forward. Maybe someday I’ll have a true base starter kit I can reuse across projects.
One switch I’ve made that I’ve been very happy with, is moving from rendering multiple canvas DOM elements on top of eachother, to placing only one canvas on the dom and compositing the different layers (in this case: cursor
, grid
, art
) on to the DOM layer for each render. My rendering code is a little knotty, but it still feels a lot cleaner than stacking the canvases in the DOM.
Grant Custer is a designer-programmer interested in alternative interfaces.
You can see work and inspiration in progress on my Feed and my alternative interface experiments on Constraint Systems. I’m happy to talk on Twitter, email: grantcuster at gmail dot com, or Mastodon. You can see a full list of projects on my Index.