tl;dr
I’ve updated the {pixeltrix} package so you can create animated sprite gifs with a simple, interactive pixel editor from within R’s plot window.
Pix all the right boxes
The {pixeltrix} package—which I’ve written about before—lets you open an interactive R plot that you can click to turn ‘pixels’ on and off.
I created it for one purpose: to quickly create simple, blocky sprites for my {tamRgo} package, which lets you keep a persistent cyberpet on your computer (yes, really).
But wouldn’t it be nice if {pixeltrix} were more… general? Read on for a couple of improvements to the package that might help.
Update
The package has been updated again since this post. From version 0.2 you:
- can provide colours as input to
click_pixels()
andframe_pixels()
- receive a
colours
attribute with the output matrices, which encodes the state and colour values
Pixellate to accumulate
First, you can install the updated package from GitHub:
remotes::install_github("matt-dray/pixeltrix") # v0.1.2 in this post
library(pixeltrix)
Now the improvements: plotting with colour, and creating gif animations.
1. Plot
The click_pixel()
function opens an interactive plot. If n_state = 3
, for example, then each pixel will cycle through three states as you keep clicking it. You’re returned a matrix of these values when you hit Esc.
That was enough for {tamRgo}: I turned a binary matrix into a 1-bit sprite. But wouldn’t it be good—fundamental!—to be able to plot the matrix as an image with user-specified colours? So I made draw_pixels()
.
I’ve added a three-state matrix, blue
, into the package as an example dataset. Let’s plot it with simple colours:
draw_pixels(
m = pixeltrix::blue,
colours = c("white", "#879afb", "gray20")
)
Of course, it’s the subtly-coloured player character from Pokémon Blue (1996) as seen on the Nintendo Game Boy Color.
2. Animate
Naturally, you could use click_pixels()
and draw_pixels()
to generate several images and combine them as ‘frames’ of an animation. Why not have a function that does this automatically?
So that’s what I did:
frame_pixels()
callsclick_pixels()
and adds the output as the first element of a list, then it passes that matrix intoedit_pixels()
as the template for the next frame (and so on until you choose to stop making frames)gif_pixels()
takes the list of matrices created byframe_pixels()
and draws, combines and writes them to a gif
I’ve prepared pixeltrix::mario
as an example of an output from frame_pixels()
. It contains each of three frames that comprise Mario’s walk cycle from Super Mario Bros on the NES.
Here’s what the console output looked like when I made mario
:
mario <- frame_pixels(
n_rows = 16,
n_cols = 16,
n_states = 4 # background + 3 colours
)
# Click squares in the plot window. Press <Esc> to end.
# Add a frame? y/n: y
# Click squares in the plot window. Press <Esc> to end.
# Current frame count: 2
# Add a frame? y/n: y
# Click squares in the plot window. Press <Esc> to end.
# Current frame count: 3
# Add a frame? y/n: n
# Final frame count: 3
You can see there’s interactivity; the user is prompted to add another frame with Add a frame? y/n:
, where y
will let you create a new frame and n
will stop the process and return the list of matrices.
And so you can see it’s a list of three matrices:
str(mario)
## List of 3
## $ : int [1:16, 1:16] 0 0 0 0 0 0 0 0 1 1 ...
## $ : int [1:16, 1:16] 0 0 0 0 0 0 0 0 0 0 ...
## $ : int [1:16, 1:16] 0 0 0 0 0 0 0 0 0 0 ...
You can then convert the list to a gif with gif_pixels()
, which engifs the frames using {gifski}.1
gif_pixels(
frames = mario,
colours = c(
"white", # background
"#FDA428", # skin (yellowish)
"#FC0D1B", # overalls/hat (red)
"#A32B2E" # hair, eyes, shirt, boots (brown)
),
file = "mario.gif",
delay = 0.15 # passed via dots to gifski::save_gif()
)
# Inserting image 3 at 0.30s (100%)...
# Encoding to gif... done!
# [1] "mario.gif"
And if we open that file:
Yahoooooo, created entirely with R. Noice.
Pix n mix
So {pixeltrix} finally got a couple of nice-to-have (well, must-have) functions. This is enough for me to continue just messing around with it as a novelty2.
I mean, come on: animated pixelart created in an interactive R plot window? Why? I mean, er… wow!
Session info
## ─ Session info ───────────────────────────────────────────────────────────────
## setting value
## version R version 4.2.0 (2022-04-22)
## os macOS Big Sur/Monterey 10.16
## system x86_64, darwin17.0
## ui X11
## language (EN)
## collate en_US.UTF-8
## ctype en_US.UTF-8
## tz Europe/London
## date 2022-12-22
## pandoc 2.19.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
##
## ─ Packages ───────────────────────────────────────────────────────────────────
## package * version date (UTC) lib source
## blogdown 1.9 2022-03-28 [1] CRAN (R 4.2.0)
## bookdown 0.26 2022-04-15 [1] CRAN (R 4.2.0)
## bslib 0.3.1 2021-10-06 [1] CRAN (R 4.2.0)
## cli 3.3.0 2022-04-25 [1] CRAN (R 4.2.0)
## digest 0.6.29 2021-12-01 [1] CRAN (R 4.2.0)
## evaluate 0.15 2022-02-18 [1] CRAN (R 4.2.0)
## fastmap 1.1.0 2021-01-25 [1] CRAN (R 4.2.0)
## fontawesome 0.2.2 2021-07-02 [1] CRAN (R 4.2.0)
## htmltools 0.5.2 2021-08-25 [1] CRAN (R 4.2.0)
## jquerylib 0.1.4 2021-04-26 [1] CRAN (R 4.2.0)
## jsonlite 1.8.0 2022-02-22 [1] CRAN (R 4.2.0)
## knitr 1.39 2022-04-26 [1] CRAN (R 4.2.0)
## magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.2.0)
## pixeltrix * 0.2.0 2022-12-22 [1] local
## R6 2.5.1 2021-08-19 [1] CRAN (R 4.2.0)
## rlang 1.0.2 2022-03-04 [1] CRAN (R 4.2.0)
## rmarkdown 2.14 2022-04-25 [1] CRAN (R 4.2.0)
## rstudioapi 0.14 2022-08-22 [1] CRAN (R 4.2.0)
## sass 0.4.1 2022-03-23 [1] CRAN (R 4.2.0)
## sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.2.0)
## stringi 1.7.6 2021-11-29 [1] CRAN (R 4.2.0)
## stringr 1.4.0 2019-02-10 [1] CRAN (R 4.2.0)
## xfun 0.30 2022-03-02 [1] CRAN (R 4.2.0)
## yaml 2.3.5 2022-02-21 [1] CRAN (R 4.2.0)
##
## [1] /Library/Frameworks/R.framework/Versions/4.2/Resources/library
##
## ──────────────────────────────────────────────────────────────────────────────
The {pixeltrix} package has no dependencies and I didn’t want to force a user to install {gifski} if they weren’t going to use
gif_pixels()
. It’s therefore up to the user to install it. I also wonder if I should provide an argument for the user to name a ‘gif engine’ of choice, e.g. {gifski} or {magick}, depending on what they’ve got installed on their machine.↩︎It’s never, ever going to have the features and quality of a premium pixel-art program like Aseprite, obviously.↩︎