The Canvas Renderer has a new batchSprite method that consolidates the process of drawing a texture-based Game Object to the canvas. It processes the alpha, blend mode and matrix calculations in a single function and now is used by nearly all Game Object canvas renderers.

This commit is contained in:
Richard Davey 2018-08-03 18:53:50 +01:00
parent 921cc738d9
commit ca68904953
6 changed files with 120 additions and 130 deletions

View file

@ -85,6 +85,7 @@ The process of managing scissors in the WebGLRenderer has been completely rewrit
* The `currentBlendMode` property has been removed from the Canvas Renderer and is no longer checked by any class. Blend modes are now set directly on the context to avoid state saving invalidation.
* The `currentAlpha` property has been removed from the Canvas Renderer and is no longer checked by any class. Alpha values are now set directly on the context to avoid state saving invalidation.
* `TextureCrop` and `Crop` have a new method `resetCropObject` which generates the crop data object required by Game Objects that support cropping. This allows us to remove duplicate code from a number of Game Objects and replace it with a single function call.
* The Canvas Renderer has a new `batchSprite` method that consolidates the process of drawing a texture-based Game Object to the canvas. It processes the alpha, blend mode and matrix calculations in a single function and now is used by nearly all Game Object canvas renderers.
### Game Config Resolution Specific Bug Fixes

View file

@ -21,7 +21,7 @@
*/
var ImageCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
renderer.drawImage(src, camera, parentMatrix);
renderer.batchSprite(src, src.frame, camera, parentMatrix);
};
module.exports = ImageCanvasRenderer;

View file

@ -21,7 +21,7 @@
*/
var SpriteCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
renderer.drawImage(src, camera, parentMatrix);
renderer.batchSprite(src, src.frame, camera, parentMatrix);
};
module.exports = SpriteCanvasRenderer;

View file

@ -21,58 +21,10 @@
*/
var TextCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
if (src.text === '')
if (src.text !== '')
{
return;
renderer.batchSprite(src, src.frame, camera, parentMatrix);
}
var ctx = renderer.currentContext;
var alpha = camera.alpha * src.alpha;
if (alpha === 0)
{
// Nothing to see, so abort early
return;
}
// Blend Mode
ctx.globalCompositeOperation = renderer.blendModes[src.blendMode];
// Alpha
ctx.globalAlpha = alpha;
var canvas = src.canvas;
ctx.save();
if (parentMatrix)
{
parentMatrix.copyToContext(ctx);
}
var tx = src.x - camera.scrollX * src.scrollFactorX;
var ty = src.y - camera.scrollY * src.scrollFactorY;
if (camera.roundPixels)
{
tx |= 0;
ty |= 0;
}
ctx.translate(tx, ty);
ctx.rotate(src.rotation);
ctx.scale(src.scaleX, src.scaleY);
ctx.translate(canvas.width * (src.flipX ? 1 : 0), canvas.height * (src.flipY ? 1 : 0));
ctx.scale(src.flipX ? -1 : 1, src.flipY ? -1 : 1);
ctx.drawImage(canvas, 0, 0, canvas.width, canvas.height, -src.displayOriginX, -src.displayOriginY, canvas.width / src.style.resolution, canvas.height / src.style.resolution);
ctx.restore();
};
module.exports = TextCanvasRenderer;

View file

