phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
37.12k stars 7.1k forks source link

Tiles "overflow" and pick up parts of neighboring tiles #3229

Closed nkholski closed 6 years ago

nkholski commented 6 years ago

Tiles overflows sometimes, like if they were 1 pixel wider or higher and picks up part of the neighboring tile (Phaser 3.0.0 WebGL).

skarmbild fran 2018-02-14 10-07-29

http://metroid.niklasberg.se/phaser3platformer/

nicholas-ochoa commented 6 years ago

I worked around this by padding each tile with a 1px transparent gap all around. It seems to be an issue with the WebGL renderer only, not Canvas.

Ziao commented 6 years ago

As far as I'm aware this is not a Phaser issue. I believe it has to do with how WebGL handles image scaling when dealing with non-whole pixels. Have you tried pixelArt: true in the game's config?

Edit: another thing that would probably help is making sure the camera's X position is always a whole integer by rounding it: this.cameras.main.roundPixels = true;.

zdandoh commented 6 years ago

I had this same issue and this.cameras.main.roundPixels = true; fixed it for me. Thanks!

nkholski commented 6 years ago

The original issue is solved by this.cameras.main.roundPixels = true; for me too, but it introduces a new one; everything shakes.

Antriel commented 6 years ago

This is related to how GPU renders textures. Since UV mapping is inherently floating point, parts of the border pixels can bleed into the rendered image. To fix that you need to extrude your textures, i.e. repeat the border pixels of the tiles.

nkholski commented 6 years ago

Just noticed that I have the same issue even if I switch to Canvas so it's not only WebGL-related.

If we need to repeat the border pixels and this is a general thing, do anyone knows of something that does this automatically?

photonstorm commented 6 years ago

roundPixels can help in some cases, but not all. For example, if you were to zoom the camera by a non-integer value you'd also see this happen.

You'd think this would be supported by tools like Tiled but it only partially is. Tiled supports margin and spacing between tiles, which the Tiled docs state is the area in which tiles can bleed to avoid display issues like this. But to create that bleed effect is on your own back :(

This is quite a common problem, so there are various little utils out there. A cursory search found things like the Allegro extruder: https://www.allegro.cc/forums/thread/616156 or this Java based tool: https://forum.starling-framework.org/topic/tool-for-extruding-tile-edges-for-tilesets-no-more-bleeding and several others.

It's frustrating because it adds another step into your workflow. Plus I can't guarantee those utils will do what you need (I didn't test them, just searched for them) - it is, however, how you resolve it.

Perhaps we ought to create a cli / web based tile extruder for this purpose.

nkholski commented 6 years ago

I'm on it. I got a node script working but started to think that a plug-in doing this based on a tilemap passed as a argument would be cool, at least during development.

samme commented 6 years ago

The original issue is solved by this.cameras.main.roundPixels = true; for me too, but it introduces a new one; everything shakes.

Might add GameConfig.roundpixels=true also.

samme commented 6 years ago

https://gamedev.stackexchange.com/a/75506/27151

n-of-one commented 4 years ago

As @photonstorm suggested, adding an extra layer of pixels solved the problem for me. This tool was very easy to use: https://github.com/sporadic-labs/tile-extruder . Just transform your tilesheet and import it with margin=1 and padding=2.

gfordinal commented 2 weeks ago

See this alternative for a different approach:

Render Layer as Texture