Melomancheto Posted November 6, 2020 Share Posted November 6, 2020 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? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 6, 2020 Share Posted November 6, 2020 (edited) 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 November 6, 2020 by ivan.popelyshev Melomancheto 1 Quote Link to comment Share on other sites More sharing options...
Melomancheto Posted November 6, 2020 Author Share Posted November 6, 2020 (edited) 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: Edited November 6, 2020 by Melomancheto Quote Link to comment Share on other sites More sharing options...
b10b Posted November 6, 2020 Share Posted November 6, 2020 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. Quote Link to comment Share on other sites More sharing options...
Melomancheto Posted November 6, 2020 Author Share Posted November 6, 2020 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. Quote Link to comment Share on other sites More sharing options...
Melomancheto Posted November 7, 2020 Author Share Posted November 7, 2020 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; } } Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 7, 2020 Share Posted November 7, 2020 (edited) Passing app in all systems, kinda like here: https://codesandbox.io/s/smoosh-river-fie1l?file=/src/app.js Edited November 7, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.