Introduction

Day 1
GBA Hardware

Day 2
"Hello, World!"

Day 3
Input

Day 4
Backgrounds -
  Bitmapped Modes

Day 5
Sprites

Day 6
Backgrounds -
  Tile Modes

Day 7
Project 1 -
  Tetris

Quiz - Week 1

Day 8
Sprites #2 -
  Animation

Day 9
Maps

Day 10
Sprites #3 -
  Animation #2

Day 11
Backgrounds -
  Rotation

Day 12
Sprites #4 -
  Mosaic

Version History

Downloads

Forums

Books

Links

Graphics FAQ

GFX2GBA Readme

Translations

Games

Projects

Credits

Support

Poll

HAM Tutorial :: Day 9 :: Maps

 

Some of you may wonder after looking at this tutorial what the purpose is or how it is different from Day 6. Honestly, there isn't a lot that's different except that today the map size will be 512x512 and you can see how to make a map that can be scrolled around.

We are going to do things a little differently for today's graphics. The reason is that I don't want an optimized palette. If you've been paying attention, you should have noticed that the gfx2gba optimizes the palette by removing colors not used in your images. This is usually fine. Today, however, I want to reference a specific color when I use ham_SetTextCol() and it's much easier to figure out the index number of the color in Photoshop ahead of time.

So, to convert the graphics, type:
gfx2gba -fsrc -m -t8 -x simple_world.bmp

If you look at the gfx2gba readme, you'll see that -x prevents optimizing your palette. You'll also notice that I left out -p<palette_name> because gfx2gba ignores it when you use -x.

Your gfx directory should now have the following files:
simple_world.pal.c
simple_world.map.c
simple_world.raw.c

Now let's get to the code:

 
// The Main HAM Library
#include <mygba.h>

// Graphics Includes
// gfx2gba -fsrc -m -t8 -x simple_world.bmp
#include "gfx/simple_world.pal.c"
#include "gfx/simple_world.raw.c"
#include "gfx/simple_world.map.c"

// Global Variables
u8 newframe = 1; // Signifies a new frame
u16 map_x = 0;   // X position of the map
u16 map_y = 0;   // Y position of the map

// Function Prototypes
void vbl_func(); // VBL function

// Function: main()
int main()
{
    // Variables
    map_fragment_info_ptr bg_simple_world;

    // Initialize HAMlib
    ham_Init();

    // Initialize the text display system
    ham_InitText(0);

    // Setup the background mode
    ham_SetBgMode(0);

    // Initialize the palettes
    ham_LoadBGPal((void*)simple_world_Palette,256);

    // Set the Text Color
    ham_SetTextCol(195, 40);

    // Setup the tileset for our image
    ham_bg[1].ti = ham_InitTileSet(
        (void*)simple_world_Tiles,
        SIZEOF_16BIT(simple_world_Tiles),1,1);

    // Setup the map for our image
    ham_bg[1].mi = ham_InitMapEmptySet(3,0);
    bg_simple_world = ham_InitMapFragment(
        (void*)simple_world_Map,64,64,0,0,64,64,0);

    // Copy (the whole) map to BG0 at x=0, y=0
    ham_InsertMapFragment(bg_simple_world,1,0,0);
	
    // Display the background
    ham_InitBg(1,1,2,0);

    // Start the VBL interrupt handler
    ham_StartIntHandler(INT_TYPE_VBL,(void*)&vbl_func);

    while(1)
    {
        if(newframe)
        {
            // Write some stuff to the screen
            ham_DrawText(1,1,"512x512 Map example");
            ham_DrawText(1,2,"Use pad to scroll around");

            ham_DrawText(1,17,"scroll-x: %5d",map_x);
            ham_DrawText(1,18,"scroll-y: %5d",map_y);

            // Let the user move the map around
            if(F_CTRLINPUT_DOWN_PRESSED)
            {
                if(map_y < (512-160))
                    ham_SetBgXY(1,map_x,++map_y);
            }
            if(F_CTRLINPUT_UP_PRESSED)
            {
                if(map_y > 0)
                    ham_SetBgXY(1,map_x,--map_y);
            }
            if(F_CTRLINPUT_RIGHT_PRESSED)
            {
                if(map_x < (512-240))
                    ham_SetBgXY(1,++map_x,map_y);
            }
            if(F_CTRLINPUT_LEFT_PRESSED)
            {
                if(map_x > 0)
                    ham_SetBgXY(1,--map_x,map_y);
            }
            newframe = 0; // No longer a new frame
        } // End of if(newframe)
    } // End of while(1)

    return 0;
} // End of main()

//**********************
// Function: vbl_func()
// Purpose: VBL function
//**********************
void vbl_func()
{
    newframe = 1; // Starting a new frame

    return;
} // End of vbl_func()
 
            
 

Code Explanation

// Global Variables
newframe is used in main() in the while loop to determine if it's a new frame or not. 'When does a new frame occur?' you may be thinking. Well, every vertical blank (VBL), of course!
map_x
and map_y should hopefully be clear to you. They keep track of the top-left corner of the part of the map that will be displayed on the screen.

Now on to main()

// Set the text color
ham_SetTextCol(195, 40);
This should be a pretty simple function to figure out. Basically you pass it the index number from the background palette of the color you want for the foreground and background font color. 'How do I figure out the index number?' you ask. Well, take a look at the Graphics FAQ. If you look at the palette used with simple_world.bmp, you'll notice that 195 is red and 40 is a purplish color.

// Setup the map for our image
ham_bg[1].mi = ham_InitMapEmptySet(3,0);
mymap = ham_InitMapFragment(&simple_world_Map,64,64,0,0,64,64,0);
You hopefully noticed that I am passing 64,64 instead of 30,20. Why am I doing this? Well, I am setting up a map which is 512x512 pixels instead of a 240x160 background.

Now let's examine while(1)

if(newframe)...
This will be set to 1, or true, every VBL.

if(F_CTRLINPUT_DOWN_PRESSED)... if(map_y<(512-160))
This will allow the map to move down if it's not already at the bottom.
Not sure why we use 512 - 160? Well, there the screen height is 160 pixels. The image height is 512 pixels. The top line of the image will be at 512 - 160 pixels when the map is all the way at the bottom.
Still not sure? Click here.

ham_SetBgXY(...)
This is a function that can be used to scroll a map. You pass it the BG number, the new X offset, and the new Y offset. You'll notice that I use prefix incrementation/decrementation with map_x and map_y. For example, when the user presses DOWN, map_y gets incremented by one. NOTE: This function does NOT work with rotation backgrounds.

There is one more thing you need to know about here - tiles. There is a limit to the number of tiles you can load at once - 651 (I believe). Because my image is 512x512 pixels and because I am loading the whole image at once, this becomes something I have to consider. When you run gfx2gba you'll notice that before optimization there are 4096 tiles and after optimization there are only 431. If my image were only a bit more complicated, then this would be a problem and I would have to load the image differently. There are other ways to do this kind of scrolling, but this is one of the easiest ways to understand for now.

That's pretty much it for Day 9. I hope this isn't too complicated.

 

Download Code

NOTE: You may need to Right-click and choose Save As.

HAM Version 2.80 And Higher
Download All Files In One Zip: Day9_Maps.zip

View Demo Now

Discuss Day 9

 

<<

HOME

>>