excaliburjs / Excalibur

🎮 Your friendly TypeScript 2D game engine for the web 🗡️
https://excaliburjs.com
BSD 2-Clause "Simplified" License
1.82k stars 188 forks source link

DisplayMode.FitScreen is just … weird #2076

Closed 0xEAB closed 3 years ago

0xEAB commented 3 years ago

Steps to Reproduce

Been experimenting with your hello world thingy… Wouldn’t see the paddle, other weird things going on. Well, after getting more and more confused, I realized it’s just DisplayMode being horribly broken.

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8"/>
    <title>…</title>
    <style>
        body {
            background: #000;
            color: #F8F9FA;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
    <script src="dist/bundle.js"></script>
</body>
</html>
import {Actor, CollisionType, Color, DisplayMode, Engine, Resolution, vec} from 'excalibur'

async function main() {
    const game = new Engine({
        viewport: {width: 1000, height: 1000,},
        resolution: {width: 1000, height: 1000,},
        displayMode: DisplayMode.FitScreen,
    });

    await game.start();

    const paddle = new Actor({
        x: 220,
        y: 220,
        width: 400,
        height: 400,
        color: Color.White,
    });

    console.log('Game:', game.drawWidth, '·', game.drawHeight);
    console.log('Canv:', game.canvasWidth, '·', game.canvasHeight);

    game.add(paddle);

}

main().then(() => {
    console.log('Promise from main()');
});

Expected Result

displayMode: DisplayMode.Fixed ![Screenshot from 2021-11-01 02-53-22](https://user-images.githubusercontent.com/15967408/139610851-c7a2cb12-8751-4910-9476-df7b608e37be.png)

Actual Result

Fullscreen window (F11) ![Screenshot from 2021-11-01 02-47-51](https://user-images.githubusercontent.com/15967408/139610569-68cd35ee-43f0-4d7d-9f2a-2a8f255e8db1.png)
Non fullscreen ![Screenshot from 2021-11-01 02-48-00](https://user-images.githubusercontent.com/15967408/139610615-a350737d-ea87-4f2e-b549-770dd12679d3.png)
Non fullscreen with console open ![Screenshot from 2021-11-01 02-48-14](https://user-images.githubusercontent.com/15967408/139610673-13503778-a866-4db8-bc82-6d3feb036277.png)
Variation I ```patch - viewport: {width: 1000, height: 1000,}, - resolution: {width: 1000, height: 1000,}, + viewport: {width: 2000, height: 2000,}, + resolution: {width: 2000, height: 2000,}, ``` ![Screenshot from 2021-11-01 02-57-26](https://user-images.githubusercontent.com/15967408/139611207-920f544f-a96f-47ec-aeed-76a156276081.png)
Variation II ```patch - viewport: {width: 1000, height: 1000,}, - resolution: {width: 1000, height: 1000,}, + viewport: {width: 500, height: 500,}, + resolution: {width: 500, height: 500,}, ``` - ![Screenshot from 2021-11-01 03-05-13](https://user-images.githubusercontent.com/15967408/139611720-23a0afde-b477-4d91-b52f-6117eeac718d.png) - ![Screenshot from 2021-11-01 03-05-22](https://user-images.githubusercontent.com/15967408/139611730-0a27302a-2970-4dca-8be5-31375361dca0.png) - ![Screenshot from 2021-11-01 03-05-38](https://user-images.githubusercontent.com/15967408/139611736-f30a2708-d902-4bb4-aacb-8bdf33a9ce15.png) - `displayMode: DisplayMode.Fixed` – as expected :) ![Screenshot from 2021-11-01 03-08-19](https://user-images.githubusercontent.com/15967408/139611902-dc4a1277-bc7c-488c-b714-70afd24ff576.png)

Environment

Maybe I got wrong, what DisplayMode.FitScreen is supposed to do. But its docs are rather cryptic (without any images!) and in my experiment it was just incomprehensible and weird.

Current Workaround

displayMode: DisplayMode.Fixed

eonarheim commented 3 years ago

@0xEAB Thanks for the issue, we'll get on the docs with some images/examples...that definitely needs improvement.

FitScreen is intended to fit the game to the available screen real estate while preserving the defined pixel resolution (aspect ratio), it will change the viewport dynamically to make that happen.

Based on the screen shots you've provided I'm guessing the white box is not where you expect it to be on screen. Correct me if I'm wrong.

Running this locally it appears to be a bug (maybe 2) in excalibur:

  1. Camera initialization bug, be default excalibur tries to center the camera in the current space, it seems to be using the center of the viewpoint as world coordinates which is definitely not right. Which I think explains most of the issues you're seeing

    Forcibly setting the camera position to the center of the screen should correct it as a workaround for now.

    // after await game.start()
    game.currentScene.camera.pos = game.screen.center;
  2. At extra high resolutions the canvas seems to be displaying incorrectly (setting 3000x3000 seemed to be the start of things going wrong for me). It's possible we are bumping up against gpu limits at that size with hidpi scaling (which doubles the internal resolution to 6000x6000) in webgl and it's manifesting in an odd way. I need to do a little more research on this.

    image

    Suppressing the hidpi scaling seems to correct it as a workaround, at high resolutions like that hidpi blurring will be less of an issue.

    const game = new ex.Engine({
        width: 3000,
        height: 3000,
        suppressHiDPIScaling: true,
        displayMode: ex.DisplayMode.FitScreen,
    });

    image

eonarheim commented 3 years ago

@0xEAB We've updated the screen & viewport docs let me know if you have any additional feedback!

https://excaliburjs.com/docs/screens

0xEAB commented 3 years ago

Thank you for your explanations :)