Jump to content

Weird (propably depth) issues with iso plugin.


RedPanduzer
 Share

Recommended Posts

I'm trying to create simple isometric game using @lewster32's iso plugin, where player needs to transport his/her hero from point A to point B in simple city. Nothing special there.

However, some buildings start flickering and I can't figure how to stop it. Only solution I came up with, is that I place them in air but that's not very good because small character can go below them. It seem that the issue is with body.immovable = true and body.moves = false commands. If I give those for the field itself, flickering starts.

My code:

    var kentta;
    var house;
    var cube;
   var game = new Phaser.Game(1280, 800, Phaser.AUTO, 'test', null, true, false);

var BasicGame = function (game) { };

BasicGame.Boot = function (game) { };

var isoGroup, player;

BasicGame.Boot.prototype =
{
    preload: function () {
        game.load.image('cube', 'police_dep.png');
        game.load.image('kentta', 'kentta1.png');
        game.load.image('house1', 'house1.png');
        game.load.image('house2', 'house2.png');
        game.load.image('house3', 'house3.png');
        game.load.image('house5', 'house5.png');
        game.load.image('house6', 'house6.png');
        game.load.image('park', 'park.png');
        game.load.image('factory', 'factory.png');

        game.time.advancedTiming = true;

        // Add and enable the plug-in.
        game.plugins.add(new Phaser.Plugin.Isometric(game));

        // Start the IsoArcade physics system.
        game.physics.startSystem(Phaser.Plugin.Isometric.ISOARCADE);

        // This is used to set a game canvas-based offset for the 0, 0, 0 isometric coordinate - by default
        // this point would be at screen coordinates 0, 0 (top left) which is usually undesirable.
        game.iso.anchor.setTo(0.5, 0.5);

                
    },
    create: function () {
        // Create a group for our tiles, so we can use Group.sort
        isoGroup = game.add.group();
      isoGroup.enableBody = true;
        isoGroup.physicsBodyType = Phaser.Plugin.Isometric.ISOARCADE;
        // Set the global gravity for IsoArcade.
        game.physics.isoArcade.gravity.setTo(0, 0, -500);

        kentta = game.add.isoSprite(200,0,20,'kentta',0,isoGroup);
        kentta.anchor.setTo(0.5,0);
        game.physics.isoArcade.enable(kentta);
        kentta.body.immovable = true;
        kentta.moves = false;

        house = game.add.isoSprite(410,70,0,'house1',0,isoGroup);
        house.anchor.setTo(0.5);
        house2 = game.add.isoSprite(440,180,100,'house2',0,isoGroup);
        house2.anchor.setTo(0.5);
        house3 = game.add.isoSprite(440,250,100,'house2',0,isoGroup);
        house3.anchor.setTo(0.5);
        house4 = game.add.isoSprite(340,275,100,'house3',0,isoGroup);
        house4.anchor.setTo(0.5);
        house5 = game.add.isoSprite(500,275,100,'house5',0,isoGroup);
        house5.anchor.setTo(0.5);
        house6 = game.add.isoSprite(475,90,100,'house6',0,isoGroup);
        house6.anchor.setTo(0.5);
        park = game.add.isoSprite(330,140,80,'park',0,isoGroup);
        park.anchor.setTo(0.5);
        factory = game.add.isoSprite(240,270,80,'factory',0,isoGroup);
        factory.anchor.setTo(0.5);
        // Create another cube as our 'player', and set it up just like the cubes above.
        player = game.add.isoSprite(200, 0, 100, 'cube', 0, isoGroup);
        player.tint = 0x86bfda;
        player.anchor.set(0.5);
        game.physics.isoArcade.enable(house);
        game.physics.isoArcade.enable(house2);
        game.physics.isoArcade.enable(house3);
        game.physics.isoArcade.enable(house4);
        game.physics.isoArcade.enable(house5);
        game.physics.isoArcade.enable(house6);
        game.physics.isoArcade.enable(park);
        game.physics.isoArcade.enable(player);
        park.body.moves = false;
        park.body.immovable = true;
        factory.body.moves = false;
        factory.body.immovable = true;
        park.scale.setTo((game.width/kentta.width)*0.5);

        /*kentta.body.setSize(kentta.body.widthX*1.5,kentta.body.widthY,kentta.body.height*0.5);*/
        player.body.collideWorldBounds = true;
        kentta.body.collideWorldBounds = true;
        house.body.collideWorldBounds = true;
        house2.body.collideWorldBounds = true;


        kentta.scale.setTo((game.width/kentta.width)*0.5);
        house.scale.setTo((game.width/kentta.width)*0.15);
        house2.scale.setTo((game.width/kentta.width)*0.15);
        house3.scale.setTo((game.width/kentta.width)*0.15);
        house4.scale.setTo((game.width/kentta.width)*0.15);
        house5.scale.setTo((game.width/kentta.width)*0.15);
        house6.scale.setTo((game.width/kentta.width)*0.15);

        factory.scale.setTo((game.width/kentta.width)*0.15);
        // Set up our controls.
        this.cursors = game.input.keyboard.createCursorKeys();

        this.game.input.keyboard.addKeyCapture([
            Phaser.Keyboard.LEFT,
            Phaser.Keyboard.RIGHT,
            Phaser.Keyboard.UP,
            Phaser.Keyboard.DOWN,
            Phaser.Keyboard.SPACEBAR
        ]);

        var space = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);

        space.onDown.add(function () {
            player.body.velocity.z = 300;
        }, this);
        game.iso.projectionAngle = 0.575;
        //init once after endering is done
        setTimeout(function(){
            /*kentta.body.setSize(1400,1400,60);
             kentta.pivot.y = -150;*/
            house2.body.moves = false;
            house2.body.immovable = true;
            house3.body.moves = false;
            house3.body.immovable = true;
            house4.body.moves = false;
            house4.body.immovable = true;
            house5.body.moves = false;
            house5.body.immovable = true;
            house6.body.moves = false;
            house6.body.immovable = true;
          /*  park.body.moves = false;
            park.body.immovable = true;
            house.body.moves = false;
            house.body.immovable = true;*/

            house4.body.setSize(house4.body.widthX/0.3,house4.body.widthY/0.3*1.25,house4.body.height/0.3,0,-10);
            house5.body.setSize(house5.body.widthX/0.3,house5.body.widthY/0.3*1.25,house5.body.height/0.3,-5,-10);
            park.body.setSize(park.body.widthX/0.3*1.2,park.body.widthY/0.3*1.5,park.body.height/0.3*1.5,-15,-27);

        },1000);


    },
    update: function () {
        // Move the player at this speed.
        var speed = 100;

        if (this.cursors.up.isDown) {
            player.body.velocity.y = -speed;
        }
        else if (this.cursors.down.isDown) {
            player.body.velocity.y = speed;
        }
        else {
            player.body.velocity.y = 0;
        }

        if (this.cursors.left.isDown) {
            player.body.velocity.x = -speed;
        }
        else if (this.cursors.right.isDown) {
            player.body.velocity.x = speed;
        }
        else {
            player.body.velocity.x = 0;
        }

        // Our collision and sorting code again.
        game.physics.isoArcade.collide(isoGroup);

        game.iso.topologicalSort(isoGroup);
    },
    render: function () {
        game.debug.text("Move with cursors, jump with space!", 2, 36, "#ffffff");
        game.debug.text(game.time.fps || '--', 2, 14, "#a7aebe");
        isoGroup.forEach(function (tile) {
            game.debug.body(tile, 'rgba(189, 221, 235, 0.6)', false);
        });
    }
};

