Strange effect with pixelart

Hi,

I use the pixelArt effect as you can see above:

const my_game = {
    init: () => {

        var config = {
            // type: Phaser.WEBGL, //android
            type: Phaser.CANVAS, //pc
            width: data.w,
            height: data.h,
            backgroundColor: '#222222',
            parent: 'phaser-example',
            pixelArt: true,
            physics: {
                default: 'arcade',
                arcade: {
                    fps: 60,
                    gravity: {
                        y: 0,
                        x: 0,
                    },
                    debug: false,
                }
            },
            callbacks: {
                postBoot: function (game) {
                    game.canvas.style.width = '100%';
                    game.canvas.style.height = '100%';
                }
            },
            scene: [Boot, Splash, First_screen, Test, Main]
        }
        if (is_mobile) {
            config.type = Phaser.WEBGL
            game = new Phaser.Game(config);
        } else {
            config.type = Phaser.WEBGL
            game = new Phaser.Game(config);
        }
    },
}

The strange thing is that my spritesheet have 2 pixel dark on the side (hair) on my game 01

But in reality my spritesheet.png don’t have this 2 pixel dark on the side (hair)
02

I reproduce this with every spritesheet, it’s not due to this spritesheet !

Why could i do to avoid this ?

Setting pixelArt:true is a good thing and should be enough, but you might want to have a look at additionnal settings to make sure it’s fully pixelated. For my pixel art game, I use the following:

pixelArt: true,
antialias: false,
autoRound: true,
roundPixels: true,

Although the pixelArt setting already does the job, I added these CSS properties on the canvas in my stylesheet:

#game-div canvas
{
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-crisp-edges;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
}

Also, I see you have a callback function that sets canvas width and height to 100%. Maybe it stretches it and causes the unwanted pixels to appear?

Instead of doing that 100% thing, you could use Phaser’s scale setting in your config, to FIT the screen. In the end, your config would look like this:

var config = {
    // type: Phaser.WEBGL, //android
    type: Phaser.CANVAS, //pc
    scale: {
        mode: Phaser.Scale.FIT,
        parent: 'game-div',
        width: data.w,
        height: data.h
    },
    backgroundColor: '#222222',
    pixelArt: true,
    antialias: false,
    autoRound: true,
    roundPixels: true,
    physics: {
        default: 'arcade',
        arcade: {
            fps: 60,
            gravity: {
                y: 0,
                x: 0,
            },
            debug: false,
        }
    },
    scene: [Boot, Splash, First_screen, Test, Main]
}

If you really want your canvas to cover the whole window without stretching it, try ENVELOP instead of FIT. In that case, part of the canvas will most likely be out of the window boundaries, hence invisible.

Thanks, i have do all you mentions but still the samme bug…

see my gif :

Peek 22-10-2021 19-36

Could you give your boilerplate ?

Hi,

Peek 25-10-2021 17-48

it’s what i have…always the same bug.
One line of my character have two pixel (between head and costume).
Here below all my config :

my game.js

