import GameObject from './GameObject.js';
import BitmapFontMetrics from './BitmapFontMetrics.js';
/**
* Renders text by copying parts of a bitmap (usually displaying a font or letters of some sort)
*
* @extends module:gameobjects~GameObject
* @memberof module:gameobjects~
*/
class BitmapText extends GameObject {
/**
* @param {object} config - A config object that sets some basic properties.
* @param {number} [config.x=0] - The game object's x position. See [textAlign]{@link module:gameobjects~BitmapText#textAlign}.
* @param {number} [config.y=0] - The game object's top y position.
* @param {string} config.text - The string to use.
* @param {string} config.font - The name of the image asset.
* @param {string} [config.textAlign=center] - The alignement of the text. 'left', 'right' or 'center'.
* @param {module:gameobjects~BitmapFontMetrics} [config.metrics] - A configuration object describing the positions of the characters.
* @param {string} [config.fillStyle=undefined] - A color to overlay on the opaque areas of the font. If undefined, no coloring is applied.
*/
constructor ({
x = 0,
y = 0,
text = '',
font = undefined,
textAlign = 'center',
metrics = undefined,
fillStyle = undefined
} = {})
{
super({x, y});
this._lines = [];
this.text = text;
this.font = font;
this.textAlign = textAlign;
this.redraw = true;
if (metrics) {
this.metrics = metrics;
} else {
this.metrics = new BitmapFontMetrics();
}
this.fillStyle = fillStyle;
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d');
}
/**
* The game object's x position. See [textAlign]{@link module:gameobjects~BitmapText#textAlign}.
*
* @name module:gameobjects~BitmapText#x
* @memberof module:gameobjects~BitmapText
* @type {number}
*/
/**
* The game object's top y position.
*
* @name module:gameobjects~BitmapText#y
* @memberof module:gameobjects~BitmapText
* @type {number}
*/
/**
* Draws the text to the screen.
*
* @param {CanvasRenderingContext2D} context - The translated canvas context.
*/
draw (context)
{
if (this.font == undefined) {
return;
}
if (this.redraw) {
this.redraw = false;
let charWidth = Math.max(...(this._lines.map(str => str.length)));
this.canvas.width = this.width = charWidth * this.metrics.width;
this.canvas.height = this.height = this._lines.length * this.metrics.height;
this.context.clearRect(0, 0, this.width, this.height);
let x = 0;
let y = 0;
this._lines.forEach((line) => {
let lineOffsetX = 0;
if (this.textAlign == 'center') {
lineOffsetX = (this.width - line.length * this.metrics.width) / 2;
}
if (this.textAlign == 'right') {
lineOffsetX = this.width - line.length * this.metrics.width;
}
line.split('').forEach((char) => {
let pos = this.metrics.getCharData(char);
let img = this.scene.assets.getByName(this.font);
if (img) {
let xDest = x * this.metrics.width + lineOffsetX;
let yDest = y * this.metrics.height;
this.context.drawImage(img, pos.x, pos.y, this.metrics.width, this.metrics.height, xDest, yDest, this.metrics.width, this.metrics.height);
}
x++;
});
x = 0;
y++;
});
if (this.fillStyle) {
this.context.save();
this.context.fillStyle = this.fillStyle;
this.context.globalCompositeOperation = 'source-atop';
this.context.fillRect(0, 0, this.width, this.height);
this.context.restore();
}
}
// copy the buffer onto the scene
let offsetX = 0;
if (this.textAlign == 'center') {
offsetX = - this.width / 2;
}
if (this.textAlign == 'right') {
offsetX = - this.width;
}
context.drawImage(this.canvas, offsetX, 0);
}
/**
* The string that will be rendered.
*
* @type {string}
*/
get text()
{
return this._text;
}
set text(text)
{
this._text = text;
this._lines = text.split('\n');
this.redraw = true;
}
/**
* The alignement of the text. 'left', 'right' or 'center'. If the alignement is 'left', the text is drawn from the x onwards to the left. When the alignement is 'center', x will be in the middle. If the 'aligenment' is right, the text is drawn from x tot the right.
*
* @type {string}
*/
get textAlign()
{
return this._textAlign;
}
set textAlign(textAlign)
{
this._textAlign = textAlign;
this.redraw = true;
}
}
export default BitmapText;