game.state.add('Boot', BasicGame.Boot);
game.state.start('Boot');

If you're wondering why there is a stupid timeout function, that's because all buildings flickered if those where defined in create function. I have no idea why. kentta variable is the field.
Here is the picture of my game, body of field is rather off, I know, I know.
 

game.PNG

Link to comment
Share on other sites

If I look at lewster's code, it seems to match your problem:

separateZ: function (body1, body2, overlapOnly) {                           
                                                                                
        //  Can't separate two immovable or non-existing bodys                  
        if (body1.immovable && body2.immovable) {                               
            return false;                                                       
        }                                                                       

So it seems like your objects' Z bounds are intersecting, and then depth-sort can't work. Your solution to place them in the air is correct, just try to find the lowest possible Z.
Or decrease the height of the object. There is probably a collision margin anyway.

Link to comment
Share on other sites

This is indeed an issue with intersecting objects and the topological depth sorting routine. When two objects overlap in 3D space, the topological sort is no longer able to correctly ascertain their depth, and instead renders them at alternating depths. You can either:

  • Separate your objects
  • Reduce the size of your objects' IsoArcade body bounds
  • Switch to simple sorting (which is a lot faster and does not have this issue but is a lot less accurate when things are positioned close together)
  • Use the 'padding' parameter when doing the topological sort routine. Increasing the number will reduce the accuracy of the sort but improve flickering where objects only slightly overlap:
// the second parameter sets padding, which by default is 1.5 - increased numbers make the sorting more tolerant but less accurate
game.iso.topologicalSort(isoGroup, 3);

There's an interesting discussion of the problem faced with isometric depth sorting here.

Link to comment
Share on other sites

Thanks for the answers. I tried both solutions. With lowering till flicker starts, objects where still way too high (no idea why). I also tried to smaller body sizes but even in very small size, objects flickered and field body couldn't be made smaller. I once tried simple sorting too, but that broke thing rather badly. 

However, I came up with the solution where field isn't isoSprite at all. That was my original idea but I failed to make work back then. Now it seems I'm getting somewhere and that way there is no flickering at all.

Link to comment
Share on other sites

Your houses are too high because your anchor is in the center - you should probably have your y anchor at the bottom, which makes more sense in an isometric scene:

// set the x anchor to 0.5 (center), and the y anchor to 1 (bottom)
house.anchor.setTo(0.5, 1);

The way I'd approach this is to think about how I can 'cheat' the whole depth thing and have each 'layer' in a separate group, ensuring they're in the correct order. By layers, I mean sets of objects which will never overlap, for instance one would assume that the buildings would never appear below the floor? If so, the floor should be a group on its own positioned below the buildings, and never depth sorted (or only depth sorted once) as (again presumably) nothing in that group moves. The buildings layer, if they're all on the same z plane, could then theoretically get away with simple sorting. If you had then clouds and aeroplanes above the buildings, again these could be in their own group above the buildings, and simple sorted (or perhaps topologically sorted if the planes moved up and down on the z axis).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

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