Jump to content
New account registrations are disabed. This website is now an archive. Read more here.
  • 0
justabox21

Pre-Cache graphics for less lag

Question

Is there a way to "pre-cache" (If that is a real thing) a specified group of pictures so that when they are used in sequence to make a cutscene there will be less lag?

Share this post


Link to post
Share on other sites

15 answers to this question

Recommended Posts

  • 0

Yes there is. Just insert a script before Main and load the graphics you wish using this line:

RPG::Cache.picture("<your picture's name>")

For each graphic you wish to load (assuming they're all pictures, otherwise you have to change the method name accordingly, i.e. RPG::Cache.character for characters)

 

If you don't want to bother inputting all your pictures' names, you can have the game load all files from the Pictures directory instead. This piece of code should do the trick (untested):

valid_ext = ['.bmp', '.png', '.jpg']
for filename in Dir.entries("Graphics/Pictures")
 if valid_ext.include?(File.extname(filename))
RPG::Cache.picture(filename)
 end
end

 

Also, if you have lots of graphics to load, you might want to add a Graphics.update inside the loop to prevent the "Script is hanging" error.

Edited by Moonpearl

Share this post


Link to post
Share on other sites
  • 0

Moonpearl is right; but if I remember correctly, you were having issues with too many bitmaps loaded into memory at once and you had to clear the cache to prevent the game from crashing, right?

 

So, to build on what Moonpearl said, you'll have to make a call to

RPG::Cache.picture("picture_name")

for the bitmaps you want to Cache. Then, the next time they are called with the same line of code, it will return the bitmap from memory rather than loading it into memory then returning it.

module Cutscene_Loader
 def self.load(filenames)
filenames.each do |filename|
  RPG::Cache.picture(filename)
end
 end
end
CUTSCENE_1 = [
 'filename1',
 'filename2',
 'filename3'
]
Cutscene_Loader.load(CUTSCENE_1)

 

This will cache all files from the picture folder, contained in the array that is passed to #load

 

If you wanted to extend this to ANY folder:

module Cutscene_Loader
 def self.load(type, filenames)
filenames.each do |filename|
  RPG::Cache.send(type, filename)
end
 end
end
Cutscene_Loader(:picture, CUTSCENE_1)
# works with any of the RPG::Cache methods passed in as a symbol

 

One thing to keep in mind though, if you were having lag issues with loading them into memory, you may still want to account for possible performance issues.

 

If loading all the bitmaps at once causes issues, you can design the Cutscene_Loader to utilize "incremental" loading:

class Cutscene_Loader
 def initialize(type, filenames)
@type = type
@filenames = filenames
@index = 0
 end
 def loaded?
@filenames.size - @index  == 0
 end
 def update
unless loaded?
  RPG::Cache.send(@type, @filenames[@index])
  @index += 1
end
 end
end

loader = Cutscene_Loader.new(:picture, CUTSCENE_1)
until loader.loaded?
 loader.update
end

 

Then you can use the loader, in the scene prior to the cutscene (if this is possible), you can update the loader at specific times (every other frame, etc), to spread out the workload involved.

 

Or, you could take advantage of the call script event:

1. Create an event (parallel process/autostart)

2. Add a bunch of single "call script"s, with a call to

RPG::Cache.picture("filename")

for each file.

3. At the end, flip on a switch that turns off the event.

 

Then, when that switch is turned on, you know that the pictures are loaded into memory. Also, this takes advantage of the fact the event interpreter in RPG Maker has a frame delay between event calls, so this will automatically spread out the workload of processing the graphics. (Would probably be better as a parallel process, since autostart halts everything else.)

 

You could also make such calls between "Message" boxes for dialogue.

 

If you can hide all the loading in sneaky places, the loading process can remain transparent to the player.

Share this post


Link to post
Share on other sites
  • 0

Wow this is alot of information (Not that I'm complaining, I really do appreciate all the help)! Ok, I'm gonna give this a try. Since I'm using "show picture commands" to make cutscenes I have a bunch of pictures. Like hundreds. I'll try using that directory method first and hope it doesn't kill my computer, lol.

 

Ok, so I tried doing the one Moonpearl said where instead of loading each frame individually I just load them all from a directory. This is what I did, and I got a syntax error. Does this look right?

 

 

valid_ext = ['.bmp', '.png', '.jpg']

for filename in Dir.entries

("Desktop/Project/

Grave

Prosperity/Cutscenes/Intro/

Apartment")

if valid_ext.include?(File.extname

(filename))

RPG::Cache.picture(filename)

end

end

Edited by justabox21

Share this post


Link to post
Share on other sites
  • 0
I got a syntax error.

What line?

 

Does this look right?

If you wrote it exactly as shown here, then there are 2 problems:

  • You shouldn't break lines unless you know exactly what you're doing. I suspect the syntax error come from either the second or third line being broken improperly
  • Why did you enter your project's folder in the directory path? I would have told you so if it was required. Just input the path assuming you're already in the project's folder like I did in my example. Besides, Desktop being your drive's root folder is Windows bullshit, Ruby won't ever find your project using such syntax. Also, it seems like your pictures are NOT in the Graphics/Pictures folder, that's not a good thing because the RPG::Cache.picture method can't find them. Put your pictures in the Pictures folder, or at least in a subfolder from there, using:

RPG::Cache.picture("<your path from Graphics/Pictures>"/#{filename}")

Share this post


Link to post
Share on other sites
  • 0

folder = 'Cutscenes/Intro/Apartment'
files = Dir[folder + '/*.{png,jpg,bmp}']
files.each {|file| RPG::Cache.load_bitmap(folder, file) }

 

I think this should do the trick.

 

If you want to do multiple folders, or recursively search the entire "Cutscenes" folder, you could also do this:

 

folder = 'Cutscenes/**/**'
files = Dir[folder + '/*.{png,jpg,bmp}']
files.each {|file| RPG::Cache.load_bitmap(folder, file) }

 

I haven't tested this, I don't really have any folders structured like that to test at the moment...

Edited by ForeverZer0

Share this post


Link to post
Share on other sites
  • 0

@Moonpearl: I didn't actually break the line, that was the way the call script window had it set up after typing in the directories. I think the "prosperity" part was too long for it to stay on the same line in that tiny call script box. I just copied and pasted it the way it was. Which part goes above Main? Was it the whole thing or is that how I call it when I need it? The syntax error was just a window that said "A syntax error occurred while running script".

 

And as far as the directory's path goes, that was my mix up. I didn't realize you were putting in a literal path to follow, I thought your directory names were just an example guide line for me to go by. I get it now though, my mistake. The pictures are in the project's graphics/pictures area, I was using the original location of the pics before they got imported into RMXP. I'm going to do it again the right way and see what happens. Sorry about the crazy mix up!

 

@ForeverZer0: I also tried out your script. The weird thing is RMXP isn't ever reacting to the call script, like it isn't even there. I tried it the first time and the scene still lagged, then I tried it with a purposely misspelled directory just to see if it would catch it and it just went on like nothing was even there..

Edited by justabox21

Share this post


Link to post
Share on other sites
  • 0

You're right. I forgot that the found files will include the folder and extension of the file.

This will work, I actually even tested it.

 

folder = 'Graphics/Characters/'
files = Dir[folder + '/*.{png,jpg,bmp}']
files.each {|f|
 name = File.basename(f, File.extname(f))
 RPG::Cache.load_bitmap(folder, name)
}

 

It shouldn't actually "do" anything, it's just caching images to prevent lag later. Exactly how are you using this anyway? In all reality, if this is just a single scene that is scene once, its probably not a good idea to use the RPG::Cache. You can cache images anyway you please, even just add them to array to reference later. It is pointless to cache all sorts of images into RAM where they will continue to take up memory when they were only needed once.

 

If this is your scenario, it would be much wiser to simple create an array, fill it with bitmaps, use them for whatever you are doing, which I will guess is some sort of animation since speed seems to be an issue, and then iterate over the array and dispose them when you're done.

Share this post


Link to post
Share on other sites
  • 0

Yeah I'm just using this for specific cutscenes that will be seen only once throughout the game. I'm not sure what an array is though. If it means anything, I am also using a clear cache script after I have used the required pictures in a cutscene in order to clear up RAM. Assuming that I'm using these things right, that is.. I hate to say it but when it comes to scripting I am one dumb bastard, so I'll need to be guided Barney style if I'm going to get this right.

 

Well I tried your new script and it seems to be working quite nicely! The FPS didn't drop below 37, and I am using tons of pictures for these cutscenes so that's really saying something. Of course I am still curious about that array thing you put out there earlier.

Edited by justabox21

Share this post


Link to post
Share on other sites
  • 0

If you three wouldn't mind, I'd like to give a shot at answering the array question...

 

What ForeverZer0 was suggesting is that you load all your pictures into one variable (which makes the variable an array for having multiple items stuffed into it) and use that array whenever you wanted to cache something. ForeverZer0 does have a working code using such a method. When your done, just clean the cache. When you want to use it again(if ever) just call the array again to cache everything back in. (ForeverZer0, if that's not what your doing, or I'm being too presumptuous, send me a hot scalding pm about it then xD)

Share this post


Link to post
Share on other sites
  • 0

Yeah, you pretty much got it right. The RPG::Cache is a very handy tool to prevent the constant re-loading of commonly used graphics in the game. It basically just loads a bitmap, and instead of disposing it and letting it get picked up by the garbage collector, it retains a reference to it, which means next time you need it, its already loaded and ready to go, no loading.

 

Obviously the more images you cache, the more memory (RAM) the game is going to use, since it is "remembering" all these cached images. For most circumstances, this completely fine, since throughout gameplay, the same graphics are being used over and over again.

 

There are special circumstances that I would advise against the RPG::Cache, and simply create your own container for images. Such circumstances are when you are using a large amount of graphics that are only going to be used once, such as a cutscene that will not be repeated. Basically what is going to happen is this:

 

Lets say you load 100 images to make an animation, and each image uses 500 KB of memory. This means that if you are using RPG::Cache, you are loading 50 MB of stuff into memory that will remain there until the game closes, just for a brief scene that will never be seen again. In this case, instead of using RPG::Cache, you could do something like this:

 

 

@bitmaps = []
folder = 'Graphics/Characters/'
files = Dir[folder + '/*.{png,jpg,bmp}']
files.each {|f|
 name = File.basename(f, File.extname(f))
 @bitmaps.push(Bitmap.new("#{folder}/#{name}"))
}

# Do whatever you need with your bitmaps, cycle through animation, etc.

@bitmaps.each {|b| b.dispose }

 

This will pre-cache your images to prevent lag, still do what you need, and release the memory when you are done. It all depends on the circumstances the bitmaps are being used. I am merely making an assumption based on the need of so many bitmaps and the fact the folder he is loading from us label "Cutscene/Intro".

Share this post


Link to post
Share on other sites
  • 0

@Foxkit: Ok, that makes sense. Arrays aren't so complicated afterall. Thanks for the helpful input!

 

@ForeverZer0: That "Cutscene/Intro" label I was using originally was from a separate folder outside of my RMXP Project. I have the needed pictures inside the normal "Graphics/Pictures" area of the project too though. But I think your post before this one pretty much fixed my lag issue.

Share this post


Link to post
Share on other sites
  • 0

You missed the whole point of the post then. It wasn't about where the files were located, it was about freeing up worthless RAM when you are done using the pictures, no matter where they are loaded from, and avoiding the RPG::Cache if circumstances warranted it.

 

Its not a big deal though, more of a general programming tip about managing memory efficiently, but its just a homebrew RMXP game, not a large application that requires it.

Share this post


Link to post
Share on other sites
  • 0

I think, ForeverZer0 is probably unaware of your current situation. His approach is correct, and perfect for usual RPG Maker games but in your case you are clearing the cache often to avoid rpg maker from crashing (from too many/too large bitmaps), correct?

 

His approach was in terms of a scenario where you wouldn't want to clear the entire cache but if you are currently clearing the cache sometime before the scene and again after the scene--then it wouldn't make much of a difference.

 

If you aren't clearing the cache before the scene, then this approach would be good (and you can save the other bitmaps that are still in the cache)

 

ForeverZer0 is simply just using an array to build a "local cache" (if you will) of bitmaps, and explicitly freeing the memory after through "bitmap.dispose"

 

With RPG::Cache.clear, RPG Maker clears out all references to the global cache, and asks the Garbage Collector to cleanup instead. The Garbage Collector knows how to free up dangling references to bitmaps. So essentially, it works the same, except with regards to the Cache that is targeted. ForeverZer0 clears a local cache, RPG::Cache.clear clears the global cache

Share this post


Link to post
Share on other sites
  • 0

Oooh ok, that makes sense. Yeah you got it right in that first paragraph about the too many large bitmaps. So we're essentially all doing the same thing, just on different scales.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...