Jump to content

Problem with Phaser.group and cacheAsBitmap..


Recommended Posts

I'm working on a game with tetris-type blocks and I've basically done this:
- create a custom object based on Phaser.Group
- in the constructor of the custom object I add some sprites
- in custom object set "cacheAsBitmap = true;"
The strange thing is that the results are different when I set cacheAsBitmap = true; and when I comment out that line, see screenshot below, the bottom part is correct and as expected. It looks like some sort of rendering issue, when I leave out the cacheAsBitmap it suddenly renders more tiles than expected, why is that?

I've tried to isolate the error in this example code:

EDIT: I've put this tester project also on GitHub here

// bitmaptext testing centered functionvar CANVAS_WIDTH = 800;var CANVAS_HEIGHT = 600;var TILE_SIZE = 40;// -------------------------------------// define mygame state// -------------------------------------var mygame = {};mygame.Screen1 = function(game){    this.game = game;    this.myblocks = [];};mygame.Screen1.prototype = {    preload: function() {        this.load.spritesheet('tiles', 'tiles.png', TILE_SIZE, TILE_SIZE);    },    create: function() {        // TESTING draw rectangle        this.stage.backgroundColor = 0x808080;            // tile 1        for (var i = 0; i < 7; i++) {            // new object sprite            var newobj = new TetrisBlock(game, i);            this.myblocks.push(newobj);            newobj.x = newobj.x + (i*100);            newobj.y = newobj.y + (i*8);        };    }};// -------------------------------------// tetris blocks// -------------------------------------// block object constructorvar TetrisBlock = function(game, blocktype) {    // inherits from Phaser.Group    Phaser.Group.call(this, game);    // save which block type    this.blocktype = blocktype;        switch(blocktype) {        case 1: // 'l' tetris block            this.initBlock(".#...#...#...#..");        case 2: // 'S' tetris block            this.initBlock(".....##.##......");        case 3: // 'Z' tetris block            this.initBlock(".....##...##....");        case 4: // 'L' tetris block            this.initBlock(".....#...#...##.");        case 5: // 'J' tetris block            this.initBlock("......#...#..##.");        case 6: // 'T' tetris block            this.initBlock(".....###..#.....");        default: // 0 = 'O' tetris block            this.initBlock(".....##..##.....");    };};// Specific JavaScript object/construcor stuff going on here(?)// game objects are a type of Phaser.SpriteTetrisBlock.prototype = Object.create(Phaser.Group.prototype);TetrisBlock.prototype.constructor = TetrisBlock;// TetrisBlock initialise sprites for block configurationTetrisBlock.prototype.initBlock = function(str) {    // phaser.sprite.reset    var x = 0;    var y = 0;    for (var i=0; i < str.length; i++) {        // block or no block        if (str.substr(i, 1) == '#') {            // calculate position            var xpos = x * TILE_SIZE;            var ypos = y * TILE_SIZE;            // add sprite to game            var sprblock = this.game.add.sprite(xpos, ypos, 'tiles', this.blocktype);             this.add(sprblock);        };        // next 'grid' position        x++;        if (x > 3) {            x=0;            y++;        };    };        // cache all sprites as 1 bitmap, else small lines sometimes appear between block parts    //this.cacheAsBitmap = true;};// -------------------------------------// define Phaser game and add states// -------------------------------------var game = new Phaser.Game(CANVAS_WIDTH, CANVAS_HEIGHT, Phaser.CANVAS, 'game');game.state.add('Screen1', mygame.Screen1);game.state.start('Screen1');

The really weird thing is that in my actual project all was working fine with cacheAsBitmap=true, but after upgrading from Phaser 2.3.0 to Phaser 2.4.0a the sprites of the custom group are not visible at all. And when I remove the cacheAsBitmap line then it's all visible again. So in my actual project I have to do the opposite to fix it, compared to this example code.

So I couldn't reproduce the invisible sprites exactly in this example code, but still weird stuff is going on. Maybe I'm creating the custom object based on Phaser.group the incorrect way. Or maybe the sprites become invisible because in my actual project there are also other sprites on-screen (different particles and background stuff) that use different .png images?
Can someone shed some light on this?  :huh:
Link to comment
Share on other sites

  • 1 year later...

Ok I found something that helped me...

Originally I was creating the group and adding to the parent right away:

    var backing = this.game.add.group(this); // 'this' is my parent group
    // create content, add some images to the backing group
    // ...
    backing.cacheAsBitmap = true; // results in group being chopped off

But if I choose to set cacheAsBitmap = true, and then add to the group, it displays properly:

    var backing = this.game.add.group();  // assign to default parent, which is the world
    // do the creation stuff
    // ...
    // cache as bitmap now
    backing.cacheAsBitmap = true;

    // NOW attach to the real parent group

Looking at the pixi code, I think there's a problem in there calculating the local bounds for the group, causing the original bug.

Hope this helps.


Link to comment
Share on other sites

  • 1 year later...
On 9/15/2016 at 11:00 PM, richpixel said:

Ok I found something that helped me...

Looking at the pixi code, I think there's a problem in there calculating the local bounds for the group, causing the original bug.

Hope this helps.

You are absolutely right. I wasted over 4 hours trying to understand what is going wrong and why input is not longer working. It took me 3 hours to find that once cacheAsBitmap is enabled, group's left, top coordinates reset to parent group. I was suspicious about that because in PIXI.Graphics.prototype._generateCachedSprite I found this line var bounds = this.getLocalBounds(); WHICH (getLocalBounds) NEVER WORKS IN PHASER, NEVER EVER! So far I have no clue how to fix it but I am happy that I could reproduce error and narrow it parent group. Simplified example to reproduce error:

var parent_group = new Phaser.Group(this.game);
parent_group.top = 100;
parent_group.left = 100;

var group = new Phaser.Group(this.game, parent_group);
var sprite = new Phaser.Sprite(this.game, 200, 200, 'sprite');
sprite.inputEnabled = true;
sprite.events.onInputUp.add(function() {
}, this);
group.cacheAsBitmap = true;

To get log messages you should click top left of the image (-100, -100). The solution you suggested did not work for me but I used your idea and did following:

I simply set all parent group's coordinates to 0, 0 and instead of moving parent, I moved cached group to appropriate position and it worked.

Of course bug in Phase still exist, but I am still using 2.6.2 May be in later releases the problem was resolved.

Second solution I found is to add wrapper group which will hold the cached group, this solution also worked for me.

However, I am thinking to create my own simple cache method which will set all children of group invisible and adds new sprite created with texture generated out of group ?

Link to comment
Share on other sites


  • Recently Browsing   0 members

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