Re: [melonjs:6816] HTMLImageElement after passing a string through functions

263 views
Skip to first unread message
Message has been deleted

Aaron McLeod

unread,
Jan 30, 2014, 8:49:31 AM1/30/14
to mel...@googlegroups.com
If you have the DOM element stored in a variable, you should be able to get it via the innerHTML property. I wouldnt recommend persisting it this way though. Typically it's cleaner to just store the image source paths, and load a new image object when you need it. Whether using the melonjs loader, or just using your own wrapper around the window.Image object.


On Thu, Jan 30, 2014 at 1:55 AM, <ayakashi.a...@gmail.com> wrote:
Hello, i have a problem converting HTMLImageElement to a string, or make a string stay as a string when being passed through functions.

I created a function to load an item database JSON, and load the resourecs using jQuery.each() with me.loader.load then save it in a game.data.database variable

this is my loader function: and I load it in play.js init

function loadImage(imageName) {
    me.loader.load({ name: imageName, type: "image", src: "data/img/items/" + imageName + ".png" }, function () { return true; }, function () { return false; });
    this.imageLoaded = true;
}

For ease of use, i want to be able to use the imageName so I could pass it to functions and get the imageName related data in the parsed JSON..

It was passed as string okay, until I reach a draw() method of an GUI_object the string being passed to.

In init, i tried console.log() to check if it the string being passed as string or not, and it is, even until the end of the init() method.
Then I save this passed string into a this.name variable so I could pass it to other method in the object.

But when it reached draw() and onClick() method, when I put a console.log() there to check if it this.name is a string, the output shows HTMLImageElement.

And since then, whenever I pass the the imageName around it turned to HTMLImageElement and I can't use it to call the data from game.data.database. because if I do this:  var a = game.data.database["item"][imageName]["itemName"], it return with error: "itemName" undefined or null

So how could I get the string as string and not an html element? I've tried toString() method but it still returned [object HTMLImageElement.]

--
You received this message because you are subscribed to the Google Groups "melonJS - A lightweight HTML5 game engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to melonjs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Aaron McLeod
http://agmprojects.com

ayakashi.a...@gmail.com

unread,
Jan 30, 2014, 10:04:06 AM1/30/14
to mel...@googlegroups.com
yeah, i'm currently getting the imageName through the .src attribute then splitting it with a limiter....at least i'm able to get the imageName...

i'm still understanding how this loader works, actually. I've read various posts here about loading resources.
at first, i was using the me.loader.load every time i need the image. but, is that wise?
because once loaded it will always loaded unless I set unload on the resource right? or am i wrong?
and since this items would appear every now and then during the play, won't it have impact to the performance to load it too often?

and this window.Image... what is it exactly? I've searched it in the docs but found none.  

Aaron McLeod

unread,
Jan 30, 2014, 10:49:53 AM1/30/14
to mel...@googlegroups.com
I should correct myself in that it's more the constructor for creating an image object: https://developer.mozilla.org/en/docs/Web/API/HTMLImageElement

Using the loader, it basically has all the images and files cached in memory. So when you use the preload function, and pass the resources, that's when it does all the requesting & loading. From then on, it is just accessing the resources from memory. When you use me.loader.getImage('name');, it's simply returning the image instance. It's not creating a new one each time or anything like that.

ayakashi.a...@gmail.com

unread,
Jan 30, 2014, 6:16:25 PM1/30/14
to mel...@googlegroups.com
About loaders, 
me.loader.getImage I understand. I've used it many times. But is the me.loader.load only load once? or is it the same as me.loader.preload but only for one item? 
I see. then why do i get HTMLImageElement when I pass the imageName as string and not object?

Back to the problem with HTMLImageElement....
when I get the imageName after doing some split to the url, and pass them to a variable to be saved before I pass it to other function, it changed to the HTMLImageElement again in the function where it being passed to, and forced me do some splitting again to get the filename. .

However, i have a bunch of resources in game.resources that have its "name" the same as the image fileName, and never had the problem about it changing into a HTMLImageElement..... It was passed as string and stay string....


is this supposed to happen when loading the image through $.each function?

        this.itemData = me.loader.getJSON("item");
        //load item image resources
        
        $.each(this.itemData.consumables, function (key, value) {
            loadImage(value.image); //this function call me.loader.load({......});
            console.log(key, value, value.image); //this return the "itemA", [object Object], "itemA" (the value of itemA.image);
        });


myJSON is build like this:

