Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (580)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Resource Loading manager. Onto memory or not?  (Read 1869 times)
0 Members and 1 Guest are viewing this topic.
Offline Ryonik

Senior Newbie


Medals: 1



« Posted 2012-08-16 20:10:41 »

Since I don't mind reinventing the wheel for the sake of learning something I've been working on a small engine/framework as a foundation to work on some simple games. When I was working on my imageLoading manager (part of the resourceLoading bundle), at the moment I have it set up in a way that once a image is loaded, its temp. held (in memory) by the program as long as its running. If a call asks for an image that hasn't been loaded yet, it does so, else it returns the copy that was loaded and stored in a hashmap (which essentially is in memory).
I've also done pretty much the same for my audioResourceLoading manager.

Now what I'm thinking of implementing down the road is that the imageLoading manager only holds image files that are under a certain size or animations (other things like static backgrounds can be reloaded if needed).
And as for the audio, if its sound effects its pre-loaded onto a clip and therefore its held in memory. But for large audio files like background music, I'm thinking of maybe streaming it and buffering it so that its played as its loaded, with a sourceDataLine.

One thing I'm wondering is, I know when i load an image and an instance is presenting it on the screen (using it as representation), its being held in memory. Now if I'm putting a copy of it in a hashmap will that copy be in memory as well? or is it using the same memory space as the first one that was loaded? Same goes for when I create other instances that use this same image as a representation. Does anyone know?

And yes I know tools like Slick2D handle all this resource loading stuff for you (or so I've read), but I'm mostly doing it for the learning experience. For example to get that audioLoader going I learned a great deal of the sound API.

 So yeah, just wanna hear some thoughts on this.  Grin
Offline Best Username Ever

Junior Member





« Reply #1 - Posted 2012-08-17 03:59:50 »

If you're using a desktop or laptop then preload whatever you might use and never load resources you'll never use. If you can have the user (programmer) inform the engine of what resources they will need later, then prioritize storing those resources - leaving resources that might be used in the next level if you want to save future loading times OR freeing resources to make room for non-resources. For example if you're loading an ice level in a tile based games you don't need to keep magma, dessert, grass, sky world, or underwater tilesets unless you want to save loading times later. Besides the obvious benefits, this would also let you use a greater variety of art while still using the same amount of ram. Sound effects, tiles, animations, sprites, textures, and models should be preloaded this way. Background music and images are harder, but I would not stream them. For background music, you can sort of get the best of both worlds by loading an entire song and the first 5 seconds of alternate background music as a clip. Hopefully then you wouldn't need to pause music while loading.

In terms of total memory usage, I would use excess memory to your advantage if you have it. For all types of programs, you need to worry about crowding out other programs. Ordinary programs shouldn't be greedy, but players understand that they should close other programs if they want better performance, especially for full screen games. Don't waste memory but don't force users to change their hardware, operating system, or habits either. I'm guessing memory management efficiency problems are over hyped and I can't think of any other reason why using less memory than the total physical memory available would slow down most applications. Transferring data to and from different mediums over and over again seems like a bad idea (but I'm biased because hard disk noises have just started to really annoy me a lot more recently.) Maybe try other methods to save space like compression, procedural art, replacing similar tiles on lower end systems, simplifying models, shrinking textures, loading lower bit rate, lossily compressed audio, etc. I think 3D games use similar methods to save video ram, so you could implement a system that allows for adaptive changes or user supplied quality/performance settings.

For a game engine, it probably would be nice to give the developer more control so it can be reused in games where all resources can fit in memory, games with heavy resource usage that require good rendering performance, and games that don't require many resources and would prefer using that memory for game specific data structures or artificial intelligences. Since I'm not really sure what's best in practice or what other games/engines try to do I'd like to see what other people think. I think a lot of my suggestions also apply to non pc platforms, but maybe they're not worth as much since the memory may be slower and it might be quicker to transfer data from flash memory storage.
Offline kaffiene
« Reply #2 - Posted 2012-08-17 09:35:00 »

