Skip to content

Instantly share code, notes, and snippets.

@QuinnStephens
Last active March 8, 2022 16:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save QuinnStephens/fae4f931fc10ce1f1cc7885a26629963 to your computer and use it in GitHub Desktop.
Save QuinnStephens/fae4f931fc10ce1f1cc7885a26629963 to your computer and use it in GitHub Desktop.
Capture looping animation from Phaser
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.min.js"></script>
</head>
<body>
<script>
/**
* This is a simple one-page Phaser app that allows you to create simple looping animations
* and save the frames as individual images, which can then be converted to GIF or video formats.
* This example loads four images—one static, three moving—and sets them to scroll across the screen
* by creating tileSprites and animating the tilePosition property. Sample images can be found here:
*
* https://res.cloudinary.com/quinnstephens/image/upload/v1646697468/gist/phaser-animation-loop/layer0.png
* https://res.cloudinary.com/quinnstephens/image/upload/v1646697468/gist/phaser-animation-loop/layer1.png
* https://res.cloudinary.com/quinnstephens/image/upload/v1646697468/gist/phaser-animation-loop/layer2.png
* https://res.cloudinary.com/quinnstephens/image/upload/v1646697468/gist/phaser-animation-loop/layer3.png
*
* They will need to be downloaded and placed in the same folder as this file.
*
* In order to run this file locally, you will need to set up a local development server. Phaser's docs explain
* how to do this on different platforms, and why you need to:
* https://phaser.io/tutorials/getting-started-phaser3
*
*/
const config = {
type: Phaser.AUTO,
width: 256,
height: 256,
render: {
roundPixels: true,
},
scene: {
preload: preload,
create: create,
update: update
},
fps: {
target: 24,
// Change framerate to a very low value when exporting frames
// target: 2,
forceSetTimeOut: true
},
};
const game = new Phaser.Game(config);
function preload() {
this.load.image('layer0', 'layer0.png');
this.load.image('layer1', 'layer1.png');
this.load.image('layer2', 'layer2.png');
this.load.image('layer3', 'layer3.png');
}
function create() {
this.layer0 = this.add.image(0, 0, 'layer0').setOrigin(0, 0);
this.layer1 = this.add.tileSprite(0, 0, 256, 256, 'layer1').setOrigin(0, 0);
this.layer2 = this.add.tileSprite(0, 0, 256, 256, 'layer2').setOrigin(0, 0);
this.layer3 = this.add.tileSprite(0, 0, 256, 256, 'layer3').setOrigin(0, 0);
this.snapshotCount = 0;
}
function update() {
// Total animation length: 64 frames
// Layer 1 has a tile width of 64 frames, so we want it to
// move 64 frames over the course of the animation,
// or 1 pixel per frame
this.layer1.tilePositionX += 1;
// Layer 2 tile size is 128; 2 * 64 = 128
this.layer2.tilePositionX += 2;
// Layer 3 tile size is 256; 4 * 64 = 256
this.layer3.tilePositionX += 4;
// Uncomment this to export frames
// const totalFrameCount = 64
// if (this.snapshotCount < totalFrameCount) {
// this.renderer.snapshot((image) => {
// exportCanvasAsPNG(this.canvas, `${this.snapshotCount}`, image.src);
// });
// this.snapshotCount += 1
// }
// Once frames are exported, you can convert them to a GIF with imagemagick:
// convert -delay 20 -loop 0 *.png myimage.gif
}
function exportCanvasAsPNG(id, fileName, dataUrl) {
var canvasElement = document.getElementById(id);
var MIME_TYPE = "image/png";
var imgURL = dataUrl;
var dlLink = document.createElement('a');
dlLink.download = fileName;
dlLink.href = imgURL;
dlLink.dataset.downloadurl = [MIME_TYPE, dlLink.download, dlLink.href].join(':');
document.body.appendChild(dlLink);
dlLink.click();
document.body.removeChild(dlLink);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment