Game Development Community

Sharing Scene Graphs ...

by David Higgins · in Torque Game Builder · 02/11/2007 (1:41 pm) · 6 replies

I came up with an idea to create a 'mini map' ... and have prototyped it in about 5 minutes by making slight modifications to my "split screen starter kit" that I posted a while back ...

Basically, the concept is fairly simple -- create a GUI that has a scene window in it, then in code, push the GUI onto the canvas and then set the scene graph of the GUI's scene window to the value of the sceneWindow2D.getSceneGraph() -- this basically makes the smaller scene window reference the 'game' scene graph ...

Scene Window control the Camera, so the smaller "mini map" can be zoomed out and even looking at different parts of the map then the player is currently on (look ahead or behind on the mini map, for example) --

However, there's a few flaws in this, one of which is that the mini map is sharing 'everything', including AI Units, etc, etc ... and there is no "replacement" concept or "hide" concept that I can think of, since the Scene Graph is a reference to the other scene graph ...

So ... I figured I could probably easily create a custom 'load level' concept that built my level for me, and made copies of objects in the two scene graph when necessary (tile layers, static objects, etc -- skipping mobile objects) and then creating a new tile map that is the size of the entire level, and filled with black tiles (fog of war) ... and then I could control the fog of war as the player moves around the map and start removing black tiles one by one or in an octagon shape around the player ...

Now... this all sounds 'great' and would even work ... whats the problem? Well, now i've got duplicate copies of most of my level objects, and the problem is, the things I'm duplicating are probably the things that consume the most memory (large tile maps, tons of duplicate static sprites [trees, etc])

What to do now ... ?


Well ... my next thought was this ...

What if I created a custom Level Builder tool that was able to "play" the level, but only loaded what my mini-map would display, and then zoomed out to fit the entire world on the screen ... then took a screen shot and saved it in the level directory with the same name as the level ...

Wait ... what?

Ok ... I would then take this screenshot, and load it into a Static Sprite into the mini-map scenegraph ... set my zoom level and camera position, build the custom tilemap for the fog-of-war ... and be done with it ...


Well ... what if my level is HUGE?! TGB has a limit on image sizes, doesn't it?

Well, thats where the fun comes in ... I could make the world map screenshot set to whatever resolution I want too, by having my tool change the resolution of TGB "on the fly" using the "setScreenMode" and then use the screenshot function ...

Problem with the setScreenMode function is, it won't let me go below 640x480 ... which I'm not sure if thats a system specific issue (video card limitation, OS limitation, or engine limitation?) -- well ... either way ... no biggy ...

So if my map is rectangular, and is longer then it is tall ... wouldn't I have extra "blank space" in my screenshot? yeah ... I would, if I didn't account for the width/height differential before setting my screen resolution and snapping the screenshot ...

#1
02/11/2007 (1:41 pm)
Once I get that figured out, it's more or less just a matter of adding a "loadMiniMap" function and pass a the same value into it as I did for "loadLevel" ... then attach ".png" or ".jpg" to the end of the level file name, create a new ImageMap of it, then toss a t2dStaticSprite object into the mini-map scenegraph, and assign it to the newly created "mapImageMap" ... then determine the size of the t2dStaticSprite (which I should know, since I had to set it when I created the sprite, no? -- Yep...)

How to get the size of the sprite? Hrm ... I could have my tool report back the screen resolution, but TGB uses "relative" coordinates ... so "744x522" doesn't translate properly ... no big deal, I can just drop the jpg into the level builder and get the default starting size ... then if I want to shrink it down or anything, I can resize the image with photoshop or just resize it dynamically in the level builder till I'm happy ... the store the size of the map in the Level's Dynamic Fields ... so I can retrieve it later -- little extra work, yeah ... but without making C++ modifications, it'll have to do ...

So ... now I create my tilemap with the black tiles filling it ... this emulates my "fog of war" ... when the player starts moving around, I keep tabs on the player objects position, and then translate it to my minimap coordinates ... which should be some fairly straight forward math since all I have to do is determine the difference between main scenegraph and the minimap scenegraphs' overall size ... once I get that, I simply just call "pickTile" and pass the players world position in ... and i can start clearing tiles around it fairly easily ...

If the player was at, "100 -52" in world coordinates, and I get back "45 12" from the tile map by calling pickTile ... I can easily remove the 5 tiles around the player (tile the player is "on" and the one above, to the left, right and bottom of the player ... ) by adding 1 and subtracting 1 to 45 and 12 ... I can get the 45 and the 12 by using getWord ...


Summary

