Jump to content

How to access resource texture right


Melomancheto
 Share

Recommended Posts

I'm trying to get the texture of already loaded image and pass it to the PIXI.Sprite.

 

import { Loader } from 'pixi.js'

export default class SpriteLoader {
    constructor(sprites) {
        this.loader = new Loader();
        this.loader.baseUrl = 'assets';

        this.loader.onProgress.add(this.showProgress);
        this.loader.onComplete.add(this.doneLoading);
        this.loader.onError.add(this.onError);
    }

    add = (name, file) => {
        this.loader.add(name, file)
    };

    load = () => {
        this.loader.load();
    }

    texture = (name) => {
        console.log(this.loader.resources[name]);

        return this.loader.resources[name].texture
    }

    showProgress = (event) => {
        // console.log(event.progress);
    };

    doneLoading = (event) => {
        // console.log('DONE LOADING')
    };

    onError = (event) => {
        console.error("ERROR: " . event.message);
    };

}

const loader = new SpriteLoader();
loader.add('dirt', 'dirt.png');
loader.load();
loader.texture('dirt');

I have a simple class that is wrapping the loader.

When I instantiate the loader I use a few wrapper functions to load the needed .png files, so far so good.
When I try to access the loaded image image texture to pass it in the constructure of the Pixi. Sprite is where the problem occurs.

I can see that I have a Resource object and it has a texture. When I try to access it  with 

this.loader.resources['NAME_OF_THE_TEXTUE'].texture is undefined for some reason. What am I doing wrong?
Am I accessing it somehow wrong or what?

 

MjwX71a - Imgur.png

Link to comment
Share on other sites

Loader is async, it waits while browser actually loads the image.

What you need is Texture.fromUrl('myImage.png') - it does not wait, creates texture prematurely, with width=1,height=1,valid=false, you can pass it to sprites and they'll be resized later automatically. 

In this case, just dont use the loader.

Alternatively, you can try figure out how to do things asynchronously :)

Edited by ivan.popelyshev
Link to comment
Share on other sites

Since I'm kinda new and still reading around and watching repos how people do it. What is the best way to approach this if I use the Loader?

Should I add a listener for loaded images and when they load I continue to the logic of my game or this is going to slow down everything?
I Saw that the loader has a build in cache aswell that I may use. I have my sprite extended from a class that I have and the constructor only accepts Textures, so this is one more thing
I need to think of I gues? What would be the bes t way to approach this? Right now I'm trying to build a map builder with blocks. So there will be a lot of images loading most likely.

I'm trying out the Texture way that you suggested.

Texture.fromURL('assets/dirt.png').then(result => {
	const dirt = new Dirt(result);
	const block = new Block();
	block.create(dirt);
});

This is my code that is creating the Texture and adds it to the Stage. I've noticed that Texture.fromURL() is returning a Promise I guess for better image handling. I created 2 classes that will take care of the Block that I want to display. Since I have different type of blocks, my idea is to have a Block class that will take care of the rendering of the specific block and a Dirt, Grass, Water class for each type of block that I want to render on the Stage.

The Dirt class that Extends Sprite as It says HERE.
 

import { Sprite } from 'pixi.js'

export default class Dirt extends Sprite {
    constructor(texture) {
        super(texture);
    }
}

and the Block class that uses the create method (for the testing) to add to the stage the type of block that I've created from a Texture that I loaded in the Sprite class. The Block class on the other hand is Extending a Builder class that is Extending the Application Class of PixiJS so I can have access to the view and the stage.

import Builder from "./Builder";

export default class Block extends Builder {
    constructor() {
        super();
        this.source = null;
    }

    create(source) {
        this.stage.addChild(source)
        // this.stage.on("pointermove", this.moveTile);
    }

    moveTile = (e) => {
        let pos = e.data.global;

        this.source.x = pos.x;
        this.source.y = pos.y;
    }
}

When I try to add the child that I passed to the create() method of the Builder class that is a Dirt class that extends Sprite, nothing happens. When I console.log the dirt class it seems to be okay. There are no errors in the console or anything. It just doesn't display the block.

When I use a Non OOP way and spit everyting in a single file it works like a charm.

For example a sprite that follow the cursor.


 

Texture.fromURL('assets/dirt.png').then(result => {
	let player = new Sprite.from(result);
	player.x = app.view.width / 2;
	player.y = app.view.height / 2;
	player.anchor.set(0.5);

	app.stage.addChild(player);


	app.stage.on("pointermove", moveTile);

	function moveTile(e) {
		let pos = e.data.global;

		player.x = pos.x;
		player.y = pos.y;
	}
});



I'm probably doing something wrong when extending but I can't seem to find what.

This is my block class:


 

Screenshot 2020-11-06 185456.png

Edited by Melomancheto
Link to comment
Share on other sites

5 hours ago, Melomancheto said:

Should I add a listener for loaded images and when they load I continue to the logic of my game or this is going to slow down everything?

Generally, I'd say yes, do this.

"Preloading" the bulk of your resources up-front makes life much easier as your loading logic is behind you and you can be confident the resource is available when called at runtime (no popins, no undefineds).  Does it slow down everything? ... a preloader delay is a somewhat expected part of the UX so doesn't count against you even if it does slow things down fractionally.  If that's a big concern then more advanced approaches can partition resources into multiple loaders (e.g. tier 1 = required by all, tier 2 = conditional based on user choices) and also individual loaders for on-demand content.  Then trigger them (and wait for them to complete) at the appropriate point in the user experience.  However this can count against you as it's not always expected UX to have to wait for a level, or a shop, or modal, etc to load - so adopt sparingly.

 

Link to comment
Share on other sites

25 minutes ago, b10b said:

Generally, I'd say yes, do this.

"Preloading" the bulk of your resources up-front makes life much easier as your loading logic is behind you and you can be confident the resource is available when called at runtime (no popins, no undefineds).  Does it slow down everything? ... a preloader delay is a somewhat expected part of the UX so doesn't count against you even if it does slow things down fractionally.  If that's a big concern then more advanced approaches can partition resources into multiple loaders (e.g. tier 1 = required by all, tier 2 = conditional based on user choices) and also individual loaders for on-demand content.  Then trigger them (and wait for them to complete) at the appropriate point in the user experience.  However this can count against you as it's not always expected UX to have to wait for a level, or a shop, or modal, etc to load - so adopt sparingly.

 

This is just what I was thinking about. Cuz I imagine this as a loading bar showing while the images are being loaded to the game. After they load you remove the banner for example and navigate them to the game. Everything else that you need to load will be loaded on the go. I have something like that in my head.

Link to comment
Share on other sites

I found the problem in the OOP code. The problem is me extending Application and them a class inherits it and another class inherits the class that inherits application (damn that sounds weird). Javascript does not support this natively. so I guess I will need to pass the application in the constructor of every class that I need.

Here is some code for example:

This is my entry file.

// App with width and height of the page
const app = new Application(document, {
	width: 500,
	height: 500,
	resolution: 1,
	backgroundColor: 0xAAAAA,
});

Texture.fromURL('assets/dirt.png').then(result => {
	const dirt = new Dirt(result)
	const block = new Block();
	block.create(app, dirt);
});

This is the file that take care of building my block and adding it to the screen with interactions:

 

import Builder from "./Builder";

export default class Block extends Builder {
    constructor() {
        super();
    }

    create(application, source) {
        this.source = source;
        application.stage.addChild(source)
        application.stage.on("pointermove", this.moveTile);
    }

    moveTile = (e) => {
        let pos = e.data.global;

        this.source.x = pos.x;
        this.source.y = pos.y;
    }
}

 

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