Rtl Foreground

From Uzebox Wiki
Jump to: navigation, search

Foreground Effects For Uzebox

With rtl_Foreground there is now an easy and standard way to create objects your sprites can hide behind. This introduces a level of depth to your game's visuals, and perhaps can even be used as a gameplay element. Let's take a look at what we're talking about.

Foreground1.png

See those deadly bunnies hiding in wait for their victims? Here's a link[1] to the teaser demo so you can try it out first hand. Looks pretty good eh? So, let's see how simple it is to add this functionality to your game!

Using rtl_Foreground

rtl_Foreground consumes only a few extra bytes of ram, minimal code space, and a moderate amount of cpu cycles depending on how many sprites are behind the foreground. To enable, you must add -DRTL_FOREGROUND to your kernel or cflags in your makefile.There is also built in functionality that provides some measure of protection from stack overflow, allowing the user's program to either WaitVsync(1) or simply stop the effect short to avoid running out of cycles. This is enabled with two switches added in your make file:

  • -DRTL_FOREGROUND_SAFETY - specifies that you would like RTL to take precautions against stack overflow.
  • -DRTL_VSYNC_WAIT - specify 0 to stop processing effects early, or 1 to WaitVsync(1) then continue with effect.

I highly recommend you first try WITHOUT either switch. If you are having problems try reducing ram usage, and free up some extra cycles with -DFIRST_RENDER_LINE. See rtl_Primer for more information on extra cycles. Unfortunately if you do not have enough time, it will likely have a poor visual result. Fortunately though, this works with not much extra time so generally this will be a non-issue. Enough talk, let's see some code. These are the functions you will be using:

  • void rtl_SetForeground(const uint8_t * map, const uint8_t * tiles, uint8_t start, uint8_t end)
    • This sets the parameters of your foreground.
      • const uint8_t *map-a pointer to a map representing the foreground(at least the size of the screen area sprites can move on).
      • const uint8_t *tiles-a pointer to the actual graphics data you will use for the foreground. This is in the same standard format as other 8bpp Uzebox graphics, and you can use the same tools you use normally to prepare the data.
      • uint8_t start-declares the first tile index that will be considered a foreground. So if for instance a sprite is on top of tile 20 and start is declared as 10, the 10th tile in the foreground tiles will be blitted over the sprite at that location(20-start make sense?).
      • uint8_t end-similarly, declares the last tile index that is considered foreground.
    • To disable using foreground maps, simply set map to NULL.
    • To disable the use of indexed foreground simple set start and end to 0.
    • To quickly disable foregrounds, simply set *map to NULL

Code Example

As you have seen above, there is only one function we must deal with. We must also use the standard rtl_PreVsync() and rtl_PostVsync() as usual for the RTL library. Let's take a look at a simple example source listing:

 #define RTL_FOREGROUND 1//include the code
 #define RTL_FOREGROUND_SAFETY 0//we're going for broke!
 #define RTL_VSYNC_WAIT 0//no thanks!

 #include "rtl/rtl.h"//include the library
 #include "ForegroundMap.inc"//your foreground map
 #include "ForegroundTiles.inc"//your foreground tiles, 0 is a dummy tile

 int main(){
 	//setup your sprites,tiles,patches, and music stuff like usual...

 	SetUserPreVsyncCallback(&rtl_PreVsync);//enable Ram Tile Library Pre and Post Vsync routines as usual
 	SetUserPostVsyncCallback(&rtl_PostVsync);

 	rtl_SetForeground(ForegroundMap,ForegroundTiles,0,0);//set up our foreground to our preference
	
 	YourGameLogicLoop();
 	//run your game as usual, your sprites will be automatically be drawn behind the foreground if they should be.
 	//no need to worry about it after it's set up!

 	return 1;
 }

All there is to it! You can now code your game like normal, changing foreground parameters to match the current situation on screen and the library takes care of the rest. All you have to do it ensure there will be enough free cycles! Enjoy!

Final Considerations

To achieve the proper visual effect, your graphics must be created to look like a foreground is in front of it when no sprites are there. This is because, when no sprite is there(and hence no ram tile blitted to the location) the normal tile will show. We want it to look the same regardless of if a sprite is there or not, best I give a picture example from my Jump n' Bump demo. Notice the level graphics have the parts that are the foreground included. Normally is is just drawn as a tile, when a sprite is over it the corresponding piece of the foreground tile data is drawn(which conveniently has exactly the same pixels for the parts we want overlapping the sprites).

Level graphics: Foreground3.png


Foreground graphics: Foreground2.png


And finally we would make our foreground map look something like this for these graphics to achieve a proper effect:

const uint8_t ForegroundMap[] PROGMEM = {
	 0,7,0,11,12,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,12,0,0,0,0,0,
	 0,0,0,0,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,15,0,0,0,0,
	 0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,4,0,11,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,4,0,0,14,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,13,0,0,0,0,0,0,0,0,
	 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,
	 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,5,0,0,0,
	 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,8,9,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,11,12,13,0,0,0,0,0,6,7,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,15,0,0,0,0,0,8,9,0,0,0,0,0,0,0,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};