Skip to content

Textures

samme edited this page Jun 8, 2021 · 42 revisions

Textures are stored in the Texture Manager, this.textures in a scene.

// List all the texture keys
console.log(this.textures.getTextureKeys()); // → ['mummy', 'bat', 'torch', …]

// Texture exists?
console.log(this.textures.exists('mummy')); // → true

There are three built-in textures: __DEFAULT (32 × 32 transparent), __MISSING (32 × 32 green slashed box), and __WHITE (2 × 2 white). You don't need to use them, but you could:

// Starfield!
this.add.blitter('__WHITE');

textures.get() always returns a texture; it will be the "missing" texture if the given texture key is not found. To avoid ambiguity, do

console.log(this.textures.exists('mummy') ? this.textures.get('mummy') : null);

Textures have a key, a default frame, a list of frames, one or more source images, and zero or more data source images (normal maps). There are two types, Texture and CanvasTexture. RenderTexture is a game object that holds a special texture.

Frames are rectangular areas on a texture. Frames have a name, position, several dimensions (realWidth and realHeight are most important), and an optional custom pivot point. The docs call frame names "names" (for atlas textures) and "indexes" (for spritesheet textures) but they are all the same thing. All textures have a special frame, named __BASE, that represents the entire texture.

// List the frame names for a texture
// 'mummy' is a spritesheet texture
console.log(this.textures.get('mummy').getFrameNames()); // → ['0', '1', '2', …]

// Get texture frame dimensions
const { name, realWidth, realHeight } = this.textures.getFrame('mummy', 1);
console.log(name, realWidth, realHeight); // → '1', 37, 45

// Show the entire texture on a game object
this.add.image(0, 0, 'mummy', '__BASE');

You can add frames to any texture, but you will likely do this only for blank textures (CanvasTexture and RenderTexture).

A game object holds its current texture and frame in texture and frame:

const mummy = this.add.sprite(0, 0, 'mummy', 1);

mummy.texture === this.textures.get('mummy'); // → true
mummy.frame === this.textures.getFrame('mummy', 1); // → true

You can set each texture's filter mode:

// Nearest-neighbor filter (pixelated)
this.textures.get('mummy').setFilterMode(Phaser.Textures.FilterMode.NEAREST);

// Linear filter (antialiased)
this.textures.get('mummy').setFilterMode(Phaser.Textures.FilterMode.LINEAR);

Textures from loaded images

This is the usual way, and the textures are created automatically once the images are downloaded.

  • load.image() creates a texture with the single frame __BASE.
  • load.image() creates a texture with frames named as integers starting from '0', plus __BASE.
  • load.atlas() creates a texture with frames named in the atlas data, plus __BASE.
  • load.multiatlas() creates the same, with multiple source images

Textures from images

If you already have a complete image or canvas somehow, you can add it to the Texture Manager directly, e.g.,

this.textures.addSpriteSheet('mummy', sourceImage, frameConfig);

The arguments for these methods are similar to those of the load() methods.

Blank textures

The blank textures are CanvasTexture and RenderTexture (actually its texture). With both of them, you draw on the __BASE frame and then add or clone frames if you need multiple frames.

Canvas Texture

A Canvas Texture is the only way to do per-pixel modifications.

const texture = this.textures.createCanvas('canvas', width, height);

// Draw another texture frame onto it
texture.drawFrame(texture, frame, x, y);

// Or use Canvas 2D
const ctx = texture.getContext();
// …

// Always refresh when finished
texture.refresh();

Render Texture

In WebGL rendering mode a Render Texture is more performant than a Canvas Texture.

A Render Texture is actually a game object. If you want to reuse the texture itself, create the game object off the scene display list and then "save" the texture to access it:

const rt = this.make.renderTexture({ width: 100, height: 100 }, false);
const texture = rt.saveTexture('bubbles');

texture.draw(/*…*/);
texture.addFrame(/*…*/);

this.add.image(0, 0, 'bubbles');

Appendix: TMI

Texture from load.image()

function preload() {
  this.load.image('image', 'image.png');
}

function create() {
  const texture = this.textures.get('image');

  console.log(texture.frameCount); // -> 1
  console.log(texture.firstFrame); // -> '__BASE'
  console.log(texture.getFrameNames()); // -> []
  console.log(texture.getFrameNames(true)); // -> [ '__BASE' ]
  console.log(texture.get()); // -> Frame { name: '__BASE', … }
}

Texture from load.spritesheet()

function preload() {
  this.load.spritesheet('spritesheet', 'spritesheet.png', { frameWidth: 16, frameHeight: 24 });
}

function create() {
  const texture = this.textures.get('spritesheet');

  console.log(texture.frameCount); // -> 6
  console.log(texture.firstFrame); // -> 0
  console.log(texture.getFrameNames()); // -> [0, 1, 2, 3, 4, 5] (6)

  const frame = texture.get(0); // -> Frame { name: 0, … }

  console.log(frame.width, frame.height); // -> 16, 24
}

Texture from load.atlas()

function preload() {
  this.load.atlas('atlas', 'atlas.png', 'atlas.json');
}

function create() {
  const texture = this.textures.get('atlas');

  console.log(texture.frameCount); // -> 4
  console.log(texture.firstFrame); // -> 'mummy'
  console.log(texture.getFrameNames()); // -> ['mummy', 'bat', 'snake', 'torch'] (4)

  const frame = texture.get('mummy'); // -> Frame { name: 'mummy', … }

  console.log(frame.width, frame.height); // -> 16, 24
}

Add frames

const texture = this.textures.get('image');

// This is a single-frame texture
console.log(texture.firstFrame); // -> '__BASE'

// Add frames, named like a spritesheet
texture.add(0, 0, 0, 0, 16, 24);
texture.add(1, 0, 16, 0, 16, 24);
texture.add(2, 0, 32, 0, 16, 24);

// Add frames, named like an atlas
texture.add('walk03', 0, 0, 48, 16, 24);
texture.add('walk04', 0, 64, 0, 16, 24);
texture.add('walk05', 0, 80, 0, 16, 24);

// `firstFrame` is the default frame
console.log(texture.firstFrame); // -> 0

Clone this wiki locally