Scrolling Game Development Kit Forum

SGDK Version 2 => Help, Errors, FAQ => Topic started by: Tanja on 2007-12-19, 02:47:47 PM

Title: Preloading Objects
Post by: Tanja on 2007-12-19, 02:47:47 PM
dunno if its only my slow computer or if the animations i am using are too big, but maybe preloading them may help. any chance to do this and how? (searched the help for "preload", found nothing)
and should i use "unloadMap" after "ClearOverlay" to remove the map from the RAM?
Title: Re: Preloading Objects
Post by: bluemonkmn on 2007-12-19, 06:11:37 PM
Where are you seeing slowness?  Once the game is running, all the graphics should be stored in video memory (if I understand how DirectX works).  If your game is slow starting up, it might be because it is generating alpha masks.  If you have a large sprite with lots of states and frames, it can take a while to generate an alpha mask for each frame of each state because it has to look at each individual pixel for each transformed frame of each state in system RAM.
Title: Re: Preloading Objects
Post by: Tanja on 2007-12-19, 06:25:04 PM
when the player touches a plan rectangle, a new map "snowstorm" is set overlay.
this map has three layers, each filled (1 tile, virtual size: 10;10) with one tile that holds an animation. these animations consist of about 48 single images (128x128). the graphic sheet for that is a png, and i use a lot of transparency.
so, when the player touches the rectangle, all movements freeze for about a second, and then the animation is played. that is the "problem".
Title: Re: Preloading Objects
Post by: bluemonkmn on 2007-12-19, 06:36:14 PM
Does that happen every time the player touches a snowstorm tile or only the first time?
Title: Re: Preloading Objects
Post by: Tanja on 2007-12-19, 06:38:37 PM
only the first time, when he touches the plan. i could try next time to trigger the storm several times, atm it happens only once in the game. see if it pauses then.
Title: Re: Preloading Objects
Post by: bluemonkmn on 2007-12-19, 07:23:50 PM
I guess I wasn't entirely accurate when I said all graphics were loaded into video memory.  Only the graphics for the current map(s) are loaded.  If you look at Display.cs you can see a property named "Texture" in a class named TextureRef, which calls a function named GetTexture only if the texture has not already been loaded and cached.  In order to pre-load the graphics, you would have to call GetTexture on the graphics that you want to load.

The reason they aren't being loaded is because SGDK2 has no idea that you are going to load this other overlay map.  If you can do anything to force it to load those graphics, it would work.  Put a sprite that contains a graphic from that graphic sheet somewhere on the map or set the overlay and clear it really quickly at the beginning.  Normally all graphics for a map are loaded, but since the overlay is a whole separate map, SGDK2 did not know you were going to be using the graphics from that map.  There are many ways to deal with this.  Not sure which you would prefer.
Title: Re: Preloading Objects
Post by: Tanja on 2007-12-20, 05:29:09 AM
hm, i took a few tiles from the snowstorm graphic sheet and put them into my ground frameset. then i have put these tiles an one of my layers which are played. but it didn't worked properly, there is still a huge pause when starting the animation.
maybe there is another reason for this. hit me when i did unnecessary work, but i have created three tilesets, one for every snowstorm layer. at every tileset, the base is the snowstorm graphic sheet, but only one tile is animated. and the layers are filled with just this one animated tile.
(i know i need only one tileset for the three animated tiles, but so it is easier to keep the overview for me)

