Jump to content

Aliasing on Arcade Sprites


Recommended Posts

This thread talks about the finished product in the phaser tutorial described here:
After using the arrow keys to walk around, your character sometimes comes to a stop like this:

Which when zoomed in, looks like this:

However, other times your character comes to a stop like this:
Which when zoomed in, looks like this:

How do I ensure that sprites do not interpolate or alias across two locations one pixel apart? That is, how do I make sure that sprites always display the first way and never the second way?

(This possible bug was first noticed on 2.0.1. Updating to 2.0.5 did not help.)

For reference, here is the code:
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });

function preload() {

    game.load.image('sky', 'assets/sky.png');
    game.load.image('ground', 'assets/platform.png');
    game.load.image('star', 'assets/star.png');
    game.load.spritesheet('dude', 'assets/dude.png', 32, 48);


var player;
var platforms;
var cursors;

var stars;
var score = 0;
var scoreText;

function create() {

    //  We're going to be using physics, so enable the Arcade Physics system

    //  A simple background for our game
    game.add.sprite(0, 0, 'sky');

    //  The platforms group contains the ground and the 2 ledges we can jump on
    platforms = game.add.group();

    //  We will enable physics for any object that is created in this group
    platforms.enableBody = true;

    // Here we create the ground.
    var ground = platforms.create(0, game.world.height - 64, 'ground');

    //  Scale it to fit the width of the game (the original sprite is 400x32 in size)
    ground.scale.setTo(2, 2);

    //  This stops it from falling away when you jump on it
    ground.body.immovable = true;

    //  Now let's create two ledges
    var ledge = platforms.create(400, 400, 'ground');
    ledge.body.immovable = true;

    ledge = platforms.create(-150, 250, 'ground');
    ledge.body.immovable = true;

    // The player and its settings
    player = game.add.sprite(32, game.world.height - 150, 'dude');

    //  We need to enable physics on the player

    //  Player physics properties. Give the little guy a slight bounce.
    player.body.bounce.y = 0.2;
    player.body.gravity.y = 300;
    player.body.collideWorldBounds = true;

    //  Our two animations, walking left and right.
    player.animations.add('left', [0, 1, 2, 3], 10, true);
    player.animations.add('right', [5, 6, 7, 8], 10, true);

    //  Finally some stars to collect
    stars = game.add.group();

    //  We will enable physics for any star that is created in this group
    stars.enableBody = true;

    //  Here we'll create 12 of them evenly spaced apart
    for (var i = 0; i < 12; i++)
        //  Create a star inside of the 'stars' group
        var star = stars.create(i * 70, 0, 'star');

        //  Let gravity do its thing
        star.body.gravity.y = 300;

        //  This just gives each star a slightly random bounce value
        star.body.bounce.y = 0.7 + Math.random() * 0.2;

    //  The score
    scoreText = game.add.text(16, 16, 'score: 0', { fontSize: '32px', fill: '#000' });

    //  Our controls.
    cursors = game.input.keyboard.createCursorKeys();

function update() {

    //  Collide the player and the stars with the platforms
    game.physics.arcade.collide(player, platforms);
    game.physics.arcade.collide(stars, platforms);

    //  Checks to see if the player overlaps with any of the stars, if he does call the collectStar function
    game.physics.arcade.overlap(player, stars, collectStar, null, this);

    //  Reset the players velocity (movement)
    player.body.velocity.x = 0;

    if (cursors.left.isDown)
        //  Move to the left
        player.body.velocity.x = -150;

    else if (cursors.right.isDown)
        //  Move to the right
        player.body.velocity.x = 150;

        //  Stand still

        player.frame = 4;
    //  Allow the player to jump if they are touching the ground.
    if (cursors.up.isDown && player.body.touching.down)
        player.body.velocity.y = -350;


function collectStar (player, star) {
    // Removes the star from the screen

    //  Add and update the score
    score += 10;
    scoreText.text = 'Score: ' + score;


Link to comment
Share on other sites

This is not really a bug, just a by-product of the fact that the physics systems work with floating point numbers, and Phaser isn't a framework dedicated to pixel art. Try this at the end of the update function maybe?

player.x = player.x | 0;player.y = player.y | 0;

This will round the x and y position of the player, which should prevent it landing between pixels. 

Link to comment
Share on other sites

The collision issue may be because the ground's body doesn't lie exactly on a pixel boundary either. Rather than scaling the ground sprite, you may want to try explicitly setting the size of the body with body.setSize() and try again just to be sure.


I should add that player.x | 0 will always round down, but it's very fast. You could also try player.x = Math.round(player.x) and see how that differs.

Link to comment
Share on other sites

  • 2 years later...

This question is pretty old but still one of the top results on google so I thought it'd be nice to update it.

This can now be fixed with the antialias param when creating the game:

var transparent = false;
var antialias = false;
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', this, transparent, antialias);


Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...