-1

I'm creating a game using HTML5 and JavaScript, and it is going to be using a ton of images. Having all of those images at once takes a lot of memory, and I was wondering how I could load/unload different images so that whoever plays the game doesn't need 8GBs of memory or so just for the images.

<img src = "source1" id = "img1"></img>
<img src = "source2" id = "img2"></img>
<img src = "source3" id = "img3"></img>
<!--Just imagine this for every image, which is likely going to peak over 10,000 at some point-->
<img src = "source10000" id = "img10000"></img>

<canvas width = "1350" height = "600" id = "canva"></canvas>
<script>
var canvas = document.getElementById("canva");
var can = canvas.getContext("2d");

var imge = function(im, x, y, w, h) {
can.drawImage(document.getElementById(im), x, y, w, h);
};

var playerX = 0;
var playerY = 0;

var run = function() {
imge("img1", playerX, playerY, 32, 32);
//Need to use tones of images
requestAnimationFrame(run);
};
run();

</script>

I don't need to use 10,000 images at once, more like have 60 at once(player animations, blocks, enemy animations, particles, etc), and since I'm early in development I'm open to having to redo stuff, like how I grab images.

Question: How can I load/unload images in HTML5/JavaScrpit

  • Don't use too much images.Better create larger images with multiple sprites and animate them with CSS background positioning. Take a look here for examples: https://www.spriters-resource.com/snes/smarioworld/sheet/53664/ – Tyr Mar 10 '19 at 23:22
  • 8GB of images? What's the life-time of your game? Sounds a bit much if you're not doing an open world. Probably there is something you must check in there already. – Kaiido Mar 10 '19 at 23:45
  • @Kaiido That was exaggerating to get a point across. My game should only require 500MB at most. –  Mar 10 '19 at 23:46
  • Why exaggerate? You don't deal the same way 500MB assets and 8GB ones... – Kaiido Mar 10 '19 at 23:48
  • I meant how much memory is being used, not storage. If I load 10,000 images and I'm only using 60 of them, I'm wasting memory on 9,940 unused images. –  Mar 10 '19 at 23:50
  • But 10000 images is too much anyway. If you have more than ten, that's already a lot. As said previously, use sprite-sheets (aka image-atlas) instead. – Kaiido Mar 10 '19 at 23:53
  • @Kaiido I see your point, however its harder to program with a spritesheet than with a bunch of smaller seperate images. –  Mar 10 '19 at 23:58
  • No it's not hard, and better learn it before you go the way to write a full game, that's basics. – Kaiido Mar 11 '19 at 00:00
  • @Kaiido I meant tedious. And I can handle doing it in unity. but with HTML5/JavaScript canvas you have to individually program in the location on the spritesheet for each sprite. Since there would be 10,000+ sprites that seems like more effort than its worth. I've tried using a spritesheet for a platformer game once, but simply making the player walk and jump was more hassle than its worth for the spritesheets. This is just me being stubborn, not you being wrong. Though you are wrong since you don't agree with me >:) This is starting to get far off from loading/unloading. –  Mar 11 '19 at 00:04

2 Answers2

1

You can control loading images in JavaScript. However, you seemingly cannot force the browser to unload an image. The browser will decide for itself when to unload it from memory as long as you no longer have any references to that image in your code.

Jan-Luca Klees
  • 516
  • 4
  • 8
  • Thanks for the answer, however to me that seems like it would still be wasting memory on sprites currently being unused. –  Mar 10 '19 at 23:52
0

1) Load Images - using a js function, that triggers on page load and ensure you set sufficient cache on images so that they are just requested from network once and served from browser's cache when requested again. There are multiple ways to do this, however best done with js since you need to keep a reference variable of these images for step 2.

2) Unload images - There is no unload image from memory yet in browsers. However, you can toggle the source of image to a smaller image, when it is not being used.

3) Render function - You'll need to write a switch function to toggle in the images, when you need them & toggle out the images when not in need.