so, the snowstorm graphic sheet is supposed to be in the memory now, but maybe it is not storing the animations properly?
maybe i need to merge the ground and the snowstorm tiles to one frameset, and create the animations in it. (or i try the GetTexture feature you mentioned).
Title: Re: Preloading Objects
Post by: bluemonkmn on 2007-12-20, 07:09:39 AM
??? I don't know why that wouldn't fix it.  Maybe like you say the pause is coming from somewhere else.  If you want to post your project at http://sgdk2.enigmadream.com/support/ (http://sgdk2.enigmadream.com/support/) I can investigate.  :nerd:
Title: Re: Preloading Objects
Post by: Tanja on 2007-12-21, 10:10:07 AM
this GetTexture works for the graphic sheet, right? but the sheet is supposed to be in the memory already, like i described above. hm, i try something tomorrow.
Title: Re: Preloading Objects
Post by: bluemonkmn on 2007-12-22, 09:47:15 AM
Maybe the sheet isn't in memory unless you can actually see some tiles from that sheet on the screen.
Title: Re: Preloading Objects
Post by: Tanja on 2007-12-23, 04:24:29 AM
no, the tiles were seen.
this brings me to a new question, which actually a fellow student asked. (but i am not sure if i understand him correctly  :laugh:)
when the map is bigger than my screen, is the whole map stored in my RAM? or is the needed part loaded at runtime when i move around?
Title: Re: Preloading Objects
Post by: bluemonkmn on 2007-12-23, 07:50:21 AM
The whole map is stored in RAM, but only the tile numbers, not the graphics.  So if you have 1 million tiles on your layer (1000x1000 tiles), that could be 128000x128000 pixels (if your tiles are 128x128 pixels) = 16 billion pixels.  But if your layer is only 1 byte per tile, then it only takes 1 million bytes (less then 1 MB) of RAM.  Or if you use 2 bytes per tile then its 2 million bytes (under 2 MB) of RAM.  Since most systems have more than 512 MB of RAM today, that's pretty small to keep 16 billion pixels of your map in memory  :surprise:.  (If you have multiple layers, all the tiles for each layer are stored in memory.)

The tiles for the maps that aren't loaded are not kept in RAM (this is why there are unload functions for maps).  But if you have an overlay map for your snow it should be a very small map.  The data for the overlay map only needs to be 1 tile because you want the same tile to cover the whole map, so you should make the layer size 1 tile and make the layer's virtual size big enough to fill the map.  Then the map will only take 1 byte! (Actually it will probably take a little more to keep track of a couple other small things, but only 1 byte for the tiles).  The other benefit of using 1 tile and a large virtual size is that you only have to click once to fill the whole layer with the same tile.
Title: Re: Preloading Objects
Post by: Tanja on 2007-12-23, 01:01:40 PM
(If you have multiple layers, all the tiles for each layer are stored in memory.)

you mean tile numbers, here, don't you?
i already use a 1-tile-sized-layer with a virtual size, cool.
Title: Re: Preloading Objects
Post by: bluemonkmn on 2007-12-24, 09:14:08 AM
(If you have multiple layers, all the tiles for each layer are stored in memory.)
you mean tile numbers, here, don't you?

Yes, I use the terms interchangably, I guess, but I mean the tile numbers.
Title: Re: Preloading Objects
Post by: Jam0864 on 2007-12-24, 05:53:51 PM
But if your layer is only 1 byte per tile, then it only takes 1 million bytes (less then 1 MB) of RAM.  Or if you use 2 bytes per tile then its 2 million bytes (under 2 MB) of RAM.
is there an upside to using 2 bytes a tile? it seems at the moment that it is just wasting more RAM. lol
Title: Re: Preloading Objects
Post by: durnurd on 2007-12-24, 07:07:32 PM
The number of bytes per tile defines how many different tiles you can have on the layer.  One byte allows for 256 different tiles to be placed anywhere in the layer.  If you need more than that many kinds of tiles on a single layer, you'd need to use 2 bytes per tile, which allows for 65536 different tiles.  This should probably be enough for any mapper, but if you do in fact need more than 65536 different tiles on a single layer, SGDK2 has you covered.  You're crazy, and there's probably a better way to do things, but it's got you covered, because the final option is 4 bytes per tile, which lets you get up to 4294967296 different tiles per layer.

(When I say different tiles, I mean different kinds of tiles.  The size of the layer determines the actual number of tiles present on the map.)
Title: Re: Preloading Objects
Post by: Tanja on 2008-01-17, 04:41:58 PM
finally. i had the problem that my game would freeze for a little while when i came into a region, where a new (big) graphic sheet was introduced. (eg. wind streams)
it doesn't matters if this sheet is used in the same framework as the sheet for eg. rocks, which are already on the screen.

because i have a few layers, and one layer in the background with the same scrolling rate as the player layer, i can "hide" a wind tile behind a rock region in the foreground. now it takes the game longer to start, but there is no more lag while playing. condition to work for this: the hidden wind tile must be in the same start screen as the player.
i think the problem at the game start won't matter when i have build in a title screen.
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-21, 01:07:03 PM
If you look at Display.cs you can see a property named "Texture" in a class named TextureRef, which calls a function named GetTexture only if the texture has not already been loaded and cached.  In order to pre-load the graphics, you would have to call GetTexture on the graphics that you want to load.

