Here's the formulas I promised to help you find yourself in your world. Suppose you have a world that is 4x6 in size, with world map size 2x2, that would give you...
4x6 = 24 world entries
2x2 = 4 map entries
24/4 = 6 overall maps
thus,
x,y = (y-1) * cols + x = overall position
world entries - overall position/map entries = eliminated maps
overall maps - eliminated maps = found map #
found map # * map entries - overall position = alpha
map entries - alpha = real position - 1
This is how you can find where ever you are based on your world and map sizes.
Good luck!
Monday, February 25, 2008
Sunday, February 24, 2008
Where The Hell Have You Been!?
"Okay...don't have me sitting here for weeks on you...waiting for you to blog...where the hell have you been!?"
Ahhh...I've been caught up in real world work, I apologize.
Ok...weeks ago I said I would present the formula for finding exactly where you are in your world based on the size of your world, down to the tile and pixels. I actually, figured out the formula 2 days after I said I would, but just got caught up in so much work (I'm the lead/sole programmer on a virtual machine/security application).
I'm actually going to take a nap right at this moment, but I will post the formula before the day is over. I promise...just way too tired to do it and explain right now, but if anyone is out there ("if they were, you've lost them now dummy...people not waiting on you.") I wanted to update the blog.
So, before the day is over...stay tuned.
I'll be baaahhhccck!
Ahhh...I've been caught up in real world work, I apologize.
Ok...weeks ago I said I would present the formula for finding exactly where you are in your world based on the size of your world, down to the tile and pixels. I actually, figured out the formula 2 days after I said I would, but just got caught up in so much work (I'm the lead/sole programmer on a virtual machine/security application).
I'm actually going to take a nap right at this moment, but I will post the formula before the day is over. I promise...just way too tired to do it and explain right now, but if anyone is out there ("if they were, you've lost them now dummy...people not waiting on you.") I wanted to update the blog.
So, before the day is over...stay tuned.
I'll be baaahhhccck!
Wednesday, January 23, 2008
What's Next?
Some have asked for the source, so I will clean it up and some how get a link on this blog for you to grab it, or just email it to those that have asked. I'll will try to get it up before Friday.
Before, I do the object placing in the world, scrolling, and removing/restoring object when visible, I will work on determining where I am in my defined tile map world. I will move a sprite around in my world, and find out the tile entry it is on. By knowing this, I can then define tiles in my world that are, passable, setting boundaries in my tile maps, and thus the beginnings of a simple tile level editor.
I will once again set a time frame for myself for figuring this out. For the scrolling, I gave myself 3 weeks and got it done in 2 weeks (actual time worked on it was approx. 40 hours).
Till next time...
Before, I do the object placing in the world, scrolling, and removing/restoring object when visible, I will work on determining where I am in my defined tile map world. I will move a sprite around in my world, and find out the tile entry it is on. By knowing this, I can then define tiles in my world that are, passable, setting boundaries in my tile maps, and thus the beginnings of a simple tile level editor.
I will once again set a time frame for myself for figuring this out. For the scrolling, I gave myself 3 weeks and got it done in 2 weeks (actual time worked on it was approx. 40 hours).
Till next time...
Tuesday, January 22, 2008
Find It Here
Just adding some keywords for search engines to help those looking for a Nintendo DS Tile Scroll Algorithm, with smooth scrolling.
I think that covers it. :)
I think that covers it. :)
Monday, January 21, 2008
"Keep Scrollin', scrollin', scrollin'..."
"Now I know ya'll be lovin' this right here...R.O.D. is right here. People in the house with there laptops in the air..."
Okay...whew...I was gettin' jiggy...oh, they don't say that anymore...showing my age. :)
Anyway, the tile, scroll engine is done. Well, not the engine, but the code that does all the tile, world scrolling is "oppperrratttiooonaaal." I'll clean it up and make it into a generic engine. Anyway, I know some of you are itching to see how to scroll. As, I mentioned previously I'll will post here some hand drawings to explain my scheme, and also will post the code. So, here it is...