@ -21,85 +21,9 @@
*/
var TileSpriteCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
var ctx = renderer.currentContext;
var frame = src.frame;
src.updateCanvas();
src.updateTileTexture();
var alpha = camera.alpha * src.alpha;
if (alpha === 0)
{
// Nothing to see, so abort early
return;
}
// Blend Mode
ctx.globalCompositeOperation = renderer.blendModes[src.blendMode];
// Alpha
ctx.globalAlpha = alpha;
var dx = frame.x - (src.originX * src.width);
var dy = frame.y - (src.originY * src.height);
var tx = src.x - camera.scrollX * src.scrollFactorX;
var ty = src.y - camera.scrollY * src.scrollFactorY;
var fx = 1;
var fy = 1;
// Flipping
if (src.flipX)
{
fx = -1;
dx += src.width;
}
if (src.flipY)
{
fy = -1;
dy += src.height;
}
if (camera.roundPixels)
{
dx |= 0;
dy |= 0;
tx |= 0;
ty |= 0;
}
ctx.save();
if (parentMatrix)
{
parentMatrix.copyToContext(ctx);
}
ctx.translate(dx, dy);
ctx.translate(tx, ty);
// Flip
ctx.scale(fx, fy);
// Rotate and scale around center
ctx.translate((src.originX * src.width), (src.originY * src.height));
ctx.rotate(fx * fy * src.rotation);
ctx.scale(this.scaleX, this.scaleY);
ctx.translate(-(src.originX * src.width), -(src.originY * src.height));
// Draw
ctx.scale(src.tileScaleX, src.tileScaleY);
ctx.translate(-this.tilePositionX, -this.tilePositionY);
ctx.fillStyle = src.tileTexture;
ctx.fillRect(this.tilePositionX, this.tilePositionY, src.width / src.tileScaleX, src.height / src.tileScaleY);
ctx.restore();
renderer.batchSprite(src, src.frame, camera, parentMatrix);
};
module.exports = TileSpriteCanvasRenderer;

View file

@ -522,6 +522,119 @@ var CanvasRenderer = new Class({
this.snapshotEncoder = encoderOptions;
},
batchSprite: function (sprite, frame, camera, parentTransformMatrix)
{
var alpha = camera.alpha * sprite.alpha;
if (alpha === 0)
{
// Nothing to see, so abort early
return;
}
var ctx = this.currentContext;
var camMatrix = this._tempMatrix1;
var spriteMatrix = this._tempMatrix2;
var calcMatrix = this._tempMatrix3;
var cd = frame.canvasData;
var frameX = cd.x;
var frameY = cd.y;
var frameWidth = frame.width;
var frameHeight = frame.height;
var res = frame.source.resolution;
var x = -sprite.displayOriginX + frame.x;
var y = -sprite.displayOriginY + frame.y;
var fx = (sprite.flipX) ? -1 : 1;
var fy = (sprite.flipY) ? -1 : 1;
if (sprite.isCropped)
{
var crop = sprite._crop;
if (crop.flipX !== sprite.flipX || crop.flipY !== sprite.flipY)
{
frame.updateCropUVs(crop, sprite.flipX, sprite.flipY);
}
frameWidth = crop.cw;
frameHeight = crop.ch;
frameX = crop.cx;
frameY = crop.cy;
x = -sprite.displayOriginX + crop.x;
y = -sprite.displayOriginY + crop.y;
if (fx === -1)
{
if (x >= 0)
{
x = -(x + frameWidth);
}
else if (x < 0)
{
x = (Math.abs(x) - frameWidth);
}
}
if (fy === -1)
{
if (y >= 0)
{
y = -(y + frameHeight);
}
else if (y < 0)
{
y = (Math.abs(y) - frameHeight);
}
}
}
spriteMatrix.applyITRS(sprite.x, sprite.y, sprite.rotation, sprite.scaleX, sprite.scaleY);
camMatrix.copyFrom(camera.matrix);
if (parentTransformMatrix)
{
// Multiply the camera by the parent matrix
camMatrix.multiplyWithOffset(parentTransformMatrix, -camera.scrollX * sprite.scrollFactorX, -camera.scrollY * sprite.scrollFactorY);
// Undo the camera scroll
spriteMatrix.e = sprite.x;
spriteMatrix.f = sprite.y;
// Multiply by the Sprite matrix, store result in calcMatrix
camMatrix.multiply(spriteMatrix, calcMatrix);
}
else
{
spriteMatrix.e -= camera.scrollX * sprite.scrollFactorX;
spriteMatrix.f -= camera.scrollY * sprite.scrollFactorY;
// Multiply by the Sprite matrix, store result in calcMatrix
camMatrix.multiply(spriteMatrix, calcMatrix);
}
ctx.save();
calcMatrix.setToContext(ctx);
ctx.scale(fx, fy);
ctx.globalCompositeOperation = this.blendModes[sprite.blendMode];
ctx.globalAlpha = alpha;
ctx.drawImage(frame.source.image, frameX, frameY, frameWidth, frameHeight, x, y, frameWidth / res, frameHeight / res);
ctx.restore();
},
/**
* [description]
*