Ok, what was the point of this post? Not really sure ... I'm just voicing out an idea I came up with and thought I'd share it with others and see what they thought of it ... and, if anyone was struggling with how to do something like this, perhaps this can help ... I don't really have the time to go full-out on this and actually implement it in a reasonable time frame, so I figured ... why let the idea float around and dissipate slowly ... get it out there ... so, I hope this was either educational, helpful or at least comedic ... either way, enjoy.

And feel free to comment ... :)
#2
02/11/2007 (1:57 pm)
Quote:However, there's a few flaws in this, one of which is that the mini map is sharing 'everything', including AI Units, etc, etc ... and there is no "replacement" concept or "hide" concept that I can think of, since the Scene Graph is a reference to the other scene graph ...
You can try: t2dSceneWindow.setRenderMasks()

When I was building a mini-map with a smaller scene window I ran into the problem that images that look good at one zoom level don't always look good at a different zoom level.
#3
02/11/2007 (2:19 pm)
@Dan -- the problem with that is, you'd still be consuming MUCH more memory then is necessary, as well as CPU Cycles -- hence the reason I went on a 2-page rant about the "screenshot map" concept -- which was something I came up with as a way to reduce overall resource consumption ... allowing the game to have more ...

Keep in mind, a "mini map" is mostly used in either an RTS or an RPG, in which case, you've most likely got a number of schedules/timers going on ... as well as a ton of AI calculations being performed ... on top of which, a ton of objects on screen being drawn over and over ...

To reduce all of this strain by creating the mini-map, I thought it best to make the map "static" ... with the 'static' map, you could still add dynamic things to it -- a Player icon, AI Unit icons for "near by" or "attacking" areas -- as well as even add "object icons" for things like dynamically placed houses ... etc, etc ... and doing so would still keep the overall resource consumption much lower then literally sharing the scenegraph's ...

But thanks for the input, I'll put the setRenderMasks, setRenderGroups and setRenderLayers into consideration for the next time I approach this ... appreciate the input ...
#4
02/11/2007 (2:25 pm)
Quote:the problem with that is, you'd still be consuming MUCH more memory then is necessary
?

How would you be consuming more memory with a single scenegraph vs. your plan of a scenegraph + giant sprite? I can see potential performance problems, since the mini-map would be trying to render a ton more individual things (such as every single tile in a potentially huge tilemap), but I don't see the extra memory usage.
#5
02/11/2007 (2:39 pm)
@Dan -- from my understanding ... the way TGB, as with most graphical engines ... redraws each object to the screen (or in this case, 'scene graph') one by one in a large loop ...

The reference to 'memory' in my statement was probably incorrect, and should have been 'cpu cycles' ...

Take for example this ...

When an image is loaded into memory, it's mapped to an in-memory bitmap ... blitting this bitmap is fairly quick as it's usually done by the Vid Card these days ... however, if you have to blit 1200-5000 objects (the potential overall object count in your level ... and since your displaying the entire level in the mini-map ... )

Blitting a single large image is much quicker then blitting hundreds or thousands of images ... the overall "memory" mention was misleading, as my concern was not with memory (RAM to be specific) but with system resources all-together (CPU Cycles, Memory, I/O, etc) ...

I do believe, unless someone can explain in detail how TGB 'blits' to the screen ... that a single large image would be faster then a few hundred smaller objects ...

Granted, I assume that TGB has some sort of internal caching or whatever, so that the blitting is only done when something changes ... but still ...

Also, the "fog of war" tilemap would have to be placed on the main screen ... as opposed to just in the mini-map ... in the event the game play was designed to allow the player to see "full screens" (Zelda Style, for example) but not the "entire map" ... this would involve creating an ENORMOUS Tile Layer, as opposed to a much smaller one (a 640x480 image is a single 'TGB Screen' ... where as my map may be 100x100 total 'TGB Screens' ... so now my tilemap is 64000x64000 (or whatever) and my tiles are 640x480 in size ... OUCH ...

That there would involve more memory ... as the engine is now storing the entire tilemap ... and I assume (assumption, I know) that the tilemap is stored in memory "post render" (after its size and images have been determined, for faster 'blitting')

@Dan, these are all assumptions i've made based on my experience with other drawing library, such as SDL for example and PyGame, etc ... I assume TGB has to do the same thing internally at some point ...

We could easily test and benchmark the two concepts ... and see which is actually better -- but as my post said, this was just an idea, and I'm open to suggestions, etc ... and I most likely won't even implement any of this as I don't have the time ... just a thought I had, and felt the need to share ... I appreciate your feedback.
#6
02/11/2007 (2:42 pm)
The 'fog of war' in the mainscreen ... btw, is because the scenegraphs are shared ... so the fog of war would have to exist in both scenewindows ... that or we'd have to create yet another scenegraph to store the fog of war ... which actually might not be all that bad, but complicates the overall process ... *shrug*