import Sprite from '../Sprite';
/**
* @class Bitmap
* @memberof bitmap
* @extends Sprite
* @desc A sprite that renders an image asset
* @author Chris Peters
*/
export default class Bitmap extends Sprite {
constructor(x = 0, y = 0) {
super(x, y);
this._srcX = 0;
this._srcY = 0;
this._srcWidth = 0;
this._srcHeight = 0;
this._imageLoaded = false;
this._image = null;
this._tiling = 'no-repeat';
this._animations = {};
}
/**
* @method Bitmap#addAnimation
* @param {String} name The animation reference name
* @param {Animation} animation The animation instance
*/
addAnimation(name, animation) {
this._animations[name] = animation;
}
/**
* @method Bitmap#playAnimation
* @param {String} name The name of the animation to play
*/
playAnimation(name) {
this._playingAnimation = name;
this._animations[name].play();
}
/**
* @method Bitmap#stopAnimation
*/
stopAnimation() {
this._playingAnimation = undefined;
this._animations[name].stop();
}
/**
* Render the entity via context's drawImage
*
* @method Bitmap#render
* @param {Object} context The context object
* @param {Integer} factor The 0-1-based model of elapsed time
* @param {Integer} ticks Total elapsed ticks
*/
render(context, factor, ticks) {
if (!this._imageLoaded) {
return;
}
if (this._playingAnimation) {
const { srcX, srcY } = this._animations[this._playingAnimation].update(ticks);
this._srcX = srcX;
this._srcY = srcY;
}
context.save();
super.render(context);
if (this._tiling != 'no-repeat') {
// TODO cache pattern object
const pattern = context.createPattern(this._image, this._tiling);
context.rect(
0, 0,
this._width * this._scaleX,
this._height * this._scaleY
);
context.fillStyle = pattern;
context.fill();
} else {
context.drawImage(
this._image,
this._srcX,
this._srcY,
this._srcWidth,
this._srcHeight,
0, 0,
this._width * this._scaleX,
this._height * this._scaleY
);
}
context.restore();
}
/**
* Set the iamge to render and sets dimensions if not set
*
* @method Bitmap#setImage
* @param {String} path The image path
* @return {Bitmap}
*/
setImage(path) {
var image = new Image();
image.onload = ()=> {
this._image = image;
if (!this._srcWidth && !this._srcHeight) {
this._srcWidth = this._image.width;
this._srcHeight = this._image.height;
}
if (!this._width && !this._height) {
this._width = this._image.width;
this._height = this._image.height;
}
this._imageLoaded = true;
};
image.src = path;
return this
}
/**
* Choose how to tile the image. Can be <code>repeat</code>, <code>repeat-x</code>
* <code>repeat-y</code> or <code>no-repeat</code>. Default is <code>no-repeat</code>.
*
* @method Bitmap#setTiling
* @param {String} val The tiling value
* @return {Bitmap}
*/
setTiling(val) {
switch (val) {
case 'repeat':
case 'repeat-x':
case 'repeat-y':
case 'no-repeat':
this._tiling = val;
return this;
default:
throw new Error(
'Bitmap#setTiling: argument must be either "repeat", "repeat-x", "repeat-y", or "no-repeat".'
);
}
}
}