i looked and found it. i would like to write a custom code object, where i can define the graphic sheets that should be preloaded (because they are in other maps and are set for overlay at runtime). how would i do that?

Code: [Select]
public class TextureRef : IDisposable
   {
      private string m_Name;
      private Texture m_Texture = null;
      private Display m_Display;
     
      public TextureRef(Display Disp, string Name)
      {
         m_Display = Disp;
         m_Name = Name;
      }

      public string Name
      {
         get
         {
            return m_Name;
         }
      }

      public void Reset()
      {
         m_Texture = null;
      }

      public Texture Texture
      {
         get
         {
            if (m_Texture == null)
               m_Texture = m_Display.GetTexture(m_Name);
            return m_Texture;
         }
      }

      #region IDisposable Members
      public void Dispose()
      {
         if (m_Texture != null)
         {
            m_Texture.Dispose();
            m_Texture = null;
         }
      }
      #endregion
   }
   #endregion
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-21, 06:25:38 PM
I think a line of code like this could go almost anywhere to pre-load a texture:
Display.TextureRef dummy = new Display.TextureRef(Project.GameWindow.GameDisplay, "MyGraphicSheet");
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-22, 04:38:42 AM
almost everywhere?
meins30\Display.cs(12,1) : error CS0116: A namespace does not directly contain members such as fields or methods
in this case i've placed it directly under using System.Collections; in Display.cs.
i placed it into public class TextureRef : IDisposable also, and there comes an error message about the jit debugger.
what place would be right?

edit:
i tried to make a custom object for non-scripters. but it seems i fail to provide the right path to the graphic sheet.
is there a chance to provide a drop-down list with all graphic sheets in the users project?
Code: [Select]
namespace CustomObjects
{
   public class Preloader
   {
      [Description("bla")]
      public static void PreloadObjects(Texture GraphicSheet)
       {

Display.TextureRef dummy = new Display.TextureRef(Project.GameWindow.GameDisplay, GraphicSheet.ToString());
        }
   }
}

Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-22, 06:31:54 AM
1) Almost anywhere, but not just any random place.  It has to be somewhere where you can put code (not in the root of a namespace) and you should put it in code that you know will run (not in TextureRef where nobody will call it).

2) I found a better line of code by looking at the generated Frameset.cs code:
Display.TextureRef dummy = Project.GameWindow.GameDisplay.GetTextureRef("MyGraphicSheet");

3) There is no possibility to display a dropdown list of graphic sheets.  SGDK 2.0 does not handle drop-down lists of graphic sheets (partly because there is no such thing as a "Graphic Sheet" at runtime).

4) There is no such thing a s a Graphic Sheet in generated code, so you can only refer to a graphic by name.  The parameter must be a string, and the caller must pass something like "SHFL32x32" (including quotes) as the value.
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-22, 07:50:47 AM
is it not possible to provide a thing like i had in mind?

The parameter must be a string, and the caller must pass something like "SHFL32x32" (including quotes) as the value.

i understand this. i only want to seperate it from editing source code, so an user can put it into rules.

public static void PreloadObjects(MyGraphicSheet)  <-- i only want to provide this parameter, compiling doesn't work, it asks for an identifier
Display.TextureRef dummy = Project.GameWindow.GameDisplay.GetTextureRef(MyGraphicSheet.ToString());
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-22, 06:16:41 PM
is it not possible to provide a thing like i had in mind?

Yes, just as I said by passing the parameter as a quoted string.

Code: [Select]
namespace CustomObjects
{
   public class Preloader
   {
      [Description("Cache the specified graphic sheet in video memory. GraphicSheet must be a quoted string.")]
      public static void PreloadObjects(string GraphicSheet)
      {
          Display.TextureRef dummy = Project.GameWindow.GameDisplay.GetTextureRef(GraphicSheet);
      }
   }
}

Then the parameter must be something like "SHFL32x32" (including quotes) when you define the rule.
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-23, 05:35:38 AM
thanks! it compiles now.
but somehow it doesn't work. i tried it with the graphic sheet for my wind system, which is very big, so i can clearly see the pause when the file is loaded into memory. i made a plan rule at the title screen to load the wind sheet. but when the player moves from his start place to another place with wind, the pause occurs. so the preloader doesn't work.
do you know why this could be?