Taran J
  • 805
  • 6
  • 10
  • 1
    Your answer just gave me an idea. Would changing the SRC of an image work and then use that when going somewhere else? For instance, the image with the source of blackBlock and id 'basicBlock' when in room A, and source of whiteBlock and id 'basicBlock in room B. –  Mar 10 '19 at 23:49
  • 1
    Changing the src is a very bad idea. Like point 2 says, it will not even free memory, you'll just have loaded 2 images instead of one... + Next time you'll need to use it, you'll have to wait for the image gets parsed again, instead of being able to use it directly. – Kaiido Mar 10 '19 at 23:51
  • Yes that's my point. Point 2 makes no sense, like this answer. – Kaiido Mar 11 '19 at 00:01
  • @Kaiido: I meant there is no direct way of unloading image from memory in browsers. If you refer the link to another answer it mentions 'This ensured that the memory used for rendering large images was freed up periodically'. As such it memory cleanup doesn't happen immediately, but still happens periodically! – Taran J Mar 11 '19 at 00:04
  • @TaranJ Does it also get garbage collected eventually if the image is not removed just its src attribute changed to empty? – Firsh - LetsWP.io –  Mar 11 '19 at 00:08
  • 1
    @Vakore: 1) Yes keeping a map and naming convention can help you write optimal algorithms. 2) Memory cleanup will happen by GC whenever required by browser. Look at this answer for understanding this cycle: https://stackoverflow.com/questions/18800440/javascript-and-garbage-collection The purpose of 2) is removing reference to the image, so it is collected by GC whenever it runs. – Taran J Mar 11 '19 at 00:09
  • @TaranJ Ok, but what if its being run with in a .exe file ported with something like electron or NW.js? –  Mar 11 '19 at 00:14
  • 1
    you can trigger GC in node: https://stackoverflow.com/questions/27321997/how-to-request-the-garbage-collector-in-node-js-to-run However I have no experience with electron. this link says it should behave like browser: https://electronjs.org/blog/electron-internals-weak-references you'll need to run some tests/ create a POC to check it out. – Taran J Mar 11 '19 at 00:17
  • But why set it to an other source? You are only adding useless data to memory. If the browser needs to GC they'll do even if the src is still set. Having a resource loaded doesn't mean it's decoded. The actual pixel data (what GC will collect), is fred up when needed, even for an Image whose src doesn't change. But setting it to an other image, you'll have the fetched data in cache (raw binary) + decoded pixel data in some browsers (at least Chrome does decode by default) => very bad idea. – Kaiido Mar 11 '19 at 00:51
  • @Kaiido: unless you dont change source, the reference to original source wont be deleted, and as such on GC memory for the image wont be freed. Further: 1) You can set the source of all unused images to a same/single 1px image file. As such all image tags will refer to same file in memory. 2) Agreed on your image parsing input, when the image is reloaded, even from cache, you'll need to parse and render it again. This will always be there, however you can optimise algorithms further, eg: ensure frequent images are never 'unloaded' or use other such techniques. – Taran J Mar 11 '19 at 01:56
  • What makes you think that decoded image data are not freed? Unused graphic data is marked for GC and eventually freed, just like any volatile data. It is even sometimes never in RAM, directly piped to GPU's memory and forgotten right away. – Kaiido Mar 11 '19 at 02:02
  • What do you call unused? How will you ensure your image object become unused? – Taran J Mar 11 '19 at 03:09
  • @vakore: if this answers your problem, please mark it thanks – Taran J Mar 11 '19 at 03:10
  • An image that is not in the DOM, nor used by scripts is unused. As soon as the renderer consumed it, it can be marked as unused. – Kaiido Mar 11 '19 at 03:17
  • Yes. And how does it fit in your idea of parsing or re-rendering, that you questioned above? Plus next time you need the image, you'll instantiate a new Image object and then setup its source to load it. With the approach I listed above you wont need to create image object over and over again, and just change its source. – Taran J Mar 11 '19 at 03:52
  • No you don't get my point. The Image object doesn't get cleared, only the bitmap data will. The network resource either, it's in the cache. With your approach you are loading dummy content both in the cache and in active memory for absolutely nothing. The resource of the first image is still in cache, and the bitmap data is cleared just like it would be otherwise. All you do is force the code to be async because the browser will have to instantiate a full network request next time you need the image, even though it was stored in cache. – Kaiido Mar 11 '19 at 05:20
  • @TaranJ I'm still confused. You said changing the src just adds to memory waste, yet you suggest changing src to 1px by 1px image... –  Mar 11 '19 at 13:17
  • @Kaiido So... changing the src will save memory? You guys have confused me more than before I asked this question... –  Mar 11 '19 at 13:18
  • @Vakore: I ddnt say that. Try a POC and then run some performance tests to see behaviour & once you have working code tweak to optimise it. && 1px image wont cause memory waste, it will hardly take some bits in memory. – Taran J Mar 11 '19 at 23:56
  • @TaranJ A: What is a POC? B: But if changing the src does nothing to reduce memory, why change it? –  Mar 12 '19 at 00:18
  • Dont get confused by this thread and simply ignore it. Refer to actual answer, and try a POC/prototype (Proof of concepts), and run some tests to validate. Although I doubt it, However, When you have a working code, try a variation without step 2) and compare performance; as what @kaiido is hinting towards. I would appreciate if kaiido could add another answer as per his understanding and that would have avoided the confusion here. – Taran J Mar 13 '19 at 02:34
  • @TaranJ the whole question here is an X-Y problem. Simply put, there should not be the need to unload anything. That's simply a question that should not have arise with a good design. I already told the OP the correct way to deal with the X (texture atlas / spritesheet) answering the Y is not something I'll do, because it has no applications and makes no sense (and is impossible to truly control from web-apis). I started this thread on your answer because you are giving dangerous advice. – Kaiido Mar 13 '19 at 02:42