{
   "consumables": {
        "itemA": {
            "id": 2,
            "name": "item A",
            "image": "itemA",
            "price": 750,
            "type": "HP",
            "modifier": 15
        },
        "itemB": {
            "id": 3,
            "name": "item B",
            "image": "itemB",
            "price": 900,
            "type": "HP",
            "modifier": 300
        }
}

About your suggestion to store the image source path. Would it make any difference? Because even if I changed the "image" value in JSON by adding a .png, the problem still persist. I've tried searching the web on how to change this HTMLImageElement to string (and hopefully make it stay as string), but all I got is the using the .src and split it. And this doesn't work well as I said above.

Aaron McLeod

unread,
Jan 30, 2014, 7:02:50 PM1/30/14
to mel...@googlegroups.com
The loader simply uses the src attribute in the hash you pass to load to build a new image object:


It does not change the string you pass to it. The name is simply used as a key in the private hash that stores the images. Where in your code is it then becoming an image object? Can you show me how you're saving it to game.data?

Jay Oster

unread,
Jan 30, 2014, 7:12:18 PM1/30/14
to mel...@googlegroups.com
me.loader.preload will internally call me.loader.load for each resource. So they work identically, just accept different arguments. You only want to call these functions to load a resource once; there's no need to load a resource more than once. After a resource is loaded, its contents are accessible using the me.loader.get* functions.

The "loadImage" function in the original post looks wrong; `this` is used, but it references the loadImage function itself. The callbacks are also not being used, so you'll never know if the resource finished loading or if there was an error. You cannot call me.loader.get* until the resource has finished loading.

I suggest you don't do your own resource loading management. It's very difficult to get right.

ayakashi.a...@gmail.com

unread,
Jan 30, 2014, 9:52:34 PM1/30/14
to mel...@googlegroups.com
@Jay: well yeah, now i just added it to game.resources which was loaded with the melonjs preload.... the only downside is that the loading to the game might delayed for a few sec (i got a lot of assets to load).

@Aaron: it change when i pass it to a GUI_Object. Okay, to refresh anyone memory, 

I load the JSON using me.loader.getJSON in play.js init(). 
           game.data.itemdatabase = me.loader.getJSON("item"); 
(this "item" referenceing to the item.JSON i set in game.resources which are loaded with me.loader.preload(game.resources) in game onload();

and then load the image using JQuery.each
$.each(this.itemData.consumables, function (key, value) {
            loadImage(value.image); //this function call me.loader.load({......});
            console.log(key, value, value.image); //this return the "itemA", [object Object], "itemA" (the value of itemA.image);
        });
 

this is my simplified code

my button class:
Button(x, y, image){
    init: function(){
         ......
         this.image = image;
         .....
    }
    
    onClick: function(){
        var name = game.data.itemdatabase[this.image][0];
        var price = game.data.itemdatabase[this.image][1];
        game.data.item.push{
                [name, price];
        };
    };

    draw: function(context){
            //drawimage and stuff
            context.drawImage(this.image,0 ,0);
    }

}

in something.objectcontainer, i call the button in the init method:
     var imageName = "itemA";
     var a = new Button(x, y, imageName);
     this.addChild(a);


The problem happens in the Button class.
if i check the this.image value in init(), it returned string, all is okay, even to the end of the init() method.
however, once i check this.image in the beginning of onClick() or draw() method, it returned with [object HTMLImageElement].

there's nothing in my code that involved adding dynamic DOM element or even related to DOM element. it was get and set data to the game.data variable.
and other functions who reference to this game.data.item

and strangely if i do some .src splitting in the Button onClick method to get the filename, and save the result to the game.data.item, somehow other functions who get the data from game.data.item still got the  [object HTMLImageElement] as the value (i check that it was string before i set it to game.data.item). The problem disappeared when I add the resources manually to game.resources to it would be loaded along in melonjs preload. (both name and imageName has the name: ie. { name: "itemA", type:"image", src:"data/img/items/itemA.png"}.

the HTMLImage element doesn't give any problem for drawImage method, but I was going to use the string to call up data in the json because my JSON key is the string.....

Jay Oster

unread,
Jan 30, 2014, 10:09:15 PM1/30/14
to mel...@googlegroups.com
Once again, your loadImage function is wrong because it ignores the callbacks for me.loader.load() You need to use these callbacks to determine when the resource has loaded, or whether loading has failed. This is a problem, and needs to be fixed. Your code will suffer many great race conditions if this is ignored.

What class does "Button" extend? It is likely that the superclass is setting the image property to an actual image. Especially if you are extending me.SpriteImage. The `image` property is private to this class.
Message has been deleted

ayakashi.a...@gmail.com

unread,
Jan 30, 2014, 10:18:09 PM1/30/14
to mel...@googlegroups.com
oh yeah, sorry, forgot to add those two.

the button extends the GUI_Object.
and i do add the callbacks (only to check if it was loaded successfully or not through console.log) and it all loaded successfully (i've checked that). 

from the console log, i see that every item has been loaded by the time i enter the game. so i don't think it was the cause....

or should i set a counter to make sure everything was loaded before i enter the game?

Jay Oster

unread,
Jan 30, 2014, 10:25:38 PM1/30/14
to mel...@googlegroups.com
Using console.log is not good enough. ;) People who play your game are not going to use the console to verify resources have loaded. Some of them will have very slow internet connections, and some may just get unlucky and have one of the resources take forever to load. The code needs to use those callbacks to push the `good/bad` result up to the resource manager. This is why I said earlier that loading is hard. It's something you MUST MUST MUST do.

GUI_Object extends SpriteObject, which uses the `image` for private internal stuff. Use a different property name to fix the problem.


--

ayakashi.a...@gmail.com

unread,
Jan 31, 2014, 12:23:37 AM1/31/14
to mel...@googlegroups.com
hmmm, it really is hard.... well, for the moment i use the preload to load those,

but, for knowledge sake, how do i sent this result to the resource manager? would using return true and false be enough?

oh and while at it, how to make a loading screen for this loading stuff? because when it loads, it just gives me white, blank screen....or at least how to reuse the loading screen that appear the first time as a transition while doing a load,  so people know that is is loading... not freezing... (because it took me 5-10 sec to load... and that's offline.)

Jason Oster

unread,
Jan 31, 2014, 1:21:02 PM1/31/14
to mel...@googlegroups.com, mel...@googlegroups.com
You can reuse the loading screen by switching the state to me.state.LOADING.

Using me.loader.preload is good because it has a resource manager built in. When you use me.loader.load, you have write the manager yourself. Using return values in the callbacks is not enough: those callbacks need to be attached directly to the resource manager for bookkeeping.

ayakashi.a...@gmail.com

unread,
Jan 31, 2014, 10:01:37 PM1/31/14
to mel...@googlegroups.com
thanks for the explanation and answers! it helps me so much!
Reply all
Reply to author
Forward
0 new messages