PageSourceSearch

https://www.codeandweb.com/component---src-templates-post-template…-tutorial-index-mdx-f11debd03bd22644b244.js

js codeandweb.com collected 2026-09-24 19:39:31 UTC 34,968 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkcodeandweb=self.webpackChunkcodeandweb||[]).push([[43814],{32308:function(e,t,a){a.r(t),a.d(t,{Head:function(){return f},default:function(){return u}});var n=a(28453),i=a(96540),s=a(94296),r=a(84007);const l=()=>i.createElement(r.A,{title:"melonJS Sprite Sheet Demo",loadingText:"Loading melonJS Demo",aspect:"aspect-2000/1300",url:"/demos/texturepacker/melonjs-spritesheet-demo/index.html"});function c(e){const t=Object.assign({p:"p",ul:"ul",li:"li",h2:"h2",a:"a",span:"span",h3:"h3",strong:"strong",ol:"ol",code:"code",pre:"pre",em:"em"},(0,n.R)(),e.components),{GitHub:a}=t;return a||function(e,t){throw new Error("Expected "+(t?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("GitHub",!0),i.createElement(i.Fragment,null,i.createElement(t.p,null,"Your goals for this tutorial:"),"\n",i.createElement(t.ul,null,"\n",i.createElement(t.li,null,"Learn why you should use sprite sheets in your melonJS game"),"\n",i.createElement(t.li,null,"Use TexturePacker to create a sprite sheet"),"\n",i.createElement(t.li,null,"Optimize the sprite sheet to improve startup time and performance of your game"),"\n",i.createElement(t.li,null,"Add a static background"),"\n",i.createElement(t.li,null,"Create and play an animation"),"\n"),"\n",i.createElement(t.p,null,"The complete tutorial project is available on ",i.createElement(a),"."),"\n",i.createElement(l),"\n",i.createElement(t.h2,{id:"why-you-should-use-sprite-sheets",style:{position:"relative"}},"Why you should use sprite sheets",i.createElement(t.a,{href:"#why-you-should-use-sprite-sheets","aria-label":"why you should use sprite sheets permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"Using a sprite sheet instead of a bunch of single images comes with some advantages:"),"\n",i.createElement(t.ul,null,"\n",i.createElement(t.li,null,"Saving memory — the sheet uses less memory"),"\n",i.createElement(t.li,null,"Faster startup time — only one file has to be loaded from the server"),"\n",i.createElement(t.li,null,"Increased frame rate — melonJS optimizes GPU usage and makes your game faster"),"\n"),"\n",i.createElement(t.h2,{id:"creating-a-sprite-sheet",style:{position:"relative"}},"Creating a sprite sheet",i.createElement(t.a,{href:"#creating-a-sprite-sheet","aria-label":"creating a sprite sheet permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"The easiest way to create an optimized sprite sheet is using TexturePacker — available for Windows, macOS and Linux.\nYou can test it within a 7-day trial period before purchasing a license:"),"\n",i.createElement(s.f,{product:"texturepacker"}),"\n",i.createElement(t.h3,{id:"selecting-your-data-format",style:{position:"relative"}},"Selecting your data format",i.createElement(t.a,{href:"#selecting-your-data-format","aria-label":"selecting your data format permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"You should see a screen similar to the one below after you've installed and started TexturePacker:"),"\n",i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<span\n      class="gatsby-resp-image-wrapper"\n      style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 832px; "\n    >
1\n      <span\n    class="gatsby-resp-image-background-image"\n    style="padding-bottom: 64.42307692307692%; position: relative; bottom: 0; left: 0; display: block;"\n  ></span>\n  <picture>\n          <source\n              srcset="/static/cb254187deca215fec4346863d943dbe/b4f21/texturepacker-select-framework%402x.avif 208w,\n/static/cb254187deca215fec4346863d943dbe/a7f15/texturepacker-select-framework%402x.avif 416w,\n/static/cb254187deca215fec4346863d943dbe/01fa0/texturepacker-select-framework%402x.avif 832w,\n/static/cb254187deca215fec4346863d943dbe/acbef/texturepacker-select-framework%402x.avif 1248w,\n/static/cb254187deca215fec4346863d943dbe/6ba7a/texturepacker-select-framework%402x.avif 1664w,\n/static/cb254187deca215fec4346863d943dbe/10fa7/texturepacker-select-framework%402x.avif 2302w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/avif"\n            /><source\n              srcset="/static/cb254187deca215fec4346863d943dbe/6abcd/texturepacker-select-framework%402x.webp 208w,\n/static/cb254187deca215fec4346863d943dbe/69edf/texturepacker-select-framework%402x.webp 416w,\n/static/cb254187deca215fec4346863d943dbe/da8f3/texturepacker-select-framework%402x.webp 832w,\n/static/cb254187deca215fec4346863d943dbe/28eb2/texturepacker-select-framework%402x.webp 1248w,\n/static/cb254187deca215fec4346863d943dbe/dcb2d/texturepacker-select-framework%402x.webp 1664w,\n/static/cb254187deca215fec4346863d943dbe/1dd8b/texturepacker-select-framework%402x.webp 2302w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/webp"\n            />\n          <source\n            srcset="/static/cb254187deca215fec4346863d943dbe/3697c/texturepacker-select-framework%402x.png 208w,\n/static/cb254187deca215fec4346863d943dbe/e3e0f/texturepacker-select-framework%402x.png 416w,\n/static/cb254187deca215fec4346863d943dbe/283d3/texturepacker-select-framework%402x.png 832w,\n/static/cb254187deca215fec4346863d943dbe/b19d7/texturepacker-select-framework%402x.png 1248w,\n/static/cb254187deca215fec4346863d943dbe/fe2bb/texturepacker-select-framework%402x.png 1664w,\n/static/cb254187deca215fec4346863d943dbe/949bb/texturepacker-select-framework%402x.png 2302w"\n            sizes="(max-width: 832px) 100vw, 832px"\n            type="image/png"\n          />\n          <img\n            class="gatsby-resp-image-image"\n            src="/static/cb254187deca215fec4346863d943dbe/283d3/texturepacker-select-framework%402x.png"\n            alt="Selecting your game development framework"\n            title=""\n            loading="lazy"\n            decoding="async"\n            style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n          />\n        </picture>\n    </span>'}}),"\n",i.createElement(t.p,null,"TexturePacker supports various game and web development frameworks.\nStart by selecting ",i.createElement(t.strong,null,"melonJS")," as your ",i.createElement(t.strong,null,"Framework"),"."),"\n",i.createElement(t.p,null,"TexturePacker has a free mode that is automatically activated after the trial.\nIt works with melonJS if you use the generic ",i.createElement(t.strong,null,"JSON (Array)")," data format but does\nnot contain the optimizations and presets for melonJS."),"\n",i.createElement(t.h3,{id:"adding-sprites",style:{position:"relative"}},"Adding sprites",i.createElement(t.a,{href:"#adding-sprites","aria-label":"adding sprites permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"Next, add your sprites by dropping the ",i.createElement(t.strong,null,"cityscene")," folder onto the center of TexturePacker.\nAll recognized image formats (such as PSD, PNG, JPG, ...) within the folder are automatically added\nto the sprite sheet. New or modified files will update the sprite sheet\nas soon as you re-enter the application."),"\n",i.createElement(t.h3,{id:"setting-pivot-points",style:{position:"relative"}}
1,"Setting pivot points",i.createElement(t.a,{href:"#setting-pivot-points","aria-label":"setting pivot points permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"The pivot point (in melonJS, it is called anchor point) determines the position of the sprite, which is placed\non a given x and y coordinate. It is also the point around which the sprite rotates and scales."),"\n",i.createElement(t.p,null,"For properly aligned sprites and animation frames, it is recommended to enable pivot points in TexturePacker!"),"\n",i.createElement(t.p,null,"In our example, we set the pivot points of the Capguy sprites to bottom/center:"),"\n",i.createElement(t.ol,null,"\n",i.createElement(t.li,null,"Click on ",i.createElement(t.strong,null,"Sprite settings")," in the toolbar"),"\n",i.createElement(t.li,null,"Select ",i.createElement(t.strong,null,"capguy")," subtree in ",i.createElement(t.strong,null,"Sprites")," list"),"\n",i.createElement(t.li,null,"Check ",i.createElement(t.strong,null,"Enable pivot points")),"\n",i.createElement(t.li,null,"Select ",i.createElement(t.strong,null,"Bottom center")," in the ",i.createElement(t.strong,null,"Predefined")," dropdown"),"\n"),"\n",i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<span\n      class="gatsby-resp-image-wrapper"\n      style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 832px; "\n    >
1\n      <span\n    class="gatsby-resp-image-background-image"\n    style="padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; display: block;"\n  ></span>\n  <picture>\n          <source\n              srcset="/static/a5b0ddff2a0a252343ebdc3355e5f573/b4f21/texturepacker-pivot-points%402x.avif 208w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/a7f15/texturepacker-pivot-points%402x.avif 416w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/01fa0/texturepacker-pivot-points%402x.avif 832w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/acbef/texturepacker-pivot-points%402x.avif 1248w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/6ba7a/texturepacker-pivot-points%402x.avif 1664w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/04d8e/texturepacker-pivot-points%402x.avif 2270w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/avif"\n            /><source\n              srcset="/static/a5b0ddff2a0a252343ebdc3355e5f573/6abcd/texturepacker-pivot-points%402x.webp 208w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/69edf/texturepacker-pivot-points%402x.webp 416w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/da8f3/texturepacker-pivot-points%402x.webp 832w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/28eb2/texturepacker-pivot-points%402x.webp 1248w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/dcb2d/texturepacker-pivot-points%402x.webp 1664w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/9cb80/texturepacker-pivot-points%402x.webp 2270w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/webp"\n            />\n          <source\n            srcset="/static/a5b0ddff2a0a252343ebdc3355e5f573/3697c/texturepacker-pivot-points%402x.png 208w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/e3e0f/texturepacker-pivot-points%402x.png 416w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/283d3/texturepacker-pivot-points%402x.png 832w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/b19d7/texturepacker-pivot-points%402x.png 1248w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/fe2bb/texturepacker-pivot-points%402x.png 1664w,\n/static/a5b0ddff2a0a252343ebdc3355e5f573/4f562/texturepacker-pivot-points%402x.png 2270w"\n            sizes="(max-width: 832px) 100vw, 832px"\n            type="image/png"\n          />\n          <img\n            class="gatsby-resp-image-image"\n            src="/static/a5b0ddff2a0a252343ebdc3355e5f573/283d3/texturepacker-pivot-points%402x.png"\n            alt="TexturePacker: Set sprite anchor points"\n            title=""\n            loading="lazy"\n            decoding="async"\n            style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n          />\n        </picture>\n    </span>'}}),"\n",i.createElement(t.h3,{id:"optimizing-your-sprite-sheet-for-speed-and-size",style:{position:"relative"}},"Optimizing your sprite sheet for speed and size",i.createElement(t.a,{href:"#optimizing-your-sprite-sheet-for-speed-and-size","aria-label":"optimizing your sprite sheet for speed and size permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"Your sprite sheet has already been optimized by TexturePacker, using ",i.createElement(t.strong,null,"Trim"),".\nIf you enable ",i.createElement(t.strong,null,"Display outlines"),', you will notice the string "85% overdraw" below the texture.\nThe missing 15% are transparent pixels that have been removed.\nThey are not needed in the sprite sheet — keeping them would waste memory and require more rendering.\nmelonJS gets the information about the removed pixels through the data file and keeps your animations aligned.'),"\n",i.createElement(t.p,null,"Reduce the file size to improve the download speed of your game by setting ",i.createElement(t.strong,null,"Texture format")," to ",i.createElement(t.strong,null,"PNG-8 (indexed)"),".\nThis enables the pngquant — storing the image as an 8-bit indexed png.\nThis decreases the file size from 383kb to 102kb while keeping the image quality almost identical.\nIf you see color bands in gradients, set ",i.createElement(t.strong,null,"Dithering")," to ",i.createElement(t.strong,null,"PngQuant High"),"."),"\n",i.createElement(t.p,null,"Original scene with 32-bit colors, 383kb:\n",i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<span\n      class="gatsby-resp-image-wrapper"\n      style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 832px; "\n    >
1\n      <span\n    class="gatsby-resp-image-background-image"\n    style="padding-bottom: 81.25%; position: relative; bottom: 0; left: 0; display: block;"\n  ></span>\n  <picture>\n          <source\n              srcset="/static/534e36af8628755bedceb1bf7f720c9c/b4f21/cityscene_32.avif 208w,\n/static/534e36af8628755bedceb1bf7f720c9c/a7f15/cityscene_32.avif 416w,\n/static/534e36af8628755bedceb1bf7f720c9c/01fa0/cityscene_32.avif 832w,\n/static/534e36af8628755bedceb1bf7f720c9c/2877c/cityscene_32.avif 1028w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/avif"\n            /><source\n              srcset="/static/534e36af8628755bedceb1bf7f720c9c/6abcd/cityscene_32.webp 208w,\n/static/534e36af8628755bedceb1bf7f720c9c/69edf/cityscene_32.webp 416w,\n/static/534e36af8628755bedceb1bf7f720c9c/da8f3/cityscene_32.webp 832w,\n/static/534e36af8628755bedceb1bf7f720c9c/78fa8/cityscene_32.webp 1028w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/webp"\n            />\n          <source\n            srcset="/static/534e36af8628755bedceb1bf7f720c9c/3697c/cityscene_32.png 208w,\n/static/534e36af8628755bedceb1bf7f720c9c/e3e0f/cityscene_32.png 416w,\n/static/534e36af8628755bedceb1bf7f720c9c/283d3/cityscene_32.png 832w,\n/static/534e36af8628755bedceb1bf7f720c9c/4da7f/cityscene_32.png 1028w"\n            sizes="(max-width: 832px) 100vw, 832px"\n            type="image/png"\n          />\n          <img\n            class="gatsby-resp-image-image"\n            src="/static/534e36af8628755bedceb1bf7f720c9c/283d3/cityscene_32.png"\n            alt="Original game scene with 32 bit colors"\n            title=""\n            loading="lazy"\n            decoding="async"\n            style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n          />\n        </picture>\n    </span>'}})),"\n",i.createElement(t.p,null,"Optimized scene with indexed colors, 102kb:\n",i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<span\n      class="gatsby-resp-image-wrapper"\n      style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 832px; "\n    >
1\n      <span\n    class="gatsby-resp-image-background-image"\n    style="padding-bottom: 81.25%; position: relative; bottom: 0; left: 0; display: block;"\n  ></span>\n  <picture>\n          <source\n              srcset="/static/f26e95d8aea675c7a542ef5a301606ef/b4f21/cityscene_8.avif 208w,\n/static/f26e95d8aea675c7a542ef5a301606ef/a7f15/cityscene_8.avif 416w,\n/static/f26e95d8aea675c7a542ef5a301606ef/01fa0/cityscene_8.avif 832w,\n/static/f26e95d8aea675c7a542ef5a301606ef/2877c/cityscene_8.avif 1028w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/avif"\n            /><source\n              srcset="/static/f26e95d8aea675c7a542ef5a301606ef/6abcd/cityscene_8.webp 208w,\n/static/f26e95d8aea675c7a542ef5a301606ef/69edf/cityscene_8.webp 416w,\n/static/f26e95d8aea675c7a542ef5a301606ef/da8f3/cityscene_8.webp 832w,\n/static/f26e95d8aea675c7a542ef5a301606ef/78fa8/cityscene_8.webp 1028w"\n              sizes="(max-width: 832px) 100vw, 832px"\n              type="image/webp"\n            />\n          <source\n            srcset="/static/f26e95d8aea675c7a542ef5a301606ef/3697c/cityscene_8.png 208w,\n/static/f26e95d8aea675c7a542ef5a301606ef/e3e0f/cityscene_8.png 416w,\n/static/f26e95d8aea675c7a542ef5a301606ef/283d3/cityscene_8.png 832w,\n/static/f26e95d8aea675c7a542ef5a301606ef/4da7f/cityscene_8.png 1028w"\n            sizes="(max-width: 832px) 100vw, 832px"\n            type="image/png"\n          />\n          <img\n            class="gatsby-resp-image-image"\n            src="/static/f26e95d8aea675c7a542ef5a301606ef/283d3/cityscene_8.png"\n            alt="Optimized game scene with indexed colors (pngquant)"\n            title=""\n            loading="lazy"\n            decoding="async"\n            style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n          />\n        </picture>\n    </span>'}})),"\n",i.createElement(t.h3,{id:"creating-the-sprite-sheet",style:{position:"relative"}},"Creating the sprite sheet",i.createElement(t.a,{href:"#creating-the-sprite-sheet","aria-label":"creating the sprite sheet permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"You can now press ",i.createElement(t.strong,null,"Publish sprite sheet")," from the top toolbar to create a data file and\nthe sprite sheet image. Enter ",i.createElement(t.strong,null,"cityscene.json")," as file name and save it in the ",i.createElement(t.strong,null,"data/img")," folder.\nYou can change the file name under ",i.createElement(t.strong,null,"Data file")," if needed."),"\n",i.createElement(t.h2,{id:"importing-and-using-the-sprite-sheet-in-melonjs",style:{position:"relative"}},"Importing and using the sprite sheet in melonJS",i.createElement(t.a,{href:"#importing-and-using-the-sprite-sheet-in-melonjs","aria-label":"importing and using the sprite sheet in melonjs permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"To start a new project, clone the melonJS boilerplate template from\n",i.createElement(t.a,{href:"https://github.com/melonjs/es6-boilerplate"},"GitHub"),". Then, use the command ",i.createElement(t.code,null,"npm run dev"),"\nto launch a development server at ",i.createElement(t.a,{href:"http://localhost:9000"},"localhost:9000"),":"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:"language-bash"},"git clone https://github.com/melonjs/es6-boilerplate.git melonjs-sprite-sheet-example\ncd melonjs-sprite-sheet-example\nnpm install\nnpm run dev\n")),"\n",i.createElement(t.p,null,"Start by configuring the canvas size to match the dimensions of the background image we're going to use.\nYou can do this with the ",i.createElement(t.code,null,"video.init()")," call in ",i.createElement(t.em,null,"index.js"),":"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:'language-js:title="index.js"'},'    if (!video.init(2000, 1300, {parent : "screen", scale : "auto"})) {\n        alert("Your browser does not support HTML5 canvas.");\n        return;\n    }\n')),"\n",i.createElement(t.p,null,"Next, include the sprite sheet and data file in the list of assets to be loaded in ",i.createElement(t.em,null,"manifest.js"),":"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:'language-js:title="manifest.js"'},'const DataManifest = [\n    { name: "cityscene", type: "json",  src: "data/img/cityscene.json" },\n    { name: "cityscene", type: "image", src: "data/img/cityscene.png" }\n];\n')),"\n",i.createElement(t.p,null,"Keep in mind that ",i.createElement(t.em,null,"manifest.js")," is automatically managed by the melonJS boilerplate in ",i.createElement(t.em,null,"index.js"),".\nIt preloads the resources, making them accessible through the ",i.createElement(t.code,null,"loader.get...()")," methods."),"\n",i.createElement(t.p,null,"By default, the boilerplate code activates the PLAY state, which is implemented in ",i.createElement(t.em,null,"play.js"),".\nIn this state, we create a TextureAtlas object using the sprite sheet image and data file resource:"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:"language-js:title=js/stage/play.js"},'onResetEvent() {\n    // load the texture atlas file\n    const atlas = new TextureAtlas(\n        loader.getJSON("cityscene")\n    );\n\n    ...\n}\n')),"\n",i.createElement(t.p,null,"All subsequent code snippets will also be added to this ",i.createElement(t.code,null,"onResetEvent()")," method:"),"\n",i.createElement(t.h3,{id:"add-the-static-background",style:{position:"relative"}}
1,"Add the static background",i.createElement(t.a,{href:"#add-the-static-background","aria-label":"add the static background permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"Adding a static background is quite straightforward:"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:"language-js:title=js/stage/play.js"},'    // viewport width and height\n    const w = game.viewport.width;\n    const h = game.viewport.height;\n\n    // create background sprite\n    const background = atlas.createSpriteFromName("background");\n\n    // set its position to the middle of the viewport\n    background.pos.set(w/2, h/2);\n\n    // add sprite to the scene\n    game.world.addChild(background, 1);\n')),"\n",i.createElement(t.p,null,"The code uses the \"background\" texture from the sprite sheet and places\nit on the screen.\nSince we haven't changed the sprite's anchor point in TexturePacker before, it defaults to\nthe sprite's center. That's why we position the sprite at the center of the viewport."),"\n",i.createElement(t.p,null,"Another way to create a sprite object is by using the Sprite constructor.\nThis constructor requires the sprite's position as its first and second parameters:"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:"language-js:title=js/stage/play.js"},'    // create background sprite\n    const background = new Sprite(w/2, h/2, { image : atlas, region : "background" });\n\n    // add sprite to scene\n    game.world.addChild(background, 1);\n')),"\n",i.createElement(t.h3,{id:"add-the-capguy-animation",style:{position:"relative"}},"Add the Capguy animation",i.createElement(t.a,{href:"#add-the-capguy-animation","aria-label":"add the capguy animation permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"Let's add an animation for the player sprite.\nTo do this, we'll inherit from the ",i.createElement(t.code,null,"Entity")," class and implement it in ",i.createElement(t.em,null,"js/renderables/player.js"),":"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:"language-js:title=js/renderables/player.js"},'class PlayerEntity extends Entity {\n\n    constructor(x, y, atlas) {\n        // call the parent constructor\n        super(x, y, { width: 210, height: 330 });\n\n        // use animation arrays exported by TexturePacker\n        const animations = loader.getJSON("cityscene").animations;\n        const walkFrames = animations["capguy/walk"];\n        const turnFrames = animations["capguy/turn"];\n\n        // create animated sprite, specify all used animation frames\n        this.renderable = atlas.createAnimationFromName([...walkFrames, ...turnFrames]);\n\n        // define animations, pass frames to be used in each animation\n        this.renderable.addAnimation("walk", walkFrames, 125);\n        this.renderable.addAnimation("turn", turnFrames, 125);\n\n        this.body.setStatic(true);\n    }\n\n});\n')),"\n",i.createElement(t.p,null,"This code initializes a basic entity and adds a Sprite as renderable component.\nTexturePacker 7.1 (and newer) detects sprites which differ only in a sequence number and\nexports them as animations. You can use the generated\nsprite name arrays to create a Sprite object with ",i.createElement(t.code,null,"createAnimationFromName()"),".\nThe ",i.createElement(t.code,null,"addAnimation()")," method adds a new animation to the sprite, expecting three parameters:"),"\n",i.createElement(t.ul,null,"\n",i.createElement(t.li,null,"The animation name: It's used to activate the animation, as we'll see later."),"\n",i.createElement(t.li,null,"The frames to use for the animation."),"\n",i.createElement(t.li,null,"The frame delay in milliseconds; in the following example: 1000 / 125 = 8 fps"),"\n"),"\n",i.createElement(t.p,null,"In melonJS, when you create an entity, it usually follows the laws of physics and gravity.\nThis means that the entity will fall down unless you disable gravity for it.\nThis is done with the ",i.createElement(t.code,null,"setStatic(true)")," call."),"\n",i.createElement(t.p,null,"Adding the animated sprite to the game is now quite simple, add the following lines to ",i.createElement(t.em,null,"play.js"),":"),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:"language-js:title=js/stage/play.js"},"    const capguy = new PlayerEntity(w/2, h*0.9, atlas);\n    game.world.addChild(capguy, 2);\n")),"\n",i.createElement(t.p,null,"If you run the demo now, you'll see 
1CapGuy walking in place, but he's not yet moving.\nTo make CapGuy move to the right, include the following code block in ",i.createElement(t.em,null,"player.js")),"\n",i.createElement(t.pre,null,i.createElement(t.code,{className:"language-js:title=js/renderables/player.js"},"    update(dt) {\n        // just manually change the guy position\n        this.pos.x += 0.3*dt;\n\n        // repeat once leaving the viewport\n        if (this.pos.x >= game.viewport.width) {\n            this.pos.x = 0;\n        }\n\n        // call the parent method\n        super.update(dt);\n        return true;\n    }\n}\n")),"\n",i.createElement(t.p,null,"This block shifts CapGuy slightly to the right. ",i.createElement(t.code,null,"dt"),"  is the time difference between the last frame\nand the current frame. Using this as a basis for the update keeps the animation speed constant.\nThe ",i.createElement(t.code,null,"if"),"  block resets CapGuy to the left border after he left to the right."),"\n",i.createElement(t.h2,{id:"summary",style:{position:"relative"}},"Summary",i.createElement(t.a,{href:"#summary","aria-label":"summary permalink",className:"anchor after"},i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}}))),"\n",i.createElement(t.p,null,"You've now learned how to create sprite sheets and use them in your melonJS project.\nTexturePacker makes it easy to handle your assets and optimize your game for size and speed."))}var o=function(e){void 0===e&&(e={});const{wrapper:t}=Object.assign({},(0,n.R)(),e.components);return t?i.createElement(t,e,i.createElement(c,e)):c(e)};var d=a(11042),p=a(77891),m=a(74110);function h(e){let{data:t,pageContext:a,children:n}=e;const s=a.pageData,r=t.mdx,l=r.tableOfContents,c=r.frontmatter.noTitleImage?null:r.frontmatter.image;return i.createElement(p.W,null,i.createElement(m.n,{pageData:s,image:c,onPageItems:l.items},n))}function u(e){return i.createElement(h,e,i.createElement(o,e))}const f=e=>{let{pageContext:t}=e;return i.createElement(i.Fragment,null,i.createElement(d.A,{pageData:t.pageData}))}},84007:function(e,t,a){a.d(t,{A:function(){return c}});var n=a(96540),i=a(77387);let s=function(e){function t(){return e.apply(this,arguments)||this}return(0,i.A)(t,e),t.prototype.render=function(){return n.createElement("svg",{version:"1.1",xmlns:"http://www.w3.org/2000/svg",className:this.props.className||"w-8 h-8",viewBox:"0 0 40 40"},n.createElement("path",{opacity:"0.2",fill:"#000",d:"M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946 s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634 c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"}),n.createElement("path",{fill:"#000",d:"M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 C22.32,8.481,24.301,9.057,26.013,10.047z"},n.createElement("animateTransform",{attributeType:"xml",attributeName:"transform",type:"rotate",from:"0 20 20",to:"360 20 20",dur:"0.5s",repeatCount:"indefinite"})))},t}(n.Component);var r=a(46942),l=a.n(r);var c=e=>{let{title:t,loadingText:a,url:i,aspect:r="aspect-4/3",className:c=""}=e;const{0:o,1:d}=(0,n.useState)(!1),{0:p,1:m}=(0,n.useState)(!1);(0,n.useEffect)((()=>{d(!0)}),[]);const h=l()("w-full bg-gray-100",r,c);return n.createElement("div",{className:l()(h,"relative")},n.createElement("div",{className:l()(h,"flex flex-col justify-center items-center absolute top-0 left-0",p?"z-0":"z-10")},n.createElement(s,{className:"block w-24 h-24"}),n.createElement("div",{className:"text-gray-400 text-3xl"},a)),o&&n.createElement("iframe",{scrolling:"no",className:l()(h,"absolute top-0 left-0",p?"z-10":"z-0"),title:t,loading:"lazy",onLoad:()=>{m(!0)},src:i}))}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.