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.09k stars 7.1k forks source link

Pixels of atlas sprites breaks down when zoom ratio is high enough #6887

Closed CinnamonPan closed 1 month ago

CinnamonPan commented 2 months ago

Version

Description

I'm using atlas feature of pixel graphic sprites. I'm not sure whether it's an error or not, but when the zoom ratio is 3 or higher, there's a phenomenon where the area of atlas and pixels break down. Not all atlas sprites have this issue. I guess only sprites that have large size. It only happens on mobile devices. I guess it is something related to devicePixelRatio, but I couldn't find any relationship.

Example Test Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>Test</title>
    <script src="https://cdn.jsdelivr.net/npm/phaser@3.80.0/dist/phaser-arcade-physics.min.js"></script>
    <style>
        html, body {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <script type="module" src="javascript.js"></script>
</body>
</html>
var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#5c5c5c',
    scene: {
        preload: preload,
        create: create
    },
    render: {
        pixelArt: true
    }
};

var game = new Phaser.Game(config);

function preload() {

    // load example 1 texture
    load(this, 'test1', 'example1');

    // load example 2 texture
    load(this, 'test2', 'example2');

    // set zoom (3 or higher)
    var camera = this.cameras.main;
    camera.setZoom(3);
}

function create() {
    // example 1
    anim(this, 'weddingzone', 'test1', 400, 280);

    // example 2
    anim(this, 'Floor_Front', 'test2', 400, 320);
}

function load(scene, texture, name) {

    // set file location
    var imagePath = `./images/${name}.png`;
    var jsonPath = `./images/${name}.json`;

    // load as atlas data
    scene.load.atlas(texture, imagePath, jsonPath);
}

function anim(scene, prefix, texture, x, y) {

    // load texture
    var atlasTexture = scene.textures.get(texture);

    // get custom data from json
    var customData = atlasTexture.frames[`${prefix}_0.png`].customData.customData;

    // get frames using prefix
    var pattern = new RegExp(`^${prefix}_[0-9]+\\.png$`);

    // count frames
    var count = Object.keys(atlasTexture.frames).filter(frame => {
        return pattern.test(frame);
    }).length - 1;

    // create animation
    scene.anims.create({
        key: texture,
        frames: scene.anims.generateFrameNames(texture, {
            prefix: prefix + '_',
            suffix: '.png',
            zeroPad: 1,
            start: 0,
            end: count
        }),
        frameRate: 1000 / customData.delayTime,
        repeat: customData.stopAtLastFrame ? 0 : -1
    });

    // place and play
    scene.add.sprite(x, y, texture)
    .play(texture);
}

Additional Information

https://github.com/user-attachments/assets/5c41058f-b877-4e90-b5ce-80bc7c65b89f

https://github.com/user-attachments/assets/07af7379-f540-4feb-87c2-05d0a34a6a74

TexturePack.zip - used sprites and json files

photonstorm commented 2 months ago

Has the atlas been created with frame extrusion / border padding enabled? If not, make sure it is updated to do so, then re-test this.