Game Resources
As previously mentioned, your game is not permitted to make network requests. This means that it can't asynchronously load resources such as more code, images, sprites, or fonts.
By the way! Kenney is a great place for finding free assets (sprites, etc) for your games.
Any
resources needed by your game must be bundled into the game itself,
i.e., into the final build output file,
bundle.js.
Images & Sprites
ExcaliburJS uses ImageSource to
represent and load images.
To bundle an image resource into your game, you have a couple of options:
Import Images as base64-encoded Data URIs
You can import image resources as base64-encoded data URIs.
To do this, first encode your image as a base64 string. (You can find free base64
encoders online; or, on a Mac or Linux machine, for example, you can use
the base64 command; i.e., base64 -i my-image.png).
Once you have the base64-encoded string for your image file, you can then copy it into a TypeScript-importable file — for example, if your image was an SVG file:
export default 'data:image/svg+xml;base64,<base64 encoded svg>';
Or, for a PNG file (note the image/png MIME type):
export default 'data:image/png;base64,<base64 encoded png>';
Now we can import our image resource into our game and use it as a
graphic
on an Actor:
import { ..., ImageSource, ... } from 'excalibur';
import myImage from './my-image.svg'; // imports the my-image.svg.ts file
const myImageSource = new ImageSource(myImage);
const loadImgResources = () => {
return Promise.all([myImageSource.load()]);
};
export const install: XellyInstallFunction
= (context: XellyContext, engine: Engine) => {
const desiredWidth = 50;
// we still must go through async loading before we use our image:
loadImgResources().then(() => {
const myActor = new Actor({
anchor: Anchor.Zero,
scale: vec(desiredWidth / sprite.width, desiredWidth / sprite.width)
});
myActor.graphics.use(myImageSource.toSprite());
engine.add(myActor);
});
}
Use ImageSource.fromSvgString to load SVGs
You can use ImageSource.fromSvgString
to load SVG files directly from a string; no need to base64-encode them!
const arrowImageSource = ImageSource.fromSvgString(`
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
...
</svg>`)
Make sure your <svg/> tag has a width and height attribute.
Spritesheets
We can create SpriteSheets from
loaded ImageSources:
import { ..., ImageSource, SpriteSheet, ... } from 'excalibur';
import mySpriteSheet from './my-sprite-sheet.png';
const mySpriteSheetImageSource = new ImageSource(mySpriteSheet);
...
loadImgResources().then(() => {
const sheet = SpriteSheet.fromImageSource(mySpriteSheetImageSource);
// ...
};
...
Fonts
Here's how to bundle and load custom fonts:
import { ..., Font, ... } from 'excalibur';
import myFont from './MyFont.woff';
const myFontFace = new FontFace('MyFont', `url(${myFont})`);
export const install: XellyInstallFunction
= (context: XellyContext, engine: Engine) => {
myFontFace.load().then((loaded) => {
document.fonts.add(loaded);
const myFont = new Font({
color: Color.Purple,
size: 14,
family: 'MyFont',
unit: FontUnit.Px
});
engine.add(new Label({
text: "Hello, world!",
font: myFont,
pos: vec(
(engine.drawWidth - messageDimensions.width) / 2,
(engine.drawHeight - messageDimensions.height) / 2),
}));
});
}
Third-party libraries
You can bundle third-party libraries with your game, as long as your final game file isn't larger than the 500kb limit.
(For example, the example sudoku game uses the @algorithm.ts/sudoku library to generate game puzzles.)
With our rollup config,
any third-party libraries besides ExcaliburJS and
xelly.js (which are provided by the
platform) will automatically get bundled when you run npm run build.