Sheesh...the images loaded in look like crap but, if you can see the one above A shows the image of the background map divided into 4 regions I've been explaining in my previous posts. B, shows the 32x32 maps that will be loaded into those regions. I guess, I'll just get to the code, and have to figure out another way to get the diagrams up and in.
What I did to test my scheme was to make some 8x8 tiles filled with different colors. I then created test maps from those tiles, thus I have 32x32 tile maps of solid colors. This way when I scroll I can see if my test maps are loading and scrolling properly. So, my world that I'm scrolling over looks like a colorful patch quilt, but it is a good way to test.
Here's that code...
// black tile
const int nColor_Black = 0;
u8 blackTile[64]=
{
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
// red tile
const int nColor_Red = 1;
u8 redTile[64]=
{
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1
};
// green tile
const int nColor_Green = 2;
u8 greenTile[64]=
{
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2
};
// blue tile
const int nColor_Blue = 3;
u8 blueTile[64]=
{
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3
};
// yellow tile
const int nColor_Yellow = 4;
u8 yellowTile[64]=
{
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4
};
// white tile
const int nColor_White = 5;
u8 whiteTile[64]=
{
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5
};
The above are the tiles I created for testing, but in a game one of these tiles would represent some, small graphic element.
Here are the maps...
// file map1 with black tiles
u16 nWorldMap1[] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0, // 3
0,0,0,0,0,0,0,0,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,0,0,0, // 5
0,0,0,0,0,0,0,0,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
0,0,0,0,0,0,0,0,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, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 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, // 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,0,0,0,0,0, // 11
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 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,0,0,0,0,0,0, // 13
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 14
0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 16
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 17
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 18
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 19
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 21
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 22
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 23
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 24
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 25
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 26
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 27
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 28
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 29
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 30
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 31
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 32
};
// black maps
u16 *nWorldMap7, *nWorldMap13, *nWorldMap19;
nWorldMap7 = nWorldMap13 = nWorldMap19 = nWorldMap1;
// file with red tiles
u16 nWorldMap2[] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 2
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 3
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 4
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 5
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 6
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 7
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 8
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 9
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 10
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 11
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 12
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 13
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 14
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 15
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 16
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 17
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 18
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 19
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 20
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 21
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 22
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 23
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 24
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 25
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 26
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 27
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 28
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 29
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 30
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 31
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 32
};
u16 *nWorldMap8, *nWorldMap14, *nWorldMap20;
nWorldMap8 = nWorldMap14 = nWorldMap20 = nWorldMap2;
// fill map with green tiles
u16 nWorldMap3[] =
{
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 1
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 2
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 3
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 4
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 5
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 6
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 7
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 8
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 9
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 10
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 11
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 12
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 13
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 14
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 15
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 16
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 17
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 18
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 19
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 20
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 21
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 22
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 23
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 24
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 25
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 26
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 27
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 28
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 29
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 30
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 31
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 32
};
u16 *nWorldMap9, *nWorldMap15;
nWorldMap9= nWorldMap15 = nWorldMap3;
u16 nWorldMap4[] =
{
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 1
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 2
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 3
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 4
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 5
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 6
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 7
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 8
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 9
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 10
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 11
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 12
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 13
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 14
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 15
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 16
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 17
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 18
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 19
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 20
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 21
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 22
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 23
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 24
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 25
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 26
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 27
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 28
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 29
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 30
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 31
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 32
};
u16 *nWorldMap10, *nWorldMap16;
nWorldMap10 = nWorldMap16 = nWorldMap4;
// fill map with yellow tiles
u16 nWorldMap5[] =
{
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 1
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 2
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 3
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 4
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 5
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 6
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 7
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 8
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 9
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 10
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 11
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 12
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 13
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 14
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 15
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 16
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 17
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 18
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 19
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 20
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 21
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 22
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 23
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 24
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 25
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 26
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 27
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 28
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 29
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 30
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 31
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 32
};
u16 *nWorldMap11, *nWorldMap17;
nWorldMap11 = nWorldMap17 = nWorldMap5;
// fill map with white tiles
u16 nWorldMap6[] =
{
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 1
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 2
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 3
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 4
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 5
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 6
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 7
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 8
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 9
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 10
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 11
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 12
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 13
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 14
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 15
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 16
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 17
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 18
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 19
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 20
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 21
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 22
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 23
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 24
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 25
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 26
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 27
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 28
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 29
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 30
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 31
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 32
};
u16 *nWorldMap12, *nWorldMap18;
nWorldMap12 = nWorldMap18 = nWorldMap6;
You see the maps are 32x32 entries with the tile images in them, remember I'm doing solid patterns so that testing the tile scrolling is easily visible. Again, in a real game the different entries in the map would make up different tiles that could also be rotated or flipped, to make up a picture, landscape, etc... Note, that after I made one map of a solid color, I created pointers to other maps and assigned a map to them. This way, I saved time and memory not making duplicate maps filled with the same colors.
Next, is the setup code to set the background mode, tiles, palette,etc...
int main(void)
{
// enable interrupts
irqInit();
irqEnable(IRQ_VBLANK);
// set video mode and map vram to the background
videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE |
DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); // display sprite active, in tile, and bitmap mode
//enable vram and map it to the right places
vramSetMainBanks(VRAM_A_MAIN_SPRITE, //A and B maped consecutivly as sprite memory
VRAM_B_MAIN_SPRITE, //this gives us 256KB which is the max
VRAM_C_MAIN_BG_0x06000000, //map C to background memory
VRAM_D_LCD); //not using D
// set the map regions
u16* mapRegion0 = (u16*)BG_MAP_RAM(0);
u16* mapRegion1 = (u16*)BG_MAP_RAM(1);
u16* mapRegion2 = (u16*)BG_MAP_RAM(2);
u16* mapRegion3 = (u16*)BG_MAP_RAM(3);
u8* tileMemory = (u8*) BG_TILE_RAM(1);
// tell the DS where we are putting everything and set the 256 color mode
// and that we are using a 32x32 tile map
BG0_CR = BG_64x64 | BG_COLOR_256 | BG_MAP_BASE(0) | BG_TILE_BASE(1);
// load our palette...
//pallette entry 0 is black by default
BG_PALETTE[1] = RGB15(31,0,0); // red
BG_PALETTE[2] = RGB15(0,31,0); // green
BG_PALETTE[3] = RGB15(0, 0, 31); // blue
BG_PALETTE[4] = RGB15(31, 31, 0); // yellow
BG_PALETTE[5] = RGB15(31, 31, 31); // white
// copy the tiles into tile memory one after the other
swiCopy(blackTile, tileMemory, 32);
swiCopy(redTile, tileMemory + sizeof(blackTile), 32);
swiCopy(greenTile, tileMemory + sizeof(blackTile)*2, 32);
swiCopy(blueTile, tileMemory + sizeof(blackTile)*3, 32);
swiCopy(yellowTile, tileMemory + sizeof(blackTile)*4, 32);
swiCopy(whiteTile, tileMemory + sizeof(blackTile)*5, 32);
Remember, I said that my test world is 5x4, 32x32 maps and the background map is divided into 2x2, 32x32 regions, 0,1,2,&3. The table below is how the region is laid out for each row and column. Thus, if the scroll engine determines that it is on map 15 = WorldMaps[14], plugging that into nMapToRegion tells us which region map 15 belongs, i.e., region = nMapToRegion[15-1]; I subtract one since map1 is at entry zero. To avoid all that offset, subtraction, just number the maps starting at zero. I'll make that change in my final engine.
Here's the code setting up the arrays, and variables used to do the region bounds checks...
int WorldMaps[] = {
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
};
int nMapToRegion[] = {
0, 1, 0, 1, 0,
2, 3, 2, 3, 2,
0, 1, 0, 1, 0,
2, 3, 2, 3, 2,
};
int nMap = 0;
int nRegion = 0;
int nRowT = 0;
int nRowB = 0;
int nColL = 0;
int nColR = 0;
int nWorldPos_rx = 255; // 32 * 8 - 1
int nWorldPos_lx = 0;
int nWorldPos_ty = 0;
int nWorldPos_by = 191; // 24 * 8 - 1
int nScroll_x = 0;
int nScroll_y = 0;
int held; // used for keypad inputs
I created lookup tables to easily grab the maps and regions...
std::vector vRegionLookup;
std::vector vMapLookup;
// set the regions in lookup table
vRegionLookup.push_back(mapRegion0);
vRegionLookup.push_back(mapRegion1);
vRegionLookup.push_back(mapRegion2);
vRegionLookup.push_back(mapRegion3);
// push the maps to lookup table
vMapLookup.push_back(nWorldMap1);
vMapLookup.push_back(nWorldMap2);
vMapLookup.push_back(nWorldMap3);
vMapLookup.push_back(nWorldMap4);
vMapLookup.push_back(nWorldMap5);
vMapLookup.push_back(nWorldMap6);
vMapLookup.push_back(nWorldMap7);
vMapLookup.push_back(nWorldMap8);
vMapLookup.push_back(nWorldMap9);
vMapLookup.push_back(nWorldMap10);
vMapLookup.push_back(nWorldMap11);
vMapLookup.push_back(nWorldMap12);
vMapLookup.push_back(nWorldMap13);
vMapLookup.push_back(nWorldMap14);
vMapLookup.push_back(nWorldMap15);
vMapLookup.push_back(nWorldMap16);
vMapLookup.push_back(nWorldMap17);
vMapLookup.push_back(nWorldMap18);
vMapLookup.push_back(nWorldMap19);
vMapLookup.push_back(nWorldMap20);
Note, the lookup table for the World Maps is done this way only for testing and convience, in a real game you won't be able to load your whole game universe if it has a big play area. You will have to devise a scheme to read in the maps based on game levels, world size, etc...but, this gives you an idea.
Also, here are some global constants I used as well...
const int nMapEntries_x = 5;
const int nMapEntries_y = 4;
const int nMapSize = 1024;
const int nRegionSize = 256; // 32 * 8
const int nScreen_Xdim = 31*8; // ds screen width
const int nScreen_Ydim = 23*8; // ds screen height
const int nWorldSize_x = 1279; // nMapEntries_x * 32 * 8 - 1;
const int nWorldSize_y = 1023; // nMapEntries_y * 32 * 8 - 1
And, what you have been waiting to see, the scroll code...
bool bHorzBoundsHit = false;
bool bVertBoundsHit = false;
while(1)
{
// get the keys
scanKeys();
held= keysHeld();
// adjust scroll
if(held & KEY_LEFT)
{
nScroll_x--;
nWorldPos_rx--;
nWorldPos_lx--;
}
if(held & KEY_RIGHT)
{
nScroll_x++;
nWorldPos_rx++;
nWorldPos_lx++;
}
if(held & KEY_UP)
{
nScroll_y--;
nWorldPos_ty--;
nWorldPos_by--;
}
if(held & KEY_DOWN)
{
nScroll_y++;
nWorldPos_by++;
nWorldPos_ty++;
}
// reset bounds hit flags
bHorzBoundsHit = false;
bVertBoundsHit = false;
// adjust coords...not an infinite world
if(nWorldPos_lx <= 0)
{
bHorzBoundsHit = true;
nWorldPos_lx = 0;
nWorldPos_rx = nScreen_Xdim;
nScroll_x = 0;
}
if(nWorldPos_rx >= nWorldSize_x)
{
bHorzBoundsHit = true;
nWorldPos_rx = nWorldSize_x;
nWorldPos_lx = nWorldPos_rx - nScreen_Xdim;
nScroll_x = nWorldPos_rx - nScreen_Xdim - 8;
}
if(nWorldPos_ty <= 0)
{
bVertBoundsHit = true;
nWorldPos_ty = 0;
nWorldPos_by = nScreen_Ydim;
nScroll_y = 0;
}
if(nWorldPos_by >= nWorldSize_y)
{
bVertBoundsHit = true;
nWorldPos_ty = nWorldSize_y - nScreen_Ydim;
nWorldPos_by = nWorldSize_y;
nScroll_y = nWorldSize_y - nScreen_Ydim - 8;
}
//
// determine boundary hits
//
// right region border hit
if((nWorldPos_rx % nRegionSize == 0) && !bHorzBoundsHit)
{
// determine if we have split rows
nRowT = nWorldPos_ty / nRegionSize;
nRowB = nWorldPos_by / nRegionSize;
if(nRowT != nRowB)
{
//
// split rows
//
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
else
{
// rowt == rowb (same row)
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
}
// left region border hit
if((nWorldPos_lx % nRegionSize == 0) && !bHorzBoundsHit)
{
// determine if we have split rows
nRowT = nWorldPos_ty / nRegionSize;
nRowB = nWorldPos_by / nRegionSize;
if(nRowT != nRowB)
{
//
// split rows
//
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// get the previous region (one before us)
nRegion = nMapToRegion[nMap-1];
// move the previous map into the proper region
swiCopy(vMapLookup[nMap-1], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// get the previous region
nRegion = nMapToRegion[nMap-1];
// move the previous map into the proper region
swiCopy(vMapLookup[nMap-1], vRegionLookup[nRegion], nMapSize);
}
else
{
// rowt == rowb (same row)
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// get the previous region (one before us)
nRegion = nMapToRegion[nMap-1];
// move the previous map into the proper region
swiCopy(vMapLookup[nMap-1], vRegionLookup[nRegion], nMapSize);
}
}
// top region border hit
if((nWorldPos_ty % nRegionSize == 0) && !bVertBoundsHit)
{
// determine if we have split columns
nColL = nWorldPos_lx / nRegionSize;
nColR = nWorldPos_rx / nRegionSize;
// find the row we're on
nRowT = nWorldPos_ty / nRegionSize;
if(nColL != nColR)
{
//
// split columns
//
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_lx / nRegionSize) - nMapEntries_x;
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize) - nMapEntries_x;
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
else
{
// colL == colR (same columns)
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize) - nMapEntries_x;
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
}
// bottom region border hit
if((nWorldPos_by % nRegionSize == 0) && !bVertBoundsHit)
{
// determine if we have split columns
nColL = nWorldPos_lx / nRegionSize;
nColR = nWorldPos_rx / nRegionSize;
// find the row we're on
nRowB = nWorldPos_by / nRegionSize;
if(nColL != nColR)
{
//
// split columns
//
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
else
{
// colL == colR (same column)
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
}
swiWaitForVBlank();
// set the scroll registers (scroll background)
BG0_X0 = nScroll_x;
BG0_Y0 = nScroll_y;
}
That's it! You can now scroll anywhere in your world, up, down, left, right, and diagonal. Changing the test hard coded limits I have, you can make your world any size you like and scroll.
I treated the DS screen to have the coordinates, LX,TY (left x, top y) for the upper, left hand corner, and RX,BY (right x, bottom y) for the lower, right hand corner. When scrolling you might be hovering over two tiles and scrolling vertical or horizantally, that is why I test for split rows, and columns.
I will clean some things up in my test code and make a generic C++ class, tile, scroll engine. I'll next, test dropping objects in my world at arbitrary locations and see if I can scroll around, leave and comeback and they are still where I left them. Of course, they won't actually stay by themselves, I'll have to write the code to make them behave.
If anyone would like a copy of the source, to help them get started, shoot me an email or post here and I'll get a link up or email you a copy. I don't know who's reading or interested, so that would be a good barometer.
In the mean time..."keep scrollin', scrollin', scrollin'!"
Okay...whew...I was gettin' jiggy...oh, they don't say that anymore...showing my age. :)
Anyway, the tile, scroll engine is done. Well, not the engine, but the code that does all the tile, world scrolling is "oppperrratttiooonaaal." I'll clean it up and make it into a generic engine. Anyway, I know some of you are itching to see how to scroll. As, I mentioned previously I'll will post here some hand drawings to explain my scheme, and also will post the code. So, here it is...


Sheesh...the images loaded in look like crap but, if you can see the one above A shows the image of the background map divided into 4 regions I've been explaining in my previous posts. B, shows the 32x32 maps that will be loaded into those regions. I guess, I'll just get to the code, and have to figure out another way to get the diagrams up and in.
What I did to test my scheme was to make some 8x8 tiles filled with different colors. I then created test maps from those tiles, thus I have 32x32 tile maps of solid colors. This way when I scroll I can see if my test maps are loading and scrolling properly. So, my world that I'm scrolling over looks like a colorful patch quilt, but it is a good way to test.
Here's that code...
// black tile
const int nColor_Black = 0;
u8 blackTile[64]=
{
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
// red tile
const int nColor_Red = 1;
u8 redTile[64]=
{
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1
};
// green tile
const int nColor_Green = 2;
u8 greenTile[64]=
{
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2
};
// blue tile
const int nColor_Blue = 3;
u8 blueTile[64]=
{
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3
};
// yellow tile
const int nColor_Yellow = 4;
u8 yellowTile[64]=
{
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4
};
// white tile
const int nColor_White = 5;
u8 whiteTile[64]=
{
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5
};
The above are the tiles I created for testing, but in a game one of these tiles would represent some, small graphic element.
Here are the maps...
// file map1 with black tiles
u16 nWorldMap1[] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0, // 3
0,0,0,0,0,0,0,0,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,0,0,0, // 5
0,0,0,0,0,0,0,0,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
0,0,0,0,0,0,0,0,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, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 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, // 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,0,0,0,0,0, // 11
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 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,0,0,0,0,0,0, // 13
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 14
0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 16
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 17
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 18
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 19
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 21
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 22
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 23
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 24
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 25
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 26
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 27
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 28
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 29
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 30
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 31
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 32
};
// black maps
u16 *nWorldMap7, *nWorldMap13, *nWorldMap19;
nWorldMap7 = nWorldMap13 = nWorldMap19 = nWorldMap1;
// file with red tiles
u16 nWorldMap2[] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 2
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 3
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 4
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 5
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 6
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 7
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 8
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 9
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 10
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 11
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 12
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 13
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 14
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 15
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 16
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 17
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 18
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 19
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 20
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 21
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 22
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 23
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 24
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 25
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 26
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 27
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 28
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 29
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 30
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 31
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 32
};
u16 *nWorldMap8, *nWorldMap14, *nWorldMap20;
nWorldMap8 = nWorldMap14 = nWorldMap20 = nWorldMap2;
// fill map with green tiles
u16 nWorldMap3[] =
{
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 1
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 2
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 3
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 4
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 5
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 6
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 7
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 8
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 9
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 10
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 11
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 12
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 13
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 14
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 15
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 16
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 17
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 18
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 19
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 20
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 21
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 22
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 23
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 24
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 25
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 26
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 27
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 28
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 29
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 30
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 31
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 32
};
u16 *nWorldMap9, *nWorldMap15;
nWorldMap9= nWorldMap15 = nWorldMap3;
u16 nWorldMap4[] =
{
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 1
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 2
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 3
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 4
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 5
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 6
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 7
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 8
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 9
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 10
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 11
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 12
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 13
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 14
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 15
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 16
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 17
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 18
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 19
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 20
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 21
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 22
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 23
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 24
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 25
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 26
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 27
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 28
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 29
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 30
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 31
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 32
};
u16 *nWorldMap10, *nWorldMap16;
nWorldMap10 = nWorldMap16 = nWorldMap4;
// fill map with yellow tiles
u16 nWorldMap5[] =
{
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 1
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 2
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 3
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 4
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 5
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 6
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 7
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 8
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 9
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 10
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 11
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 12
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 13
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 14
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 15
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 16
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 17
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 18
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 19
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 20
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 21
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 22
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 23
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 24
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 25
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 26
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 27
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 28
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 29
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 30
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 31
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 32
};
u16 *nWorldMap11, *nWorldMap17;
nWorldMap11 = nWorldMap17 = nWorldMap5;
// fill map with white tiles
u16 nWorldMap6[] =
{
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 1
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 2
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 3
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 4
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 5
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 6
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 7
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 8
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 9
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 10
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 11
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 12
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 13
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 14
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 15
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 16
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 17
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 18
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 19
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 20
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 21
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 22
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 23
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 24
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 25
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 26
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 27
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 28
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 29
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 30
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 31
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // 32
};
u16 *nWorldMap12, *nWorldMap18;
nWorldMap12 = nWorldMap18 = nWorldMap6;
You see the maps are 32x32 entries with the tile images in them, remember I'm doing solid patterns so that testing the tile scrolling is easily visible. Again, in a real game the different entries in the map would make up different tiles that could also be rotated or flipped, to make up a picture, landscape, etc... Note, that after I made one map of a solid color, I created pointers to other maps and assigned a map to them. This way, I saved time and memory not making duplicate maps filled with the same colors.
Next, is the setup code to set the background mode, tiles, palette,etc...
int main(void)
{
// enable interrupts
irqInit();
irqEnable(IRQ_VBLANK);
// set video mode and map vram to the background
videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE |
DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); // display sprite active, in tile, and bitmap mode
//enable vram and map it to the right places
vramSetMainBanks(VRAM_A_MAIN_SPRITE, //A and B maped consecutivly as sprite memory
VRAM_B_MAIN_SPRITE, //this gives us 256KB which is the max
VRAM_C_MAIN_BG_0x06000000, //map C to background memory
VRAM_D_LCD); //not using D
// set the map regions
u16* mapRegion0 = (u16*)BG_MAP_RAM(0);
u16* mapRegion1 = (u16*)BG_MAP_RAM(1);
u16* mapRegion2 = (u16*)BG_MAP_RAM(2);
u16* mapRegion3 = (u16*)BG_MAP_RAM(3);
u8* tileMemory = (u8*) BG_TILE_RAM(1);
// tell the DS where we are putting everything and set the 256 color mode
// and that we are using a 32x32 tile map
BG0_CR = BG_64x64 | BG_COLOR_256 | BG_MAP_BASE(0) | BG_TILE_BASE(1);
// load our palette...
//pallette entry 0 is black by default
BG_PALETTE[1] = RGB15(31,0,0); // red
BG_PALETTE[2] = RGB15(0,31,0); // green
BG_PALETTE[3] = RGB15(0, 0, 31); // blue
BG_PALETTE[4] = RGB15(31, 31, 0); // yellow
BG_PALETTE[5] = RGB15(31, 31, 31); // white
// copy the tiles into tile memory one after the other
swiCopy(blackTile, tileMemory, 32);
swiCopy(redTile, tileMemory + sizeof(blackTile), 32);
swiCopy(greenTile, tileMemory + sizeof(blackTile)*2, 32);
swiCopy(blueTile, tileMemory + sizeof(blackTile)*3, 32);
swiCopy(yellowTile, tileMemory + sizeof(blackTile)*4, 32);
swiCopy(whiteTile, tileMemory + sizeof(blackTile)*5, 32);
Remember, I said that my test world is 5x4, 32x32 maps and the background map is divided into 2x2, 32x32 regions, 0,1,2,&3. The table below is how the region is laid out for each row and column. Thus, if the scroll engine determines that it is on map 15 = WorldMaps[14], plugging that into nMapToRegion tells us which region map 15 belongs, i.e., region = nMapToRegion[15-1]; I subtract one since map1 is at entry zero. To avoid all that offset, subtraction, just number the maps starting at zero. I'll make that change in my final engine.
Here's the code setting up the arrays, and variables used to do the region bounds checks...
int WorldMaps[] = {
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
};
int nMapToRegion[] = {
0, 1, 0, 1, 0,
2, 3, 2, 3, 2,
0, 1, 0, 1, 0,
2, 3, 2, 3, 2,
};
int nMap = 0;
int nRegion = 0;
int nRowT = 0;
int nRowB = 0;
int nColL = 0;
int nColR = 0;
int nWorldPos_rx = 255; // 32 * 8 - 1
int nWorldPos_lx = 0;
int nWorldPos_ty = 0;
int nWorldPos_by = 191; // 24 * 8 - 1
int nScroll_x = 0;
int nScroll_y = 0;
int held; // used for keypad inputs
I created lookup tables to easily grab the maps and regions...
std::vector
std::vector
// set the regions in lookup table
vRegionLookup.push_back(mapRegion0);
vRegionLookup.push_back(mapRegion1);
vRegionLookup.push_back(mapRegion2);
vRegionLookup.push_back(mapRegion3);
// push the maps to lookup table
vMapLookup.push_back(nWorldMap1);
vMapLookup.push_back(nWorldMap2);
vMapLookup.push_back(nWorldMap3);
vMapLookup.push_back(nWorldMap4);
vMapLookup.push_back(nWorldMap5);
vMapLookup.push_back(nWorldMap6);
vMapLookup.push_back(nWorldMap7);
vMapLookup.push_back(nWorldMap8);
vMapLookup.push_back(nWorldMap9);
vMapLookup.push_back(nWorldMap10);
vMapLookup.push_back(nWorldMap11);
vMapLookup.push_back(nWorldMap12);
vMapLookup.push_back(nWorldMap13);
vMapLookup.push_back(nWorldMap14);
vMapLookup.push_back(nWorldMap15);
vMapLookup.push_back(nWorldMap16);
vMapLookup.push_back(nWorldMap17);
vMapLookup.push_back(nWorldMap18);
vMapLookup.push_back(nWorldMap19);
vMapLookup.push_back(nWorldMap20);
Note, the lookup table for the World Maps is done this way only for testing and convience, in a real game you won't be able to load your whole game universe if it has a big play area. You will have to devise a scheme to read in the maps based on game levels, world size, etc...but, this gives you an idea.
Also, here are some global constants I used as well...
const int nMapEntries_x = 5;
const int nMapEntries_y = 4;
const int nMapSize = 1024;
const int nRegionSize = 256; // 32 * 8
const int nScreen_Xdim = 31*8; // ds screen width
const int nScreen_Ydim = 23*8; // ds screen height
const int nWorldSize_x = 1279; // nMapEntries_x * 32 * 8 - 1;
const int nWorldSize_y = 1023; // nMapEntries_y * 32 * 8 - 1
And, what you have been waiting to see, the scroll code...
bool bHorzBoundsHit = false;
bool bVertBoundsHit = false;
while(1)
{
// get the keys
scanKeys();
held= keysHeld();
// adjust scroll
if(held & KEY_LEFT)
{
nScroll_x--;
nWorldPos_rx--;
nWorldPos_lx--;
}
if(held & KEY_RIGHT)
{
nScroll_x++;
nWorldPos_rx++;
nWorldPos_lx++;
}
if(held & KEY_UP)
{
nScroll_y--;
nWorldPos_ty--;
nWorldPos_by--;
}
if(held & KEY_DOWN)
{
nScroll_y++;
nWorldPos_by++;
nWorldPos_ty++;
}
// reset bounds hit flags
bHorzBoundsHit = false;
bVertBoundsHit = false;
// adjust coords...not an infinite world
if(nWorldPos_lx <= 0)
{
bHorzBoundsHit = true;
nWorldPos_lx = 0;
nWorldPos_rx = nScreen_Xdim;
nScroll_x = 0;
}
if(nWorldPos_rx >= nWorldSize_x)
{
bHorzBoundsHit = true;
nWorldPos_rx = nWorldSize_x;
nWorldPos_lx = nWorldPos_rx - nScreen_Xdim;
nScroll_x = nWorldPos_rx - nScreen_Xdim - 8;
}
if(nWorldPos_ty <= 0)
{
bVertBoundsHit = true;
nWorldPos_ty = 0;
nWorldPos_by = nScreen_Ydim;
nScroll_y = 0;
}
if(nWorldPos_by >= nWorldSize_y)
{
bVertBoundsHit = true;
nWorldPos_ty = nWorldSize_y - nScreen_Ydim;
nWorldPos_by = nWorldSize_y;
nScroll_y = nWorldSize_y - nScreen_Ydim - 8;
}
//
// determine boundary hits
//
// right region border hit
if((nWorldPos_rx % nRegionSize == 0) && !bHorzBoundsHit)
{
// determine if we have split rows
nRowT = nWorldPos_ty / nRegionSize;
nRowB = nWorldPos_by / nRegionSize;
if(nRowT != nRowB)
{
//
// split rows
//
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
else
{
// rowt == rowb (same row)
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
}
// left region border hit
if((nWorldPos_lx % nRegionSize == 0) && !bHorzBoundsHit)
{
// determine if we have split rows
nRowT = nWorldPos_ty / nRegionSize;
nRowB = nWorldPos_by / nRegionSize;
if(nRowT != nRowB)
{
//
// split rows
//
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// get the previous region (one before us)
nRegion = nMapToRegion[nMap-1];
// move the previous map into the proper region
swiCopy(vMapLookup[nMap-1], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// get the previous region
nRegion = nMapToRegion[nMap-1];
// move the previous map into the proper region
swiCopy(vMapLookup[nMap-1], vRegionLookup[nRegion], nMapSize);
}
else
{
// rowt == rowb (same row)
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// get the previous region (one before us)
nRegion = nMapToRegion[nMap-1];
// move the previous map into the proper region
swiCopy(vMapLookup[nMap-1], vRegionLookup[nRegion], nMapSize);
}
}
// top region border hit
if((nWorldPos_ty % nRegionSize == 0) && !bVertBoundsHit)
{
// determine if we have split columns
nColL = nWorldPos_lx / nRegionSize;
nColR = nWorldPos_rx / nRegionSize;
// find the row we're on
nRowT = nWorldPos_ty / nRegionSize;
if(nColL != nColR)
{
//
// split columns
//
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_lx / nRegionSize) - nMapEntries_x;
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize) - nMapEntries_x;
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
else
{
// colL == colR (same columns)
// determine the map we're in
nMap = nRowT * nMapEntries_x + (nWorldPos_rx / nRegionSize) - nMapEntries_x;
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
}
// bottom region border hit
if((nWorldPos_by % nRegionSize == 0) && !bVertBoundsHit)
{
// determine if we have split columns
nColL = nWorldPos_lx / nRegionSize;
nColR = nWorldPos_rx / nRegionSize;
// find the row we're on
nRowB = nWorldPos_by / nRegionSize;
if(nColL != nColR)
{
//
// split columns
//
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_lx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
else
{
// colL == colR (same column)
// determine the map we're in
nMap = nRowB * nMapEntries_x + (nWorldPos_rx / nRegionSize);
// what region is this
nRegion = nMapToRegion[nMap];
// move the proper map into the proper region
swiCopy(vMapLookup[nMap], vRegionLookup[nRegion], nMapSize);
}
}
swiWaitForVBlank();
// set the scroll registers (scroll background)
BG0_X0 = nScroll_x;
BG0_Y0 = nScroll_y;
}
That's it! You can now scroll anywhere in your world, up, down, left, right, and diagonal. Changing the test hard coded limits I have, you can make your world any size you like and scroll.
I treated the DS screen to have the coordinates, LX,TY (left x, top y) for the upper, left hand corner, and RX,BY (right x, bottom y) for the lower, right hand corner. When scrolling you might be hovering over two tiles and scrolling vertical or horizantally, that is why I test for split rows, and columns.
I will clean some things up in my test code and make a generic C++ class, tile, scroll engine. I'll next, test dropping objects in my world at arbitrary locations and see if I can scroll around, leave and comeback and they are still where I left them. Of course, they won't actually stay by themselves, I'll have to write the code to make them behave.
If anyone would like a copy of the source, to help them get started, shoot me an email or post here and I'll get a link up or email you a copy. I don't know who's reading or interested, so that would be a good barometer.
In the mean time..."keep scrollin', scrollin', scrollin'!"
Friday, January 18, 2008
"In the midnight hour..."
"she cried more, more, more
with a rebel yell.."
Oh...we're on...broadcasting...
Hey there!
Just coming to you with a midnight update. I tried my scheme out on the DS just for a vertical, down scroll. I just wanted to see if what I was thinking was correct and whoohooo, it is. Hmmmn...it's not going to be a piece cake coding the DS without the source in the debugger, but I guess I'll have to manage, I don't have $1K to plunk down for the source level debugger for NO$GBA, but if anyone wants to, help a brother out, I'll be glad to put your donations to valuable DS programming use. However, I do love the fact that the NO$GBA debugger allows me to see all the memory areas of the DS, live and in living color. So, I guess I'll manage and will learn the arm7/9 assembly language too. Note: I am coding in C/C++, but the debugger only shows assembly code.
Anyway, the scheme works! There were some minor adjustments to my calculations, like the RegionSize should be 32*8, and not 32, since we're dealing with screen, pixel coordinates, not tile sizes.
I will try and code up the rest this weekend and get back to you with the...yes, yes, diagrams, and the code to do it.
"Owwww...in the midnight hour babe...
with a rebel yell.."
Oh...we're on...broadcasting...
Hey there!
Just coming to you with a midnight update. I tried my scheme out on the DS just for a vertical, down scroll. I just wanted to see if what I was thinking was correct and whoohooo, it is. Hmmmn...it's not going to be a piece cake coding the DS without the source in the debugger, but I guess I'll have to manage, I don't have $1K to plunk down for the source level debugger for NO$GBA, but if anyone wants to, help a brother out, I'll be glad to put your donations to valuable DS programming use. However, I do love the fact that the NO$GBA debugger allows me to see all the memory areas of the DS, live and in living color. So, I guess I'll manage and will learn the arm7/9 assembly language too. Note: I am coding in C/C++, but the debugger only shows assembly code.
Anyway, the scheme works! There were some minor adjustments to my calculations, like the RegionSize should be 32*8, and not 32, since we're dealing with screen, pixel coordinates, not tile sizes.
I will try and code up the rest this weekend and get back to you with the...yes, yes, diagrams, and the code to do it.
"Owwww...in the midnight hour babe...
Wednesday, January 16, 2008
Errata
In my posting yesterday, the calculation that determines that map you are in should have taken into account the row, you are scrolling over in the WorldMap. The row can be determined from your vertical scroll and a calculation to determine that.
So, the code should look like...
// determine the map we're in
nMap = nRow * nMapEntries_x + (nWorldPos_rx / nRegionSize + 1);
Where, nRow is going to be calculated from the vertical scroll. When, its all done I will post it.
Oh, just wanted to give a shot out to one of my co-workers, he works with me on the project we do for our day jobs, he's part-time, still in college. His name is Steve Taylor, this guy is already internet famous, with the indy game he released, 'Plasma Pong.' Atari got upset and made him pull his site down, since he used the name, 'Pong,' because there can be no infringement of two paddles hitting a ball across the screen. Atari wasn't the first to do that or patent that.
If you want to see the game, go to youtube, search for 'plasma pong,' it is very cool. Steve uses fluid dynamics in real time in the game. We've talked about the math intensive calculations he had to do for it. He's shown me a demo of one of his other ideas using soft-body (rag doll) physics.
As a side note, here's some 6 degrees of separation for you. I use to work for Nolan Bushnell the original founder of Atari, and creator of Pong. I worked at PlayNet, where Nolan was part-owner.
So Atari get off Steve's back and, "let me see that Pong! That Pong, pa-pa-pa-Pong!" (sing it to the beat of what's that singer's name, is he even still recording, you know, the Thong song dude).
So, the code should look like...
// determine the map we're in
nMap = nRow * nMapEntries_x + (nWorldPos_rx / nRegionSize + 1);
Where, nRow is going to be calculated from the vertical scroll. When, its all done I will post it.
Oh, just wanted to give a shot out to one of my co-workers, he works with me on the project we do for our day jobs, he's part-time, still in college. His name is Steve Taylor, this guy is already internet famous, with the indy game he released, 'Plasma Pong.' Atari got upset and made him pull his site down, since he used the name, 'Pong,' because there can be no infringement of two paddles hitting a ball across the screen. Atari wasn't the first to do that or patent that.
If you want to see the game, go to youtube, search for 'plasma pong,' it is very cool. Steve uses fluid dynamics in real time in the game. We've talked about the math intensive calculations he had to do for it. He's shown me a demo of one of his other ideas using soft-body (rag doll) physics.
As a side note, here's some 6 degrees of separation for you. I use to work for Nolan Bushnell the original founder of Atari, and creator of Pong. I worked at PlayNet, where Nolan was part-owner.
So Atari get off Steve's back and, "let me see that Pong! That Pong, pa-pa-pa-Pong!" (sing it to the beat of what's that singer's name, is he even still recording, you know, the Thong song dude).
Subscribe to:
Posts (Atom)