Back to the referencePixels
Pictures generated in code instead of on a canvas: procedural art, textures for shaders, and pictures that change while the game runs.
25 symbols
#blitPixelsfunctionnacatamalon
blitPixels(target: TPixels, source: TPixels, x: number, y: number, options: { flipX, flipY }) => TPixels
Lays one picture over another, the way a sprite is drawn over a background: a transparent pixel
of source leaves what was there, an opaque one replaces it, and one in between mixes the two.
It is how a sprite is put together from parts (a car from a body, wheels and a driver) or stamped
many times over a bigger picture.
Parameters
targetTPixelsThe picture drawn on.
sourceTPixelsThe picture drawn.
xnumberWhere source's top-left corner lands in target.
ynumberWhere source's top-left corner lands in target.
options{ flipX, flipY }flipX and flipY mirror source as it is drawn.
View source · pixels/draw.ts:275#clonePixelsfunctionnacatamalon
clonePixels(pixels: TPixels) => TPixels
A copy of a picture that can be painted on without touching the original.
Parameters
pixelsTPixelsThe picture to copy.
View source · pixels/edit.ts:15#createPixelsfunctionnacatamalon
createPixels(width: number, height: number, fill?: TColor) => TPixels
A new picture to paint on in code, transparent or filled with one colour: what to use instead of a
<canvas> whenever a picture has to be generated rather than drawn.
Drawn art (characters, tiles, backgrounds) is made in a pixel-art editor and loaded with
useLoadTexture. This is for the pictures nobody draws by hand: procedural variations, placeholders,
noise and masks for a shader, a picture that changes while the game runs, or art made by an agent
that has no image editor. A canvas only exists in a browser; this runs the same there, on the
native runtime and in a test.
It lives in memory only: paint it with fillRect, drawLine, fillGradient and the rest, then
make it a texture with createPixelTexture. It needs no game, so a build script or a test can make
one too.
Parameters
widthnumberIn pixels, at least 1.
heightnumberIn pixels, at least 1.
filloptionalTColorThe colour every pixel starts as. Left out, fully transparent.
Example
const tile = createPixels(16, 16, getColor('#2a6b3a'));
fillRect(tile, 0, 15, 16, 1, getColor('#1a4a28'));
View source · pixels/create_pixels.ts:34#createPixelTexturefunctionnacatamalon
createPixelTexture(source: TLoadedPixels | TPixels, paint: TPixelPaint, options?: TPixelTextureOptions) => TTexture
createPixelTexture(source: TLoadedPixels | TPixels, options?: TPixelTextureOptions) => TTexture
Turns a picture into a texture a sprite, a model's material or a shader shows like any image loaded
from a file.
It is how a game turns a generated picture into something it can show, with no image file and no
page: a procedural sky, a rock texture from noise for a model, a mask for a shader, a placeholder
while the real art is drawn. Art someone drew is loaded with useLoadTexture instead. It works the
same in the browser and on the native runtime, because nothing here draws with the page. Use it
instead of a <canvas>: a canvas only exists in a browser.
The picture can be:
- One painted in code (
createPixels). The texture is ready at once and keeps reading from the
picture: paint on it again and call updatePixelTexture to show the change (a minimap filling in,
a floor with a crater in it). paint, if given, is applied to it first.
- A drawn picture loaded to be processed (
useLoadPixels). The texture comes back at once,
still loading, the way one from useLoadTexture does, and whatever shows it appears when the file
has arrived. paint then receives a copy of the picture, so the loaded one, shared by everyone
who loaded the file, is never changed: a palette swap, a white silhouette for a hit, an outline.
Asked again for a key it already made at the same size, it gives that texture back with the new
picture uploaded into it, so a scene that restarts does not pile up textures.
A scene document can name a texture made here but cannot carry it, since there is no file to fetch:
make it again under the same key before loading the document.
Parameters
sourceTLoadedPixels | TPixelsThe picture: one from createPixels, or one from useLoadPixels.
paintTPixelPaintChanges the picture before it is uploaded. With a loaded picture it gets a copy.
optionsoptionalTPixelTextureOptionskey to keep it by name.
Example
const Level = () => {
// Painted in code.
const art = createPixels(16, 16, getColor('#1d2b53'));
fillCircle(art, 8, 8, 6, getColor('#ffec27'));
createSprite({ texture: createPixelTexture(art), width: 64, height: 64 });
// A drawn sprite in another colour, made from the one file.
const hero = useLoadPixels({ src: '/assets/hero.png' });
const red = createPixelTexture(hero, (p) => swapColors(p, [[getColor('#3a7bff'), getColor('#e23d3d')]]));
createSprite({ texture: red, width: 32, height: 32 });
return createScene();
};
View source · gameobjects/pixel_texture/create_pixel_texture.ts:125#drawCirclefunctionnacatamalon
drawCircle(pixels: TPixels, cx: number, cy: number, radius: number, color: TColor) => TPixels
Draws the outline of a circle, one pixel thick, with no gaps and no pixel drawn twice.
Parameters
pixelsTPixelsThe picture.
cxnumberIts centre, from the left.
cynumberIts centre, from the top.
View source · pixels/draw.ts:226#drawLinefunctionnacatamalon
drawLine(pixels: TPixels, x0: number, y0: number, x1: number, y1: number, color: TColor) => TPixels
Draws a line one pixel thick between two points, with the stepped edge of the era and no
smoothing: each pixel is either on the line or not.
Parameters
pixelsTPixelsThe picture.
x0numberWhere it starts, from the left.
y0numberWhere it starts, from the top.
x1numberWhere it ends, from the left.
y1numberWhere it ends, from the top.
View source · pixels/draw.ts:111#fillCheckerfunctionnacatamalon
fillChecker(pixels: TPixels, size: number, a: TColor, b: TColor) => TPixels
Fills the picture with a checkerboard: the first texture every 3D scene is tried with, because it
shows at a glance whether a surface is stretched, mirrored or seen from the wrong side.
Parameters
pixelsTPixelsThe picture.
sizenumberHow many pixels wide one square is.
aTColorThe colour of the top-left square.
View source · pixels/fill.ts:254#fillCirclefunctionnacatamalon
fillCircle(pixels: TPixels, cx: number, cy: number, radius: number, color: TColor) => TPixels
Fills a circle. Its edge is stepped, one pixel or none, the way a circle drawn by hand on a grid
looks, and it is exactly the edge drawCircle draws for the same radius.
Painted with a transparent colour, it cuts a round hole: the crater in a destructible floor.
Parameters
pixelsTPixelsThe picture.
cxnumberIts centre, from the left.
cynumberIts centre, from the top.
radiusnumberIn pixels. 0 is a single pixel.
colorTColorWhat it is filled with.
Example
const sun = createPixels(33, 33);
fillCircle(sun, 16, 16, 15, getColor('#ffd75a'));
View source · pixels/draw.ts:172#fillGradientfunctionnacatamalon
fillGradient(pixels: TPixels, options: TFillGradientOptions) => TPixels
Fills the picture with a gradient, smooth or cut into the flat bands of a sky from the era, with an
ordered dither between the bands if you want it.
Parameters
pixelsTPixelsThe picture.
optionsTFillGradientOptionsThe colours, the direction and how it is stepped.
Example
const sky = createPixels(320, 120);
fillGradient(sky, {
colors: ['#140a33', '#5a1667', '#e0446e', '#ffb36b'].map((hex) => getColor(hex)),
bands: 12,
dither: true,
});
View source · pixels/fill.ts:80#fillNoisefunctionnacatamalon
fillNoise(pixels: TPixels, options: TFillNoiseOptions) => TPixels
Fills the picture with smooth noise: clouds, rock, water, a height map for terrain, or a texture
for a shader to read.
It tiles without a seam: the right edge runs on into the left one and the bottom into the top,
so a model can repeat it (wrap: 'repeat') with no visible joins. For that, the blobs are fitted
to a whole number across the picture, so scale is followed as closely as that allows.
Parameters
pixelsTPixelsThe picture.
optionsTFillNoiseOptionsWhich noise, how big and between which colours.
Example
// A tiling rock texture for a model.
const rock = fillNoise(createPixels(64, 64), {
seed: 7, scale: 16, octaves: 4, from: getColor('#2b2730'), to: getColor('#8a8090'),
});
createMaterial({ name: 'rock', shader: 'mesh3d', texture: createPixelTexture(rock), wrap: 'repeat' });
View source · pixels/fill.ts:187#fillRectfunctionnacatamalon
fillRect(pixels: TPixels, x: number, y: number, width: number, height: number, color: TColor) => TPixels
Fills a rectangle with one colour, cut to the picture's edges.
Parameters
pixelsTPixelsThe picture.
widthnumberHow wide, in pixels.
heightnumberHow tall, in pixels.
colorTColorWhat it is filled with.
Example
const bar = createPixels(64, 6, getColor('#200a0a'));
fillRect(bar, 1, 1, 40, 4, getColor('#e23d3d'));
View source · pixels/draw.ts:81#getPixelfunctionnacatamalon
getPixel(pixels: TPixels, x: number, y: number) => TColor
Reads one pixel. Outside the picture it is fully transparent black.
Reading the picture is also how a game asks questions of it: whether a pixel of a destructible
floor is still solid, which colour a minimap shows somewhere.
Parameters
pixelsTPixelsThe picture.
xnumberFrom the left edge, in pixels.
ynumberFrom the top edge, in pixels.
View source · pixels/draw.ts:49#mapPixelsfunctionnacatamalon
mapPixels(pixels: TPixels, fn: (color: TColor, x: number, y: number) => TColor) => TPixels
Works out every pixel again from what it is and where it is: for anything the other functions do
not draw. A recolour, a shading by height, a pattern of your own.
Parameters
pixelsTPixelsThe picture.
fn(color: TColor, x: number, y: number) => TColorGiven each pixel's colour and position, returns what it becomes.
Example
// Brick: rows of 8 pixels, every other row shifted by half a brick, with a darker mortar line.
mapPixels(wall, (color, x, y) =>
y % 8 === 0 || (x + (Math.floor(y / 8) % 2) * 8) % 16 === 0 ? mortar : brick);
View source · pixels/draw.ts:343#setPixelfunctionnacatamalon
setPixel(pixels: TPixels, x: number, y: number, color: TColor) => TPixels
Sets one pixel. Outside the picture it does nothing.
Parameters
pixelsTPixelsThe picture.
xnumberFrom the left edge, in pixels.
ynumberFrom the top edge, in pixels.
colorTColorWhat it becomes, replacing what was there.
View source · pixels/draw.ts:25#swapColorsfunctionnacatamalon
swapColors(pixels: TPixels, pairs: typeOperator) => TPixels
Replaces colours with others, exactly: every pixel that is one of the from colours, alpha
included, becomes its to. Every other pixel is left alone.
It is the palette swap of the consoles of the era: one drawn enemy, and the red, blue and gold
versions made from it, with no extra picture drawn. Swaps are worked out from the picture as it
was, so swapping red for blue and blue for red at once trades them rather than turning both blue.
Parameters
pixelsTPixelsThe picture, changed in place.
pairstypeOperatorEach colour to replace, and what replaces it.
Example
const hero = useLoadPixels({ src: '/assets/hero.png' });
const red = createPixelTexture(hero, (p) => swapColors(p, [[getColor('#3a7bff'), getColor('#e23d3d')]]));
View source · pixels/edit.ts:44#updatePixelTexturefunctionnacatamalon
updatePixelTexture(texture: TTexture, region?: TPixelRegion) => void
Shows what has been painted on a picture since its texture was made or last updated.
Only the part asked for is sent to the graphics card, so a game that changes a little of a big
picture every frame (a crater, a revealed patch of map) passes region and stays cheap. Left out,
the whole picture is sent.
Parameters
textureTTextureA texture createPixelTexture made.
regionoptionalTPixelRegionThe rectangle that changed, in the picture's pixels. It is cut to the picture.
Example
fillCircle(ground, hitX, hitY, 6, getColor('transparent'));
updatePixelTexture(groundTexture, { x: hitX - 6, y: hitY - 6, width: 13, height: 13 });
View source · gameobjects/pixel_texture/create_pixel_texture.ts:273#useLoadPixelsfunctionhooknacatamalon
useLoadPixels(options: TUseLoadPixelsOptions) => TLoadedPixels
Loads a drawn picture as pixels, to process it in code: a palette swap, a white silhouette for
a hit, an outline, a collision mask taken from the drawing, a level read from an image.
To just show a drawn picture, use useLoadTexture: that is the normal way, and faster, because
the picture goes straight to the graphics card. This is for when the game has to read or change
the drawing first. It reads PNG files, decoded in plain JavaScript with no canvas, so it works the
same in the browser and on the native runtime.
It hands back a record at once, still loading, the way every loader does; useLoader counts it.
Give it straight to createPixelTexture with a function that changes it: the texture appears by
itself when the file arrives, and the function works on a copy. Once status is 'ready', its
pixels can be read as well (with getPixel) but not painted on: the picture is shared by every
scene that loads the same file.
Parameters
optionsTUseLoadPixelsOptionsWhere the file is, and the name to keep it under.
Example
const Level = () => {
const hero = useLoadPixels({ src: '/assets/hero.png' });
const gold = createPixelTexture(hero, (p) => swapColors(p, [[getColor('#3a7bff'), getColor('#ffd75a')]]));
createSprite({ texture: gold, width: 32, height: 32 });
return createScene();
};
View source · hooks/loaders/use_load_pixels.ts:57#TFillGradientOptionstypenacatamalon
What fillGradient is asked for.
Properties
fromoptionalTColorThe colour it starts at. With to, a gradient between two colours.
tooptionalTColorThe colour it ends at.
colorsoptionaltypeOperatorSeveral colours, evenly spaced, in place of from and to: a sunset from deep blue through
purple and red to orange.
directionoptional'down' | 'right''down' (default) runs from the top edge to the bottom one; 'right' from left to right.
bandsoptionalnumberHow many flat steps it is cut into, the way a sky was drawn when a game had few colours to
spare. Left out or below 2, it is smooth.
ditheroptionalbooleanBreaks the line between two steps with the ordered pattern the dither() effect uses, so the
steps blend into each other instead of meeting in a hard edge. Only with bands.
regionoptionalTPixelRegionOnly this rectangle is painted, and the gradient runs across it. Left out, the whole picture.
View source · pixels/fill.ts:24#TFillNoiseOptionstypenacatamalon
What fillNoise is asked for.
Properties
seedoptionalnumberWhich noise. The same seed always gives the same picture. Default 1.
scaleoptionalnumberHow big its blobs are, in pixels. Default 8.
octavesoptionalnumberHow many layers of finer detail are added, each half the size and half as strong. Default 1;
4 or so for clouds and rock.
fromoptionalTColorThe colour of the lowest values. Default black.
tooptionalTColorThe colour of the highest values. Default white.
View source · pixels/fill.ts:138#TLoadedPixelstypenacatamalon
A picture file loaded as pixels, to process in code: what useLoadPixels hands back.
pixels is null until status is 'ready'. Read it as much as you like (a collision mask, a
level drawn as an image); to change it, hand the record to createPixelTexture with a function,
which paints on a copy. The picture is shared by everyone who loaded the same file, so painting
on it directly would change it for all of them.
Properties
type'loaded-pixels'keystringWhat it is cached under in this game. The src unless a key was given.
srcstringWhere the file comes from.
pixelsTPixels | nullThe picture, once it has arrived.
View source · loaders/pixels/types/t_loaded_pixels.ts:16#TPixelPainttypenacatamalon
TPixelPaint: (pixels: TPixels) => TPixels | void
What createPixelTexture hands a picture to before uploading it: change it in place, or return a
picture of your own.
View source · gameobjects/pixel_texture/create_pixel_texture.ts:55#TPixelRegiontypenacatamalon
A rectangle of a picture, in its pixels, from its top-left corner.
Properties
xnumberynumberwidthnumberheightnumber
View source · pixels/types/t_pixels.ts:32#TPixelstypenacatamalon
A picture held in memory, to paint on in code and then hand to createPixelTexture: the engine's
replacement for drawing on a <canvas>, which only exists in a browser. Drawn art is loaded with
useLoadTexture instead; this is for pictures that are generated.
Four bytes a pixel (red, green, blue, alpha, each 0 to 255), row after row, with row 0 at the
top: the same way round as an image file and as the game's own y. Nothing in it touches the
graphics card, the page or a game, so the same picture can be painted in a scene, in a test, in a
build script or on the native runtime and comes out byte for byte the same.
data is yours to read and write directly when the painting functions are not enough; it is
width × height × 4 long and never replaced.
Properties
type'pixels'widthnumberheightnumberdataUint8Array
View source · pixels/types/t_pixels.ts:18#TPixelTextureOptionstypenacatamalon
What createPixelTexture is asked for.
Properties
keyoptionalstringA name, so the texture outlives the scene that made it and another scene can find it with
createSprite({ key }). Left out, it belongs to the part of the scene that made it and goes
when that goes.
View source · gameobjects/pixel_texture/create_pixel_texture.ts:64#TUseLoadPixelsOptionstypenacatamalon
What useLoadPixels is asked for.
Properties
srcstringWhere the PNG is.
keyoptionalstringWhat to keep it under, so another scene can reach the same one. Defaults to src.
View source · hooks/loaders/use_load_pixels.ts:14