Fix the camera rounding to work when following objects with even dimensions and pixel perfect mode is enabled (#3789)

This commit is contained in:
D8H
2022-04-01 12:00:47 +02:00
committed by GitHub
parent fc3e73f360
commit 41241d75e1
3 changed files with 42 additions and 4 deletions

View File

@@ -81,14 +81,36 @@ namespace gdjs {
Number.isInteger(zoomFactor)
) {
// Camera rounding is important for pixel perfect games.
// Otherwise the camera position fractional part is added to
// Otherwise, the camera position fractional part is added to
// the sprite one and it changes in which direction sprites are rounded.
// It makes sprites rounding inconsistent with each other
// and they seems to move on pixel left and right.
this._pixiContainer.position.x = Math.round(
// and they seem to move on pixel left and right.
//
// PIXI uses a floor function on sprites position on the screen,
// so a floor must be applied on the camera position too.
// According to the above calculus,
// _pixiContainer.position is the opposite of the camera,
// this is why the ceil function is used floor(x) = -ceil(-x).
//
// When the camera directly follows an object,
// given this object dimension is even,
// the decimal part of onScenePosition and cameraPosition are the same.
//
// Doing the calculus without rounding:
// onScreenPosition = onScenePosition - cameraPosition
// onScreenPosition = 980.75 - 200.75
// onScreenPosition = 780
//
// Doing the calculus with rounding:
// onScreenPosition = floor(onScenePosition + ceil(-cameraPosition))
// onScreenPosition = floor(980.75 + ceil(-200.75))
// onScreenPosition = floor(980.75 - 200)
// onScreenPosition = floor(780.75)
// onScreenPosition = 780
this._pixiContainer.position.x = Math.ceil(
this._pixiContainer.position.x
);
this._pixiContainer.position.y = Math.round(
this._pixiContainer.position.y = Math.ceil(
this._pixiContainer.position.y
);
}

View File

@@ -14,6 +14,7 @@ export type AlertMessageIdentifier =
| 'automatic-lighting-layer'
| 'object-moved-in-lighting-layer'
| 'use-non-smoothed-textures'
| 'use-pixel-rounding'
| 'use-nearest-scale-mode'
| 'maximum-fps-too-low'
| 'minimum-fps-too-low'
@@ -53,6 +54,10 @@ export const allAlertMessages: Array<{
key: 'use-non-smoothed-textures',
label: <Trans>Using non smoothed textures</Trans>,
},
{
key: 'use-pixel-rounding',
label: <Trans>Using pixel rounding</Trans>,
},
{
key: 'use-nearest-scale-mode',
label: <Trans>Using Nearest Scale Mode</Trans>,

View File

@@ -541,6 +541,17 @@ function ProjectPropertiesDialog(props: Props) {
</Trans>
</DismissableAlertMessage>
)}
{pixelsRounding && (
<DismissableAlertMessage
identifier="use-pixel-rounding"
kind="info"
>
<Trans>
To avoid flickering on objects followed by the camera, use
sprites with even dimensions.
</Trans>
</DismissableAlertMessage>
)}
<Text size="title">
<Trans>Project files</Trans>