Hi everyone, I’m learning p5.js and building a small 2D game with animated characters. I have the character frames drawn across multiple draw() frames, and I’d like to export them as a single sprite sheet PNG I can reuse elsewhere. I tried using saveFrames() and stitching the images manually, but it feels clunky once you have dozens of frames. Is there a recommended approach or library for capturing frames and packing them into a sprite sheet grid directly from a sketch? Any examples or tips would be much appreciated. Thanks!
Hello!
And welcome to the forum, great to have you here!
I think the easiest is to collect the images with get() in an ArrayList.
Then make a sprite sheet from the list.
Here is an example.
It grabs the whole screen, you should just grab the necessary area, using get().
You have to adjust the numbers I use; I use resize(100,0), you probably don’t want to use resize() at all. My Sprite sheet is 3 images wide and 5 images high, I don’t know about yours (doesn’t matter as long you later read the Sprite sheet with the same 3 columns and 5 rows).
- mode 0 is your animation / collect images into
ArrayList - mode 1 is not necessary
- mode 2 is were the magic happens
- mode 3 shows the result, here you can say
result.save("...");afaik,
Warm regards,
Chrisir
// https://discourse.processing.org/t/best-way-to-export-a-sprite-sheet-from-p5-js-animation-frames/49597
int mode = 0; // state
int x = 30;
ArrayList<PImage>list = new ArrayList();
PImage result = createImage(300, 500, RGB);
//-----------------------------------------------------------------------------------------------
void setup() {
// Voller Bildschirm statt size()
fullScreen();
background(0) ;
}
void draw() {
background(0) ;
if (mode==0) {
// collect list
circle ( x, 290, 18);
PImage img = get();
img.resize(100, 0);
list.add(img);
x+=15;
if (frameCount > 50)
mode = 1;// go on
}//if
if (mode==1) {
// show list / press any key
x=0;
int y=0;
int k=0;
for (PImage img1 : list) {
image(img1, x, y);
text (k, x+20, y+20);
x+=100;
k++;
}
text ("Press any key.", 20, height-20);
if (keyPressed) {
mode=2;
}
}//if
if (mode==2) {
// make sprite sheet
x=0;
int y=0;
int k=0;
for (PImage img1 : list) {
result.set( x, y, img1 );
// next image pos to the right
x+=100;
// end of line?
if ( x >= 300) {
// next line
x=0;
y+=img1.height;
}
k++;
}
mode=3; // go on
} //if
if (mode==3) {
// show sprite sheet
image (result, 0, 0);
}
}//func
//
@lovelycraftguides, note that @Chrisir’s example above for Processing Java. The same general approach should still work in p5.js though, just using p5.Image, p5.Graphics, or p5.Framebuffer instead.
Thanks for pointing that out…! ![]()
I have never used saveFrames before so I had a go. An hour later I came to the decision that was not the best option to create a sprite sheet.
![]()
The sketch below -
- creates 50 transparent sprites
- creates a single sprite sheet with the sprites in a 10 x 5 grid
- displays the sprite sheet
- saves the sprite sheet to a user defined file which will be downloaded to your
downloadsfolder
Here is the sprite sheet and the sketch code. You can also find the sketch in the web-editor here
The code should be easy to follow but if you have any questions let me know. HTH
![]()
// The sprite grid layout on the sheet
// these limit the number of sprites on the sheet
const nbrX = 10, nbrY = 5;
const nbrSprites = nbrX * nbrY;
// Individual sprite width and height
const sW = 72;
let sH = 100;
// Sheet filename
const filename = 'my-sheet.png';
// Final sprite sheet image
let sheet;
// Animation data
let ang, deltaAng;
function setup() {
createCanvas(nbrX * sW, nbrY * sH);
ang = 0;
deltaAng = (2 * PI) / (nbrSprites + 1);
sheet = createGraphics(nbrX * sW, nbrY * sH);
for(let sn = 0; sn < nbrSprites; sn++){
const px = (sn % nbrX) * sW;
const py = floor(sn / nbrX) * sH;
ang += deltaAng;
const sprite = createSprite();
sheet.image(sprite, px,py);
}
sheet.get().save(filename);
}
function draw() {
background(255, 255, 160);
image(sheet,0,0);
noLoop();
}
function createSprite(){
const pg = createGraphics(sW, sH);
const [sW2, sH2] = [sW/2, sH/2];
pg.translate(sW2, sH2);
pg.clear();
pg.noFill();
pg.stroke(200, 100, 100);
pg.strokeWeight(1);
pg.line(0, -sH2, 0, sH2);
pg.line(-sW2, 0, sW2, 0);
pg.stroke(0);
pg.rect(-sW2 + 0.5, -sH2 + 0.5, sW-1 , sH-1, 10, 10, 10, 10);
pg.fill(0, 192, 0);
const x = 0.3 * sW * cos(ang);
const y = 0.3 * sH * sin(ang);
pg.ellipse(x, y, 10, 10);
return pg;
}
P.S. Welcome to the forum
![]()