Regarding caches, my opinion is that SoftReferences provide the perfect solution.  Have a resource manager that loads everything with soft references - never free anything.  If the the VM needs more memory, it will clear up any cached objects you aren't currently using.  When you need the resources, check if they're loaded and reload them if required.  Here's the guts of one I used earlier:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
    /** image cache */
    HashMap<String, SoftReference<BufferedImage>> imageCache =
            new HashMap<String, SoftReference<BufferedImage>>();

    public BufferedImage getImage(String imageName) {
        SoftReference<BufferedImage> ref = imageCache.get(imageName);

        if(ref == null){
            // we've never stored this image
           BufferedImage img = null;
            try {
                img = ImageIO.read(new File(imageName));
            } catch (IOException ex) {
                // handle exception
           }
            imageCache.put(imageName, new SoftReference<BufferedImage>(img));
            return img;

        } else {
            // we've stored this image before...
           BufferedImage img = ref.get();
            if(img != null){
                // .... return the previously cached image
               return img;
               
            } else {
                // ...however it's since been garbage collected.  Clear the record from the
               // cache and call this method again. It will attempt to load the image
               // when there is no entry for the image in the imageMap
               imageCache.remove(imageName);
                return getImage(imageName);
            }
        }
   }


Personally, I think SoftReference (and Weak and Phantom references) are brilliant features of the JVM which are generally under-employed.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline sproingie
« Reply #3 - Posted 2012-08-17 22:31:34 »

You also might want to look into Guava, specifically CacheBuilder which can construct weak-valued maps and clean up collected entries for you.

Offline Ryonik

Senior Newbie


Medals: 1



« Reply #4 - Posted 2012-08-18 06:05:32 »

Great, thanks people:

@sproingie and kaffiene, thanks for the insight! I'll definitely will be looking more into the CacheBuilder and the Reference classes (I've mildly seen them in the API, but I'm definitely gonna take a better look at those you mentioned there).  Cheesy

@Best Username Ever, thats a lot of great tips, I'll have to re-read to fully absorb it all, but by any means, thanks for taking the time to write that and give me more to think about/look into/try out.  Wink
Offline Gingerious

Junior Member


Medals: 2



« Reply #5 - Posted 2013-01-10 18:27:21 »

Kaffiene, that's a pretty cool implementation, but does this make it more difficult to deal with sprite sheets?  It seems, if you want to deal with an animation with multiple frames, this would have to be modified a bit.
Offline Gingerious

Junior Member


Medals: 2



« Reply #6 - Posted 2013-01-14 23:13:32 »

Ok, I took another look at it and I modified the function to handle sprite sheets.  It's not perfect, but it works well enough for me:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
public BufferedImage getImage(String imageName, int row, int col, int width, int height){
      SoftReference<BufferedImage> ref = imageCache.get(imageName+row+col);
     
      if(ref == null){
         BufferedImage img = null;
         try{
            img = ImageIO.read(new File("src/images/" + imageName + ".png"))
                  .getSubimage(col*width, row*height, width, height);
         } catch (IOException ex){
            //handle exception
           System.out.println("src/images/" + imageName + ".png");
            System.out.println(ex.getMessage());
         }
         
         imageCache.put(imageName+row+col, new SoftReference<BufferedImage>(img));
         return img;
      }else{
         //we've stored this image before
        BufferedImage img = ref.get();
         if(img != null){
            return img;
         }else{
            imageCache.remove(imageName+row+col);
            return getImage(imageName, row, col, width, height);
         }
      }
   }


Here, you have to give it a row, column, width of the image, and height of the image.  I went ahead and said "give it a sprite sheet and a location on the sheet, if it can't find it, it loads the sheet, cuts the image out, and saves it back into the image cache".

Bad news is that you have to keep track of the row/column of the animation you need.  I have an animation class that handles it currently, but as far as the resource handler is concerned, there you go.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (50 views)
2014-04-15 18:08:23

BurntPizza (46 views)
2014-04-15 03:46:01

UprightPath (62 views)
2014-04-14 17:39:50

UprightPath (44 views)
2014-04-14 17:35:47

Porlus (60 views)
2014-04-14 15:48:38

tom_mai78101 (84 views)
2014-04-10 04:04:31

BurntPizza (142 views)
2014-04-08 23:06:04

tom_mai78101 (242 views)
2014-04-05 13:34:39

trollwarrior1 (201 views)
2014-04-04 12:06:45

CJLetsGame (208 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!