Jump to content

Phaser.Button hitbox disregarding the width/height of the button.


Recommended Posts

I have just updated to the latest in the dev branch, and was going over my existing code to make sure it all still works, and I found a problem with some buttons.


I have a Phaser.Button that use an image (720px by 249 px) with 3 frames (720px by 83px).

During execution, I change the size of the button using the width and height properties.

this.button.width = 300;this.button.height = 50;

On some occasions, the buttons need to be half the width of the frame, and about two thirds the height.

On these occasions, I notice that the hit box for the button is still the original frame size, while the sprite is being drawn at the expected size.

In the previous version of Phaser I had, the hitbox was resizing with the rest of the button.


After some small investigation, I found that I could get this to work as expected by slightly altering the checkPointerOver function in Input/InputHandler.js.

When checking to see if the pointer is over the button, the code uses this.sprite.texture.frame.width and this.sprite.texture.frame.height,

and that is always set to the original size of the frame. It doesn't take into account that I have resized the button to be smaller than this.


This is my revised code, from line 478. I commented out the existing lines and added my modification below them to show the difference.

checkPointerOver: function (pointer) {        if (this.enabled && this.sprite.visible)        {            this.sprite.getLocalUnmodifiedPosition(this._tempPoint, pointer.x, pointer.y);            //  Check against bounds first (move these to private vars)            //var x1 = -(this.sprite.texture.frame.width) * this.sprite.anchor.x; //Original Line            var x1 = -(this.sprite.width) * this.sprite.anchor.x;            var y1;                        //if (this._tempPoint.x > x1 && this._tempPoint.x < x1 + this.sprite.texture.frame.width) //Original Line            if (this._tempPoint.x > x1 && this._tempPoint.x < x1 + this.sprite.width)            {                //y1 = -(this.sprite.texture.frame.height) * this.sprite.anchor.y; //Original Line                y1 = -(this.sprite.height) * this.sprite.anchor.y;                            //if (this._tempPoint.y > y1 && this._tempPoint.y < y1 + this.sprite.texture.frame.height) //Original Line                if (this._tempPoint.y > y1 && this._tempPoint.y < y1 + this.sprite.height)                {                    if (this.pixelPerfect)                    {                        return this.checkPixel(this._tempPoint.x, this._tempPoint.y);                    }                    else                    {                        return true;                    }                }            }        }        return false;    },

I don't know if this has any other effects in other places, but my testing so far has not come up with any other unexpected behaviours.

I'm not using pixelPerfect checking anywhere, so I didn't look at that..


Also, now that I have updated phaser, my entire phaser source folder is showing that I have made changes, so I dont want to try sort it out to make a pull request. Git be scary.

Link to comment
Share on other sites

I have just found one of those effects in other places.


It seems that while it works in one area of our project, this fix breaks another area.


In both places I am setting the width of Phaser.Button objects directly.

With this fix, place A works fine, place B has hit box issues where the hit box is not only too small, but also not in the right place.

Without this fix, place B works fine, place A has hit boxes that are the width of the source image instead of what I am setting the button to.


So, it is back to work for me...



after lunch.

Link to comment
Share on other sites

Found the probem...

The difference between place A and B was that in place B, we are explicitly calling button.updateTransform(), while in place A we are not.

Also it has some fancy code that messes with rotations.

It seems that when setting the scale or dimensions of a sprite, its transform is not being updated,but rotating it, it does.


My current workaround is to store all my buttons in a PIXI.DisplayObjectContainer that has a rotation of 0.0000001.



Co-dev just implemented this change in our copy of phaser which seems to have solved our issue:


in Phaser/src/gameobjects/Sprite.js,  line 396, replace existing if statement with:

if (        this.worldTransform[0] != this._cache.a00 ||        this.worldTransform[4] != this._cache.a11 ||        this.worldTransform[1] != this._cache.i01 ||        this.worldTransform[3] != this._cache.i10        )
Link to comment
Share on other sites

I've literally spent hours tonight overhauling the way Sprite bounds work, and thus fixing the issue you were seeing above with buttons being incorrect, etc. Have also fixed pixel perfect checks so they work regardless of sprite being in an atlas or not.


Everything is now pushed to the dev branch and I created several new tests that show the buttons working regardless of rotation, scale, anchor or any of those coming from a parent object.

Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...