Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Containers do not support pixel perfect input #4492

Closed
BigZaphod opened this issue Apr 25, 2019 · 3 comments
Closed

Containers do not support pixel perfect input #4492

BigZaphod opened this issue Apr 25, 2019 · 3 comments

Comments

@BigZaphod
Copy link
Contributor

Version

  • Phaser Version: 3.16.2
  • Operating system: macOS
  • Browser: Safari

Description

Containers do not seem to work correctly with pixel perfect input. I would expect them to iterate their children and perform a hit test on all of them recursively or something like that, but I don't think that's happening.

In the console, I see a stream of errors like this:
image

Example Test Code

Just make a container and add a sprite or two and then do myContainer.setInteractive({ pixelPerfect: true })

@photonstorm
Copy link
Collaborator

It's because a Container doesn't have a texture. When you interact with a Container it expects the container itself to have a hit shape defined, and it is this that's used for input detection, not the children. I will add a condition so that if you do specify pixelPerfect on a container it just ignores it, to avoid the error above, but there's no way it'll actually work.

@BigZaphod
Copy link
Contributor Author

I poked around some more in the code to see what you mean and found the function that seems to do the work here: https://github.com/photonstorm/phaser/blob/master/src/input/CreatePixelPerfectHandler.js

Based on this, I think I came up with a way it could work. This might not be comprehensive, and I'm sorry this isn't in exactly the same code formatting you use, but what about something like this?

function CreatePixelPerfectHandler (textureManager, alphaTolerance) {
  function pixelPerfectHitTest (hitArea, x, y, gameObject) {
    // if this gameObject has a texture and a frame, then it is something we can query for pixels - so do it and return the result
    if (gameObject.texture && gameObject.frame) {
      const alpha = textureManager.getPixelAlpha(x, y, gameObject.texture.key, gameObject.frame.name)
      return (alpha && alpha >= alphaTolerance)
    }

    // see if the gameObject might be a Container, and if it is, check the children looking for a hit
    if (gameObject.list) {
      for (const child of gameObject.list) {
        if (pixelPerfectHitTest(hitArea, x + child.displayOriginX, y + child.displayOriginY, child)) {
          return true
        }
      }
    }

    // we could find nothing that was hit
    return false
  }

  return pixelPerfectHitTest
}

@photonstorm
Copy link
Collaborator

The problem is that this makes some assumptions that go against how everything else works. Containers have never hit tested their children and shouldn't start doing so now really.

However, you can do exactly what you want already. Remember that when you call setInteractive() on a Game Object you don't have to give it a shape, you can give it a function instead. If you were to give it your modified pixelPerfectHitTest function above, then it would use that when hit testing the Container, which would give you the result you need in this specific case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants