Pixel Perfect click detection now works even if the Sprite is part of a texture atlas.

This commit is contained in:
photonstorm
2013-10-25 05:40:46 +01:00
parent 1294b3a2b9
commit 2921a6de2e
11 changed files with 135 additions and 66 deletions
+1
View File
@@ -400,6 +400,7 @@ Phaser.Game.prototype = {
this.plugins.preUpdate();
this.physics.preUpdate();
this.stage.update();
this.input.update();
this.tweens.update();
this.sound.update();
+30
View File
@@ -61,6 +61,18 @@ Phaser.Stage = function (game, width, height) {
*/
this.aspectRatio = width / height;
/**
* @property {number} _nextOffsetCheck - The time to run the next offset check.
* @private
*/
this._nextOffsetCheck = 0;
/**
* @property {number|false} checkOffsetInterval - The time (in ms) between which the stage should check to see if it has moved.
* @default
*/
this.checkOffsetInterval = 2500;
};
Phaser.Stage.prototype = {
@@ -93,6 +105,24 @@ Phaser.Stage.prototype = {
window.onblur = this._onChange;
window.onfocus = this._onChange;
},
/**
* Runs Stage processes that need periodic updates, such as the offset checks.
* @method Phaser.Stage#update
*/
update: function () {
if (this.checkOffsetInterval !== false)
{
if (this.game.time.now > this._nextOffsetCheck)
{
Phaser.Canvas.getOffset(this.canvas, this.offset);
this._nextOffsetCheck = this.game.time.now + this.checkOffsetInterval;
}
}
},
/**
+9 -11
View File
@@ -392,6 +392,7 @@ Phaser.Sprite.prototype.updateCache = function() {
if (this.worldTransform[1] != this._cache.i01 || this.worldTransform[3] != this._cache.i10)
{
console.log('updateCache wt', this.name);
this._cache.a00 = this.worldTransform[0]; // scaleX a
this._cache.a01 = this.worldTransform[1]; // skewY c
this._cache.a10 = this.worldTransform[3]; // skewX b
@@ -430,13 +431,8 @@ Phaser.Sprite.prototype.updateAnimation = function() {
if (this._cache.dirty && this.currentFrame)
{
console.log('ua frame 2 change', this.name);
// this._cache.width = Math.floor(this.currentFrame.sourceSizeW * this._cache.scaleX);
// this._cache.height = Math.floor(this.currentFrame.sourceSizeH * this._cache.scaleY);
this._cache.width = this.currentFrame.width;
this._cache.height = this.currentFrame.height;
// this._cache.width = Math.floor(this.currentFrame.sourceSizeW);
// this._cache.height = Math.floor(this.currentFrame.sourceSizeH);
this._cache.halfWidth = Math.floor(this._cache.width / 2);
this._cache.halfHeight = Math.floor(this._cache.height / 2);
@@ -540,14 +536,16 @@ Phaser.Sprite.prototype.getLocalPosition = function(p, x, y, sx, sy) {
* @param {number} y - Description.
* @return {Description} Description.
*/
Phaser.Sprite.prototype.getLocalUnmodifiedPosition = function(p, x, y) {
Phaser.Sprite.prototype.getLocalUnmodifiedPosition = function(p, gx, gy) {
p.x = this._cache.a11 * this._cache.idi * x + -this._cache.i01 * this._cache.idi * y + (this._cache.a12 * this._cache.i01 - this._cache.a02 * this._cache.a11) * this._cache.idi;
p.y = this._cache.a00 * this._cache.idi * y + -this._cache.i10 * this._cache.idi * x + (-this._cache.a12 * this._cache.a00 + this._cache.a02 * this._cache.i10) * this._cache.idi;
var a00 = this.worldTransform[0], a01 = this.worldTransform[1], a02 = this.worldTransform[2],
a10 = this.worldTransform[3], a11 = this.worldTransform[4], a12 = this.worldTransform[5],
id = 1 / (a00 * a11 + a01 * -a10),
x = a11 * id * gx + -a01 * id * gy + (a12 * a01 - a02 * a11) * id,
y = a00 * id * gy + -a10 * id * gx + (-a12 * a00 + a02 * a10) * id;
// apply anchor
p.x += (this.anchor.x * this._cache.width);
p.y += (this.anchor.y * this._cache.height);
p.x = x + (this.anchor.x * this._cache.width);
p.y = y + (this.anchor.y * this._cache.height);
return p;
+8 -36
View File
@@ -484,47 +484,19 @@ Phaser.InputHandler.prototype = {
{
this.sprite.getLocalUnmodifiedPosition(this._tempPoint, pointer.x, pointer.y);
// The unmodified position is being offset by the anchor, i.e. into negative space
// var x = this.sprite.anchor.x * this.sprite.width;
// var y = this.sprite.anchor.y * this.sprite.height;
var x = 0;
var y = 0;
// check world transform
if (this.sprite.worldTransform[3] == 0 && this.sprite.worldTransform[1] == 0)
if (this._tempPoint.x >= 0 && this._tempPoint.x <= this.sprite.currentFrame.width && this._tempPoint.y >= 0 && this._tempPoint.y <= this.sprite.currentFrame.height)
{
// Un-rotated (but potentially scaled)
if (this._tempPoint.x >= x && this._tempPoint.x <= this.sprite.width && this._tempPoint.y >= y && this._tempPoint.y <= this.sprite.height)
if (this.pixelPerfect)
{
return true;
return this.checkPixel(this._tempPoint.x, this._tempPoint.y);
}
}
else
{
// Rotated (and could be scaled too)
if (this._tempPoint.x >= x && this._tempPoint.x <= this.sprite.currentFrame.width && this._tempPoint.y >= y && this._tempPoint.y <= this.sprite.currentFrame.height)
else
{
return true;
}
}
}
// if (this.pixelPerfect)
// {
// return this.checkPixel(this._tempPoint.x, this._tempPoint.y);
// }
// else
// {
// return true;
// }
// }
// }
// }
// }
return false;
},
@@ -538,16 +510,16 @@ Phaser.InputHandler.prototype = {
*/
checkPixel: function (x, y) {
x += (this.sprite.texture.frame.width * this.sprite.anchor.x);
y += (this.sprite.texture.frame.height * this.sprite.anchor.y);
// Grab a pixel from our image into the hitCanvas and then test it
if (this.sprite.texture.baseTexture.source)
{
this.game.input.hitContext.clearRect(0, 0, 1, 1);
// This will fail if the image is part of a texture atlas - need to modify the x/y values here
x += this.sprite.texture.frame.x;
y += this.sprite.texture.frame.y;
this.game.input.hitContext.drawImage(this.sprite.texture.baseTexture.source, x, y, 1, 1, 0, 0, 1, 1);
var rgb = this.game.input.hitContext.getImageData(0, 0, 1, 1);
+15 -13
View File
@@ -206,25 +206,27 @@ Phaser.Utils.Debug.prototype = {
if (showBounds)
{
this.context.strokeStyle = 'rgba(255,0,0,1)';
this.context.beginPath();
this.context.strokeStyle = 'rgba(0, 255, 0, 0.7)';
this.context.strokeRect(sprite.bounds.x, sprite.bounds.y, sprite.bounds.width, sprite.bounds.height);
this.context.closePath();
this.context.stroke();
}
// this.context.beginPath();
// this.context.moveTo(sprite.topLeft.x, sprite.topLeft.y);
// this.context.lineTo(sprite.topRight.x, sprite.topRight.y);
// this.context.lineTo(sprite.bottomRight.x, sprite.bottomRight.y);
// this.context.lineTo(sprite.bottomLeft.x, sprite.bottomLeft.y);
// this.context.closePath();
// this.context.strokeStyle = 'rgba(255,0,0,1)';
// this.context.stroke();
this.context.beginPath();
this.context.moveTo(sprite.topLeft.x, sprite.topLeft.y);
this.context.lineTo(sprite.topRight.x, sprite.topRight.y);
this.context.lineTo(sprite.bottomRight.x, sprite.bottomRight.y);
this.context.lineTo(sprite.bottomLeft.x, sprite.bottomLeft.y);
this.context.closePath();
this.context.strokeStyle = 'rgba(255, 0, 255, 0.7)';
this.context.stroke();
this.renderPoint(sprite.center);
this.renderPoint(sprite.topLeft, 'rgb(255,255,0)');
this.renderPoint(sprite.topRight, 'rgb(255,0,0)');
this.renderPoint(sprite.bottomLeft, 'rgb(0,0,255)');
this.renderPoint(sprite.bottomRight, 'rgb(255,255,255)');
this.renderPoint(sprite.topLeft);
this.renderPoint(sprite.topRight);
this.renderPoint(sprite.bottomLeft);
this.renderPoint(sprite.bottomRight);
if (showText)
{