Bug fix for Carcassonne display
Posted: 02 March 2020, 01:02
I've been doing some digging into a display bug (#6090) which affects Carcassonne when run on Safari (either on Mac OS or iPhone/iPad). I believe I've identified the cause, but Carcassonne (developed by Board Game Arena) isn't a project on BGA Studio so I can't clone it to test a change to the javascript (I can see the minified version but can't run any changed code). Is there any way I could either get access to the original source project, or could someone have a look at the below and see if my hypothesis works?
If the view is zoomed in or out from its default size at all, the bug manifests as tiles which are offset by a few pixels in one direction. At small sizes (including the default view in portrait on my iPhone 6S) the error can be a significant proportion of the tile, so it gets confusing to see what's going on. The offset is always in the tile's vertical direction, but tiles can be displayed with 90 degree rotation, so the displacement on screen can be in any direction. (Also you may notice that tiles change displacement when the map scrolls even if the zoom stays the same - but only if the whole interface is being zoomed smaller for being drawn on small screens).
A tile looks something like this (I've simplified it a bit):
Note that the size of div tile_35 is a non-integer number of pixels. The background-position of tile_art_35 is specified as a percentage, of the size of this div - which should be the same as the size of a tile, but it looks like Safari is rounding to an integer number of pixels that the box actually occupies on the screen, and using that rounded value in the calculation of what part of the image should be displayed. Up to half-a-pixel difference, multiplied by percentages like 2200% (because there are a lot of tiles placed vertically in that image) adds up to an offset that is quite substantial.
NB: I'm not saying Safari isn't wrong to be doing this truncation, but even if someone gets them to fix it, then it will still only look right for BGA users who have updated to the latest and greatest Safari version, and it may be possible to work around it in Carcassonne's code without breaking things for other browsers.
I believe that adding the line:
just after tile_size is written (in onWheel(), onUnzoom(), and the constructor) will probably have the right effect.
This arranges that the javascript does its calculations based on a tile size which will end up being a whole number of pixels on the screen, so the precise number and the truncated number agree.
If the view is zoomed in or out from its default size at all, the bug manifests as tiles which are offset by a few pixels in one direction. At small sizes (including the default view in portrait on my iPhone 6S) the error can be a significant proportion of the tile, so it gets confusing to see what's going on. The offset is always in the tile's vertical direction, but tiles can be displayed with 90 degree rotation, so the displacement on screen can be in any direction. (Also you may notice that tiles change displacement when the map scrolls even if the zoom stays the same - but only if the whole interface is being zoomed smaller for being drawn on small screens).
A tile looks something like this (I've simplified it a bit):
Code: Select all
<div id="tile_35" class="bdtile" style="top: 127.54473388671876px; left: -127.54473388671876px; width: 127.54469794418385px; height: 127.54469794418385px;">
<div id="tile_art_35" class="tile_art" style="background-size: 382.63409383255157px 10458.665231423076px; background-position: 0% -2200%;">
</div>
</div>NB: I'm not saying Safari isn't wrong to be doing this truncation, but even if someone gets them to fix it, then it will still only look right for BGA users who have updated to the latest and greatest Safari version, and it may be possible to work around it in Carcassonne's code without breaking things for other browsers.
I believe that adding the line:
Code: Select all
this.tile_size = (Math.round(this.tile_size * this.gameinterface_zoomFactor)) / this.gameinterface_zoomFactor;
just after tile_size is written (in onWheel(), onUnzoom(), and the constructor) will probably have the right effect.
This arranges that the javascript does its calculations based on a tile size which will end up being a whole number of pixels on the screen, so the precise number and the truncated number agree.