const my_game = {
    init: () => {
        // PUT HERE YOUR GAME//////////////////////////////////////////////
        console.log('my game initialize')

        var config = {
            // type: Phaser.WEBGL, //android
            type: Phaser.CANVAS, //pc
            scale: {
                mode: Phaser.Scale.FIT,
                parent: 'game-div',
                width: data.w, //320
                height: data.h //160
            },
            backgroundColor: '#222222',
            pixelArt: true,
            antialias: false,
            autoRound: true,
            roundPixels: true,
            physics: {
                default: 'arcade',
                arcade: {
                    fps: 60,
                    gravity: {
                        y: 0,
                        x: 0,
                    },
                    debug: false,
                }
            },
            scene: [Boot, Splash, First_screen, Test, Main]
        }

my index.html

<html>

<head>
    <title>Socx</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" type="text/css" href="css/index.css" />

    <style>
        @font-face {
            font-family: Font;
            src: url('fonts/font.woff');
            font-weight: 400;
            font-weight: normal;
        }

        body {
            height: 100%;
            margin: 0;
            padding: 0;
            background: #f94b4b;
            /* background: #151235; */
            font: caption;
        }
        /* Pour changer le fond de couleur */
        .ready {
            background: rgb(255, 132, 224);

        }
    </style>


    <div id="joystickWrapper1"></div>
    <div id="joystickWrapper2"></div>
    <div id="phaser-example">

        <div class="info" id="info">
            <div class="info">Microbe</div>
        </div>
    </div>


    <meta http-equiv="X-UA-Compatible" content="chrome=1, IE=9">
    <meta name="format-detection" content="telephone=no">
    <meta name="HandheldFriendly" content="true" />
    <meta name="robots" content="noindex,nofollow" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <meta name="apple-mobile-web-app-title" content="Phaser App">
    <meta name="msapplication-tap-highlight" content="no" />
    <meta name="viewport"
        content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
    <script type="text/javascript" src="cordova.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/nipplejs/0.9.0/nipplejs.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.55.2/phaser.min.js"></script>
    <!--ici les classes du jeu  -->
    <script src="js/classes/entity.js"></script>


    <!--ici les scenes du jeu  -->
    <!-- <script src="js/scenes/MinScene.js"></script> -->
    <script src="js/scenes/boot.js"></script>
    <script src="js/scenes/splash.js"></script>
    <script src="js/scenes/first_screen.js"></script>
    <script src="js/scenes/test.js"></script>
    <script src="js/scenes/main.js"></script>

    <!--ici le coeur du jeu  -->
    <script src="js/core/game.js"></script>
    <script src="js/core/index.js"></script>

<body>
</body>

</html>

my index.css

@font-face {
    font-family: Font;
    src: url('fonts/font.woff');
    font-weight: 400;
    font-weight: normal;

}

body {
    height: 100%;
    margin: 0;
    padding: 0;
    background: #000;
    font: caption;
}

#game-div canvas {
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-crisp-edges;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
}

What’s the good setting to have pixelart with the scale adapted to the device ?

Thanks in advance.

Hi,

First thing I notice, your config says parent: ‘game-div’ so in your HTML file you should also replace “phaser-example” by “game-div”.

Also your HTML file is broken. It doesnt have the DOCTYPE declaration, your head tag is not closed, and you are adding div tags inside the head instead of the body, which is wrong.

Your HTML file should look like this:

 <!DOCTYPE html>
 <html>

    <head>
        <title>Socx</title>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="chrome=1, IE=9">
        <meta name="format-detection" content="telephone=no">
        <meta name="HandheldFriendly" content="true" />
        <meta name="robots" content="noindex,nofollow" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />
        <meta name="apple-mobile-web-app-title" content="Phaser App">
        <meta name="msapplication-tap-highlight" content="no" />
        <meta name="viewport"
            content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
        <link rel="stylesheet" type="text/css" href="css/index.css" />
    
        <style>
            @font-face {
                font-family: Font;
                src: url('fonts/font.woff');
                font-weight: 400;
                font-weight: normal;
            }
    
            body {
                height: 100%;
                margin: 0;
                padding: 0;
                background: #f94b4b;
                /* background: #151235; */
                font: caption;
            }
            /* Pour changer le fond de couleur */
            .ready {
                background: rgb(255, 132, 224);
    
            }
        </style>
    </head>

    <body>
        <div id="joystickWrapper1"></div>
        <div id="joystickWrapper2"></div>
        <div id="game-div">
    
            <div class="info" id="info">
                <div class="info">Microbe</div>
            </div>
        </div>

        <script type="text/javascript" src="cordova.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/nipplejs/0.9.0/nipplejs.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.55.2/phaser.min.js"></script>
        <!--ici les classes du jeu  -->
        <script src="js/classes/entity.js"></script>
    
    
        <!--ici les scenes du jeu  -->
        <!-- <script src="js/scenes/MinScene.js"></script> -->
        <script src="js/scenes/boot.js"></script>
        <script src="js/scenes/splash.js"></script>
        <script src="js/scenes/first_screen.js"></script>
        <script src="js/scenes/test.js"></script>
        <script src="js/scenes/main.js"></script>
    
        <!--ici le coeur du jeu  -->
        <script src="js/core/game.js"></script>
        <script src="js/core/index.js"></script>
    </body>
    
</html>

I dont know if this will solve your problem of distorted sprites, but at least it will be a cleaner base.

Thanks @Maup-Maup

I have write a basic example following your advices and it reproduce my distorted spritesheet.
The bug appears only when i switch to a specific model (pixel2 or iphoneX). On galaxy S5 the spritesheet is not distorded.

example

Peek 29-10-2021 14-12

source

Here is the zip file :
test_sprite_sheet.zip (5.0 KB)

For those who don’t want to download this, here is the source code per files :

index.html

<!DOCTYPE html>
<html>

<head>
	<link rel="stylesheet" type="text/css" href="css/index.css" />
	<div id="game-div"></div>
	<meta charset="utf-8">
	<meta lang="en-us">
	<title>Space Shooter</title>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.23.0/phaser.min.js"></script>
</head>

<body>
	<script src="js/main.js"></script>
	<script src="js/game.js"></script>
</body>

</html>

index.css

body {
	height: 100%;
	margin: 0;
	top: 0;
	left: 0;
	padding: 0;
	background: rgb(255, 133, 133);
	font: caption;
}

#game-div canvas {
	image-rendering: -moz-crisp-edges;
	image-rendering: -webkit-crisp-edges;
	image-rendering: pixelated;
	image-rendering: crisp-edges;
}

main.js

class Main extends Phaser.Scene {
	constructor() {
		super({
			key: "Main"
		});
	}

	preload() {
		this.load.spritesheet("player", "player.png", {
			frameWidth: 24,
			frameHeight: 24
		});
	}
	create() {
		var camera = this.cameras.add(0, 0, 160, 320).setBackgroundColor("#ffa4a4")
		var player = this.add.sprite(100, 200, "player")
		player.scene.anims.create({
			key: 'normal',
			frames: player.scene.anims.generateFrameNumbers("player", {
				frames: [0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
			}),
			frameRate: 8,
			repeat: -1,
		})
		player.anims.play('normal')
	}

	update() {
	}
}

game.js

var config = {
	type: Phaser.WEBGL,
	width: 160,
	height: 320,
	scale: {
		mode: Phaser.Scale.FIT,
		autoCenter: Phaser.Scale.CENTER_BOTH,
		parent: "game-div",
		zoom: 1,
	},
	backgroundColor: "black",
	physics: {
		default: "arcade",
		arcade: {
			gravity: {
				x: 0,
				y: 0
			},
			debug: false,
		}
	},
	scene: [
		Main,
	],
	pixelArt: true,
	roundPixels: true,
};

var game = new Phaser.Game(config);