Jump to content

Problem on sprite rendering


NewPixiUser
 Share

Recommended Posts

I am creating a mobile app with using ionic capacitor and pixi.js. I am encountering a problem about rendering sprite. I have created a sprite, added it into the stage of the PIXI application. When I open the mobile app, the sprite can be shown correctly. However, when I exit my app and re-open my app. The sprite cannot be shown. After several close and re-open the app, the sprite can occasionally be shown. If I completely remove my app and re-install, the problem repeate, i.e. the sprite can be shown in the first open of my app, and then cannot be shown when close and re-open my app, and occasionally be shown after several close and re-open. I have tried many days and still cannot fix the problem. Hope I can get help from here. Below is part of my code. A GameBoardDrawer object is created whenever I enter the game page (i.e. click the 'go to play' button from the home page of my app). The function GameBoardDrawer.destroy() is called whenever I leave the game page (but not closing my app). One more information, if a sprite can be displayed, it can keep displayed no matter how many leave and enter of the game page (without closing the app). Thanks.

const baseWidth: number = 1280;
const baseHeight: number = 2560;
const baseCellDim: number = 128;

export enum TexturePaths {
    Cell = "assets/img/cell.png"
}

export class GameBoardDrawer {
    private app: any = null;
    private loader = null; 
    private cells = null;
    private width: number = baseWidth;
    private height: number = baseHeight;

    constructor(
        width, height
    ) { 
        this.width = width;
        this.height = height;
        this.init();
    }

    private init() {
        this.app = new PIXI.Application({autoStart: true, width: this.width, height: this.height});
        this.app.renderer.backgroundColor = 0x000000;
        
        this.loadTextures();
    }
    
    private loadTextures() {
        if (!this.loader) {
            this.loader = new PIXI.Loader();
            this.loader.onError.add(() => { console.log('Error on loading texture'); });
            this.loader.onComplete.add(() => { console.log('Textures.load onComplete'); });
        }

        this.loader.add(TexturePaths.Cell).load(() => {
            this.createCellSprites();
        });
    }
    
    private createCellSprites() {
        let scale: number = this.width / baseWidth;
        let cellDim: number = baseCellDim * scale;
        
        this.cells = [];
        for (let i = 0; i < 20; i++) {
            this.cells.push([]);
            for (let j = 0; j < 10; j++) {
                let s = new PIXI.Sprite(this.loader.resources[TexturePaths.Cell].texture);
                s.position.set(j*cellDim, i*cellDim);
                s.scale.set(scale, scale);
                s.visible = false;
                this.cells[i].push(s);
                this.app.stage.addChild(s);
            }
        }

        // Test the rendering
        this.cells[19][9].visible = true;
    }

    destroy() { 
        if (this.cells) {
            for (let i = 0; i < this.cells.length; i++) {
                if (this.cells[i]) {
                    for (let j = 0; j < this.cells[i].length; j++) {
                        if (this.cells[i][j]) {
                            this.cells[i][j].destroy(true);
                            // this.app.stage.removeChild(this.cells[i][j]);
                            this.cells[i][j] = null;
                        }
                    }
                    this.cells[i] = null;
                }
            }
            this.cells = null;
        }
        
        if (this.app) {
            this.app.destroy(true, true);
            this.app = null;
        }

        this.loader.resources[TexturePaths.Cell].texture.destroy(true);
        this.loader.destroy();
        this.loader = null;
        
        PIXI.utils.clearTextureCache();
        PIXI.utils.destroyTextureCache();

    }
    
    getCanvasElement() {
        if (this.app)
            return this.app.view;
        return null;
    }

}
 

 

Link to comment
Share on other sites

There is no error message from Google Chrome console

Maybe onComplete fires at wrong time or something like that.

That's a poor man debug. Connect to android device, use adb, all that stuff. Place breakpoints in loader sources, e.t.c.

Yes, its not expected from new pixi users to do that, but you tried to launch pixi not in a browser - and honestly, we have no person in pixijs team who tracks bugs in native containers.

Link to comment
Share on other sites

After many trials, the problem is still not fixed yet. Here are some updates.

1. I logged some information.
    About the content of this.loader
        - this.loader.resources[TexturePaths.Cell].texture.baseTexture.resource.source is an HTMLImageElement object. More precisely, it is <img src="assets/img/cell.png?1622119645953">.
        - this.loader.resources[TexturePaths.Cell].texture.frame.width (and height) is 128.
        - this.loader.resources[TexturePaths.Cell].texture.textureCacheIds is an array, with ["assets/img/cell.png", "assets/img/cell.png?1622119645953"].
    About the content of this.cells[19][9] (a sprite):
        - this.cells[19][9].texture.baseTexture.resource.source is an HTMLImageElement object. More precisely, it is <img src="assets/img/cell.png?1622119645953">. Exactly the same as the loader one. Other informations are also the same as loaders.

2. I tried to draw the image of this.cells[19][9].texture.baseTexture.resource.source by Canvas 2D rendering. It can be drawn successfully. More precisely, I use the following code and the sprite's source can be drawn onto the canvas successfully.
        let img = this.cells[19][9].texture.baseTexture.resource.source;
        let canvas = <HTMLCanvasElement> document.createElement('canvas');
        canvas.width = this.app.view.width;
        canvas.height = this.app.view.height;
        let ctx = canvas.getContext('2d');
        ctx.drawImage(img, 1*cellDim, 19*cellDim, cellDim, cellDim);

3. I tried to call this.app.render() manually.

4. I tried to call this.cells[19][9].render(this.app.renderer) manually.

5. I tried to set this.loader.defaultQueryString = Date.now().

6. I tried to create sprite by PIXI.Sprite.from(TexturePaths.Cell) instead of new PIXI.Sprite(this.loader.resources[TexturePaths.Cell].texture).

7. I tried to set this.app.renderer.textureGC.mode = PIXI.GC_MODES.MANUAL and call this.app.renderer.textureGC.unload(this.app.stage) in my destroy function. 

I am still hoping to fix the problem. I like to use pixi.js. One of the major reason is that this WebGL framework (legacy version) supports the fallback to Canvas drawing when WebGL is not supported by some devices. There are a lot of other WebGL framework but I don't see they support such fallback. So, I hope I can continue develop mobile game through pixi.js. But, the first thing is to fix this problem. Thanks.

Finally, just to point out some issues about the documentation. source is one of the member of PIXI.Resource but I cannot find the description of source from the doc of PIXI.Resource (https://pixijs.download/dev/docs/PIXI.Resource.html). I found this by logging the content of the loader and keep expand the object for checking my issue. Similarly, defaultQueryString cannot be found from the doc of PIXI.Loader (https://pixijs.download/dev/docs/PIXI.Loader.html). There are some more but I am not going to point out all of them here. Thanks.

Link to comment
Share on other sites

WOW I'll show that post whenever people dont provide enough information :) That's really awesome. Gonna post it in pixijs slack and alert everyone who actually works with native wrappers.

defaultQueryString was lost in docs because of problems with resource-loader, its actually separate pixi and we are going to bring it back. You can use it - it still works.

 

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...