(the graphic sheet is named "windrad gross". i tried it with space, an underscore instead of the space, a minus instead of the space, and finally with a fantasy name. no error message, no nothing happened)
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-23, 10:09:40 AM
First of all, verify that it is in fact loading the graphic.  Call the function (for the first time) during the game and check if you notice the delay (you shouldn't notice the delay the second time, so make sure the first time is someplace where you could notice it).

Secondly, if it's loading the graphic, it might not have stayed loaded.  It's more likely to stay loaded if you put the result into a global variable instead of a dummy variable, so try this:

Code: [Select]
namespace CustomObjects
{
   public class Preloader
   {
      static Display.TextureRef dummy = null;
      [Description("Cache the specified graphic sheet in video memory. GraphicSheet must be a quoted string.")]
      public static void PreloadObjects(string GraphicSheet)
      {
          dummy = Project.GameWindow.GameDisplay.GetTextureRef(GraphicSheet);
      }
   }
}

If that works, and you want to be able to use it for more than one graphic, let me know and I can show you how to keep a global collection of "dummies".
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-23, 11:33:57 AM
still doesn't work. i call it while the title screen is shown. because the screen fades out i could go to another place with wind before the overlay map was cleared, and there was still a pause. i think it simply doesn't load the graphic into memory.
what a role does the spelling play? if i have a space in the name of the sheet, does that matter?
Title: Re: Preloading Objects
Post by: durnurd on 2008-02-23, 11:55:29 AM
You have to replace all spaces with underscores... I think.  At least, that's the way it is with standard variables.

"Game Graphics" would become "Game_Graphics"
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-23, 01:01:49 PM
i did that. how could i verify that the graphic is in the memory? you know, like
if flag 1 is false, do load graphic, set flag 1 true
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-23, 11:10:38 PM
Did you skip step 1? First you have to verify that the graphic is loading by determining if there is a delay when you call the function.  Then you'll know if it's getting loaded.  If it runs very quickly, then you know it had an error and didn't load much.
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-24, 06:03:04 AM
First of all, verify that it is in fact loading the graphic.  Call the function (for the first time) during the game and check if you notice the delay (you shouldn't notice the delay the second time, so make sure the first time is someplace where you could notice it).

i did that for many times and tried to say that i did that for many times...
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-24, 07:40:17 AM
I don't understand -- I don't see any mention of that above.  So the result is that it's running very quickly and not loading anything?  If you don't know what string to pass, look at the generated Frameset.cs file to see what string it is passing when calling GetTextureRef.
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-25, 01:51:20 PM
please just tell me a place in some .cs-file i can insert the single line. let's try to find a good place for it.
Display.TextureRef dummy = new Display.TextureRef(Project.GameWindow.GameDisplay, "MyGraphicSheet");

p.s.: this surprises me. thought all spaces would be turned into underscores.
new System.Drawing.Rectangle(1408, 1920, 128, 128)),
new Frame(disp.GetTextureRef("windrad gross"), 126,
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-25, 07:06:55 PM
please just tell me a place in some .cs-file i can insert the single line. let's try to find a good place for it.
Display.TextureRef dummy = new Display.TextureRef(Project.GameWindow.GameDisplay, "MyGraphicSheet");

OK, search GameForm.cs for "while(true)".  That line begins the main game loop.  Add the new code right above that line in order to load the image right before the main game loop begins.

p.s.: this surprises me. thought all spaces would be turned into underscores.
new System.Drawing.Rectangle(1408, 1920, 128, 128)),
new Frame(disp.GetTextureRef("windrad gross"), 126,


Underscore only replaces space when an object name has to be converted into a C# name.  In this case it is only a string, so it doesn't need to be converted into a formal C# name like many other object names do.
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-26, 01:27:52 PM
the same.... no effect.

Display.TextureRef dummy = new Display.TextureRef(Project.GameWindow.GameDisplay, "windrad gross");

      while(true)
      {
         if (OnFrameStart != null)
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-27, 06:09:25 AM
I'm still not clear on whether that line of code is causing a delay (partly working, but then forgetting) or not (completely failing).  Can you tell me?
Title: Re: Preloading Objects
Post by: Tanja on 2008-02-27, 08:38:09 AM
there is no delay at all.
Title: Re: Preloading Objects
Post by: bluemonkmn on 2008-02-27, 10:03:25 AM
Try using the version of code that looks more like the generated code in Frameset.cs.  It obviously works in Frameset.cs, so maybe using code similar to that will work better.