Updated the Gruntfile. Also:

InputHandler.pixelPerfectOver - performs a pixel perfect check to see if any pointer is over the current object (warning: very expensive!)
InputHandler.pixelPerfectClick - performs a pixel perfect check but only when the pointer touches/clicks on the current object.
Previously using a Pixel Perfect check didn't work if the Sprite was rotated or had a non-zero anchor point, now works under all conditions + atlas frames.
This commit is contained in:
photonstorm 2014-02-11 13:23:54 +00:00
parent 43d9fc4f52
commit da878b2181
8 changed files with 24218 additions and 15495 deletions

View file

@ -11,43 +11,53 @@ module.exports = function (grunt) {
compile_dir: 'dist', compile_dir: 'dist',
src: { src: {
phaser: [ phaser: [
'build/p2.js',
'src/Intro.js', 'src/Intro.js',
'src/pixi/Pixi.js', 'src/pixi/Pixi.js',
'src/Phaser.js', 'src/Phaser.js',
'src/utils/Utils.js', 'src/utils/Utils.js',
'src/geom/Circle.js',
'src/geom/Point.js',
'src/geom/Rectangle.js',
'src/geom/Line.js',
'src/geom/Ellipse.js',
'src/geom/Polygon.js',
'src/pixi/core/Matrix.js', 'src/pixi/core/Matrix.js',
'src/pixi/core/Point.js',
'src/pixi/core/Rectangle.js',
'src/pixi/core/Polygon.js',
'src/pixi/display/DisplayObject.js', 'src/pixi/display/DisplayObject.js',
'src/pixi/display/DisplayObjectContainer.js', 'src/pixi/display/DisplayObjectContainer.js',
'src/pixi/display/Sprite.js', 'src/pixi/display/Sprite.js',
'src/pixi/display/Stage.js', 'src/pixi/display/SpriteBatch.js',
'src/pixi/extras/CustomRenderable.js',
'src/pixi/extras/Strip.js',
'src/pixi/extras/Rope.js',
'src/pixi/extras/TilingSprite.js',
'src/pixi/filters/AbstractFilter.js',
'src/pixi/filters/FilterBlock.js', 'src/pixi/filters/FilterBlock.js',
'src/pixi/primitives/Graphics.js',
'src/pixi/renderers/canvas/CanvasGraphics.js',
'src/pixi/renderers/canvas/CanvasRenderer.js',
'src/pixi/renderers/webgl/PixiShader.js',
'src/pixi/renderers/webgl/PrimitiveShader.js',
'src/pixi/renderers/webgl/StripShader.js',
'src/pixi/renderers/webgl/WebGLBatch.js',
'src/pixi/renderers/webgl/WebGLFilterManager.js',
'src/pixi/renderers/webgl/WebGLGraphics.js',
'src/pixi/renderers/webgl/WebGLRenderer.js',
'src/pixi/renderers/webgl/WebGLRenderGroup.js',
'src/pixi/renderers/webgl/WebGLShaders.js',
'src/pixi/text/BitmapText.js',
'src/pixi/text/Text.js', 'src/pixi/text/Text.js',
'src/pixi/text/BitmapText.js',
'src/pixi/display/Stage.js',
'src/pixi/utils/EventTarget.js',
'src/pixi/utils/Polyk.js',
'src/pixi/renderers/webgl/utils/WebGLShaderUtils.js',
'src/pixi/renderers/webgl/shaders/PixiShader.js',
'src/pixi/renderers/webgl/shaders/PixiFastShader.js',
'src/pixi/renderers/webgl/shaders/StripShader.js',
'src/pixi/renderers/webgl/shaders/PrimitiveShader.js',
'src/pixi/renderers/webgl/utils/WebGLGraphics.js',
'src/pixi/renderers/webgl/WebGLRenderer.js',
'src/pixi/renderers/webgl/utils/WebGLMaskManager.js',
'src/pixi/renderers/webgl/utils/WebGLShaderManager.js',
'src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js',
'src/pixi/renderers/webgl/utils/WebGLFastSpriteBatch.js',
'src/pixi/renderers/webgl/utils/WebGLFilterManager.js',
'src/pixi/renderers/webgl/utils/FilterTexture.js',
'src/pixi/renderers/canvas/utils/CanvasMaskManager.js',
'src/pixi/renderers/canvas/utils/CanvasTinter.js',
'src/pixi/renderers/canvas/CanvasRenderer.js',
'src/pixi/renderers/canvas/CanvasGraphics.js',
'src/pixi/primitives/Graphics.js',
'src/pixi/extras/TilingSprite.js',
'src/pixi/textures/BaseTexture.js', 'src/pixi/textures/BaseTexture.js',
'src/pixi/textures/Texture.js', 'src/pixi/textures/Texture.js',
'src/pixi/textures/RenderTexture.js', 'src/pixi/textures/RenderTexture.js',
'src/pixi/utils/EventTarget.js',
'src/pixi/utils/Polyk.js',
'src/core/Camera.js', 'src/core/Camera.js',
'src/core/State.js', 'src/core/State.js',
'src/core/StateManager.js', 'src/core/StateManager.js',
@ -61,6 +71,7 @@ module.exports = function (grunt) {
'src/core/Group.js', 'src/core/Group.js',
'src/core/World.js', 'src/core/World.js',
'src/core/Game.js', 'src/core/Game.js',
'src/input/Input.js', 'src/input/Input.js',
'src/input/Key.js', 'src/input/Key.js',
'src/input/Keyboard.js', 'src/input/Keyboard.js',
@ -68,62 +79,71 @@ module.exports = function (grunt) {
'src/input/MSPointer.js', 'src/input/MSPointer.js',
'src/input/Pointer.js', 'src/input/Pointer.js',
'src/input/Touch.js', 'src/input/Touch.js',
'src/input/InputHandler.js',
'src/input/Gamepad.js', 'src/input/Gamepad.js',
'src/input/SinglePad.js', 'src/input/SinglePad.js',
'src/input/GamepadButton.js', 'src/input/GamepadButton.js',
'src/input/InputHandler.js',
'src/gameobjects/Events.js', 'src/gameobjects/Events.js',
'src/gameobjects/GameObjectFactory.js', 'src/gameobjects/GameObjectFactory.js',
'src/gameobjects/BitmapData.js', 'src/gameobjects/BitmapData.js',
'src/gameobjects/Sprite.js', 'src/gameobjects/Sprite.js',
'src/gameobjects/Image.js',
'src/gameobjects/TileSprite.js', 'src/gameobjects/TileSprite.js',
'src/gameobjects/Text.js', 'src/gameobjects/Text.js',
'src/gameobjects/BitmapText.js', 'src/gameobjects/BitmapText.js',
'src/gameobjects/Button.js', 'src/gameobjects/Button.js',
'src/gameobjects/Graphics.js', 'src/gameobjects/Graphics.js',
'src/gameobjects/RenderTexture.js', 'src/gameobjects/RenderTexture.js',
'src/system/Canvas.js', 'src/system/Canvas.js',
'src/system/StageScaleMode.js', 'src/system/StageScaleMode.js',
'src/system/Device.js', 'src/system/Device.js',
'src/system/RequestAnimationFrame.js', 'src/system/RequestAnimationFrame.js',
'src/math/RandomDataGenerator.js',
'src/math/Math.js', 'src/math/Math.js',
'src/math/RandomDataGenerator.js',
'src/math/QuadTree.js', 'src/math/QuadTree.js',
'src/geom/Circle.js',
'src/geom/Point.js',
'src/geom/Rectangle.js',
'src/geom/Polygon.js',
'src/net/Net.js', 'src/net/Net.js',
'src/tween/TweenManager.js', 'src/tween/TweenManager.js',
'src/tween/Tween.js', 'src/tween/Tween.js',
'src/tween/Easing.js', 'src/tween/Easing.js',
'src/time/Time.js', 'src/time/Time.js',
'src/time/Timer.js', 'src/time/Timer.js',
'src/time/TimerEvent.js', 'src/time/TimerEvent.js',
'src/animation/AnimationManager.js', 'src/animation/AnimationManager.js',
'src/animation/Animation.js', 'src/animation/Animation.js',
'src/animation/Frame.js', 'src/animation/Frame.js',
'src/animation/FrameData.js', 'src/animation/FrameData.js',
'src/animation/AnimationParser.js', 'src/animation/AnimationParser.js',
'src/loader/Cache.js', 'src/loader/Cache.js',
'src/loader/Loader.js', 'src/loader/Loader.js',
'src/loader/LoaderParser.js', 'src/loader/LoaderParser.js',
'src/sound/Sound.js', 'src/sound/Sound.js',
'src/sound/SoundManager.js', 'src/sound/SoundManager.js',
'src/utils/Debug.js', 'src/utils/Debug.js',
'src/utils/Color.js', 'src/utils/Color.js',
'src/physics/arcade/SAT.js',
'src/physics/arcade/ArcadePhysics.js', 'src/physics/World.js',
'src/physics/arcade/Body.js', 'src/physics/PointProxy.js',
'src/physics/Body.js',
'src/particles/Particles.js', 'src/particles/Particles.js',
'src/particles/arcade/ArcadeParticles.js', 'src/particles/arcade/ArcadeParticles.js',
'src/particles/arcade/Emitter.js', 'src/particles/arcade/Emitter.js',
'src/tilemap/Tile.js', 'src/tilemap/Tile.js',
'src/tilemap/Tilemap.js', 'src/tilemap/Tilemap.js',
'src/tilemap/TilemapLayer.js', 'src/tilemap/TilemapLayer.js',
'src/tilemap/TilemapParser.js', 'src/tilemap/TilemapParser.js',
'src/tilemap/Tileset.js', 'src/tilemap/Tileset.js'
'src/PixiPatch.js'
] ]
}, },
pkg: grunt.file.readJSON('package.json'), pkg: grunt.file.readJSON('package.json'),

View file

@ -73,6 +73,8 @@ Significant API changes:
* Removed: Sprite.offset, center, topLeft, topRight, bottomRight, bottomLeft and bounds, as no longer needed internally. Use Sprite.getBounds() to derive them. * Removed: Sprite.offset, center, topLeft, topRight, bottomRight, bottomLeft and bounds, as no longer needed internally. Use Sprite.getBounds() to derive them.
* Button now extends Phaser.Image not Phaser.Sprite, all the same functionality as before remains, just no animations or physics body. * Button now extends Phaser.Image not Phaser.Sprite, all the same functionality as before remains, just no animations or physics body.
* Text.content has been replaced with Text.text. The Text class has a lot of new methods, check the docs! * Text.content has been replaced with Text.text. The Text class has a lot of new methods, check the docs!
* Loader won't set crossOrigin on Images unless it's set to something. The default is false, it used to be '' and can be any valid string.
* Sprite.input.pixelPerfect has been split into two: Sprite.input.pixelPerfectClick and Sprite.input.pixelPerfectOver (see new features)
New features: New features:
@ -88,6 +90,8 @@ New features:
* Text.inputEnabled allows you to enable all input events over Text objects: dragging, clicking, etc - anything that works on a Sprite works on Text now too. * Text.inputEnabled allows you to enable all input events over Text objects: dragging, clicking, etc - anything that works on a Sprite works on Text now too.
* Phaser.Ellipse added. A fully compatible port of the PIXI.Ellipse class, can be used in Sprite/Image hitArea tests. * Phaser.Ellipse added. A fully compatible port of the PIXI.Ellipse class, can be used in Sprite/Image hitArea tests.
* Phaser.Polygon added. A fully compatible port of the PIXI.Polygon class, can be used in Sprite/Image hitArea tests. * Phaser.Polygon added. A fully compatible port of the PIXI.Polygon class, can be used in Sprite/Image hitArea tests.
* InputHandler.pixelPerfectOver - performs a pixel perfect check to see if any pointer is over the current object (warning: very expensive!)
* InputHandler.pixelPerfectClick - performs a pixel perfect check but only when the pointer touches/clicks on the current object.
New Examples: New Examples:
@ -114,6 +118,14 @@ Bug Fixes:
* Tile had 2 properties (callback and callbackContext) that were never assigned, updated to use the proper names (thanks ratkingsimon) * Tile had 2 properties (callback and callbackContext) that were never assigned, updated to use the proper names (thanks ratkingsimon)
* Fixed an error that would occur if you used InputHandler.onInputUp and the Sprite destroys itself during the event. * Fixed an error that would occur if you used InputHandler.onInputUp and the Sprite destroys itself during the event.
* IE11 didn't populate the Device.ieVersion value. Now extracted from Trident revision, but still use Device.trident instead for IE11+ checks. * IE11 didn't populate the Device.ieVersion value. Now extracted from Trident revision, but still use Device.trident instead for IE11+ checks.
* Fixed bug in Math.angleBetween where it was using the coordinates in the wrong order.
* Previously using a Pixel Perfect check didn't work if the Sprite was rotated or had a non-zero anchor point, now works under all conditions + atlas frames.
TO DO:
* If you change the frame name of a pixel precise input Sprite, it will fail all clicks on it after the frame change.
You can view the Change Log for all previous versions at https://github.com/photonstorm/phaser/changelog.md You can view the Change Log for all previous versions at https://github.com/photonstorm/phaser/changelog.md

View file

@ -70,7 +70,6 @@
<script src="$path/src/geom/Ellipse.js"></script> <script src="$path/src/geom/Ellipse.js"></script>
<script src="$path/src/geom/Polygon.js"></script> <script src="$path/src/geom/Polygon.js"></script>
<script src="$path/src/pixi/Pixi.js"></script>
<script src="$path/src/pixi/core/Matrix.js"></script> <script src="$path/src/pixi/core/Matrix.js"></script>
<script src="$path/src/pixi/display/DisplayObject.js"></script> <script src="$path/src/pixi/display/DisplayObject.js"></script>
<script src="$path/src/pixi/display/DisplayObjectContainer.js"></script> <script src="$path/src/pixi/display/DisplayObjectContainer.js"></script>

File diff suppressed because it is too large Load diff

29
build/phaser.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -5,11 +5,13 @@ function preload() {
game.load.image('mushroom', 'assets/sprites/mushroom2.png'); game.load.image('mushroom', 'assets/sprites/mushroom2.png');
game.load.image('ball', 'assets/sprites/wizball.png'); game.load.image('ball', 'assets/sprites/wizball.png');
game.load.atlas('seacreatures', 'assets/sprites/seacreatures_json.png', 'assets/sprites/seacreatures_json.json');
} }
var image; var image;
var image2; var image2;
var jellyfish;
var down; var down;
var p; var p;
@ -18,7 +20,6 @@ var c;
function create() { function create() {
image = game.add.image(200, 200, 'mushroom'); image = game.add.image(200, 200, 'mushroom');
image2 = game.add.image(400, 200, 'ball'); image2 = game.add.image(400, 200, 'ball');
// image.rotation = 0.8; // image.rotation = 0.8;
@ -39,9 +40,18 @@ function create() {
image2.events.onInputOut.add(out, this); image2.events.onInputOut.add(out, this);
// game.input.mouse.mouseDownCallback = onMouseDown;
// game.input.mouse.mouseUpCallback = onMouseUp; jellyfish = game.add.sprite(500, 450, 'seacreatures', 'octopus0000');
// game.input.mouse.mouseMoveCallback = onMouseMove; jellyfish.inputEnabled = true;
jellyfish.anchor.set(0.5);
// jellyfish.pivot.set(jellyfish.width / 2, jellyfish.height / 2);
jellyfish.angle = 60;
jellyfish.scale.set(2);
jellyfish.input.pixelPerfectClick = true;
jellyfish.events.onInputDown.add(clicked, this);
jellyfish.events.onInputOver.add(over, this);
jellyfish.events.onInputOut.add(out, this);
} }
@ -72,10 +82,12 @@ function render() {
// var p = game.input.getLocalPosition(image); // var p = game.input.getLocalPosition(image);
// var p = game.input.getLocalPosition(image2); // var p = game.input.getLocalPosition(image2);
var p = game.input.getLocalPosition(jellyfish, game.input.activePointer);
// game.debug.renderPointInfo(p, 32, 32); game.debug.renderPointInfo(p, 32, 32);
// game.debug.renderPoint(p); game.debug.renderPoint(p);
game.debug.renderCircle(image2.hitArea); game.debug.renderText();
// game.debug.renderCircle(image2.hitArea);
} }

View file

@ -107,10 +107,22 @@ Phaser.InputHandler = function (sprite) {
this.snapOffsetY = 0; this.snapOffsetY = 0;
/** /**
* @property {number} pixelPerfect - Should we use pixel perfect hit detection? Warning: expensive. Only enable if you really need it! * Set to true to use pixel perfect hit detection when checking if the pointer is over this Sprite.
* The x/y coordinates of the pointer are tested against the image in combination with the InputHandler.pixelPerfectAlpha value.
* Warning: This is expensive, especially on mobile (where it's not even needed!) so only enable if required. Also see the less-expensive InputHandler.pixelPerfectClick.
* @property {number} pixelPerfectOver - Use a pixel perfect check when testing for pointer over.
* @default * @default
*/ */
this.pixelPerfect = false; this.pixelPerfectOver = false;
/**
* Set to true to use pixel perfect hit detection when checking if the pointer is over this Sprite when it's clicked or touched.
* The x/y coordinates of the pointer are tested against the image in combination with the InputHandler.pixelPerfectAlpha value.
* Warning: This is expensive so only enable if you really need it.
* @property {number} pixelPerfectClick - Use a pixel perfect check when testing for clicks or touches on the Sprite.
* @default
*/
this.pixelPerfectClick = false;
/** /**
* @property {number} pixelPerfectAlpha - The alpha tolerance threshold. If the alpha value of the pixel matches or is above this value, it's considered a hit. * @property {number} pixelPerfectAlpha - The alpha tolerance threshold. If the alpha value of the pixel matches or is above this value, it's considered a hit.
@ -506,7 +518,7 @@ Phaser.InputHandler.prototype = {
// Need to pass it a temp point, in case we need it again for the pixel check // Need to pass it a temp point, in case we need it again for the pixel check
if (this.game.input.hitTest(this.sprite, pointer, this._tempPoint)) if (this.game.input.hitTest(this.sprite, pointer, this._tempPoint))
{ {
if (this.pixelPerfect) if (this.pixelPerfectOver)
{ {
return this.checkPixel(this._tempPoint.x, this._tempPoint.y); return this.checkPixel(this._tempPoint.x, this._tempPoint.y);
} }
@ -526,15 +538,35 @@ Phaser.InputHandler.prototype = {
* @method Phaser.InputHandler#checkPixel * @method Phaser.InputHandler#checkPixel
* @param {number} x - The x coordinate to check. * @param {number} x - The x coordinate to check.
* @param {number} y - The y coordinate to check. * @param {number} y - The y coordinate to check.
* @param {Phaser.Pointer} [pointer] - The pointer to get the x/y coordinate from if not passed as the first two parameters.
* @return {boolean} true if there is the alpha of the pixel is >= InputHandler.pixelPerfectAlpha * @return {boolean} true if there is the alpha of the pixel is >= InputHandler.pixelPerfectAlpha
*/ */
checkPixel: function (x, y) { checkPixel: function (x, y, pointer) {
// Grab a pixel from our image into the hitCanvas and then test it // Grab a pixel from our image into the hitCanvas and then test it
if (this.sprite.texture.baseTexture.source) if (this.sprite.texture.baseTexture.source)
{ {
this.game.input.hitContext.clearRect(0, 0, 1, 1); this.game.input.hitContext.clearRect(0, 0, 1, 1);
if (x === null && y === null)
{
// Use the pointer parameter
this.game.input.getLocalPosition(this.sprite, pointer, this._tempPoint);
var x = this._tempPoint.x;
var y = this._tempPoint.y;
}
if (this.sprite.anchor.x !== 0)
{
x -= -this.sprite.texture.frame.width * this.sprite.anchor.x;
}
if (this.sprite.anchor.y !== 0)
{
y -= -this.sprite.texture.frame.height * this.sprite.anchor.y;
}
x += this.sprite.texture.frame.x; x += this.sprite.texture.frame.x;
y += this.sprite.texture.frame.y; y += this.sprite.texture.frame.y;
@ -670,6 +702,11 @@ Phaser.InputHandler.prototype = {
if (this._pointerData[pointer.id].isDown === false && this._pointerData[pointer.id].isOver === true) if (this._pointerData[pointer.id].isDown === false && this._pointerData[pointer.id].isOver === true)
{ {
if (this.pixelPerfectClick && !this.checkPixel(null, null, pointer))
{
return;
}
this._pointerData[pointer.id].isDown = true; this._pointerData[pointer.id].isDown = true;
this._pointerData[pointer.id].isUp = false; this._pointerData[pointer.id].isUp = false;
this._pointerData[pointer.id].timeDown = this.game.time.now; this._pointerData[pointer.id].timeDown = this.game.time.now;
@ -849,7 +886,7 @@ Phaser.InputHandler.prototype = {
}, },
/** /**
* Returns true if the pointer has entered the Sprite within the specified delay time (defaults to 500ms, half a second) * Returns true if the pointer has touched or clicked on the Sprite within the specified delay time (defaults to 500ms, half a second)
* @method Phaser.InputHandler#justPressed * @method Phaser.InputHandler#justPressed
* @param {Phaser.Pointer} pointer * @param {Phaser.Pointer} pointer
* @param {number} delay - The time below which the pointer is considered as just over. * @param {number} delay - The time below which the pointer is considered as just over.
@ -865,7 +902,7 @@ Phaser.InputHandler.prototype = {
}, },
/** /**
* Returns true if the pointer has left the Sprite within the specified delay time (defaults to 500ms, half a second) * Returns true if the pointer was touching this Sprite, but has been released within the specified delay time (defaults to 500ms, half a second)
* @method Phaser.InputHandler#justReleased * @method Phaser.InputHandler#justReleased
* @param {Phaser.Pointer} pointer * @param {Phaser.Pointer} pointer
* @param {number} delay - The time below which the pointer is considered as just out. * @param {number} delay - The time below which the pointer is considered as just out.

View file

@ -72,16 +72,17 @@ Phaser.Loader = function (game) {
/** /**
* You can optionally link a sprite to the preloader. * You can optionally link a sprite to the preloader.
* If you do so the Sprite's width or height will be cropped based on the percentage loaded. * If you do so the Sprites width or height will be cropped based on the percentage loaded.
* @property {Phaser.Sprite} preloadSprite * @property {Phaser.Sprite|Phaser.Image} preloadSprite
* @default * @default
*/ */
this.preloadSprite = null; this.preloadSprite = null;
/** /**
* @property {string} crossOrigin - The crossOrigin value applied to loaded images * @property {boolean|string} crossOrigin - The crossOrigin value applied to loaded images.
* @default
*/ */
this.crossOrigin = ''; this.crossOrigin = false;
/** /**
* If you want to append a URL before the path of any asset you can set this here. * If you want to append a URL before the path of any asset you can set this here.
@ -160,8 +161,7 @@ Phaser.Loader.prototype = {
this.preloadSprite.crop = new Phaser.Rectangle(0, 0, sprite.width, 1); this.preloadSprite.crop = new Phaser.Rectangle(0, 0, sprite.width, 1);
} }
sprite.crop = this.preloadSprite.crop; sprite.crop(this.preloadSprite.crop);
sprite.cropEnabled = true;
}, },
@ -773,7 +773,10 @@ Phaser.Loader.prototype = {
file.data.onerror = function () { file.data.onerror = function () {
return _this.fileError(_this._fileIndex); return _this.fileError(_this._fileIndex);
}; };
file.data.crossOrigin = this.crossOrigin; if (this.crossOrigin)
{
file.data.crossOrigin = this.crossOrigin;
}
file.data.src = this.baseURL + file.url; file.data.src = this.baseURL + file.url;
break; break;
@ -1244,7 +1247,7 @@ Phaser.Loader.prototype = {
this.preloadSprite.crop.height = Math.floor((this.preloadSprite.height / 100) * this.progress); this.preloadSprite.crop.height = Math.floor((this.preloadSprite.height / 100) * this.progress);
} }
this.preloadSprite.sprite.crop = this.preloadSprite.crop; // this.preloadSprite.sprite.crop = this.preloadSprite.crop;
} }
this.onFileComplete.dispatch(this.progress, this._fileList[previousIndex].key, success, this.totalLoadedFiles(), this._fileList.length); this.onFileComplete.dispatch(this.progress, this._fileList[previousIndex].key, success, this.totalLoadedFiles(), this._fileList.length);