Side scrolling can be done several ways.
Several large images
Scrolling several pieced together static bitmaps is a simple matter of scrolling the u,v coords. However you will run out of texture memory and you will not have as much flexibility as a tile engine.
Tile engine
The screen is composed of tiled images all pieced together. For scrolling you basically create a grid that has 1 extra row on top/bottom and 1 extra column on left/right. The formulas are:
Code:
if ((ScrollX % tileWidth) == 0)
{
arrayOffset ++;
//Snap X position of grid render to origin here
...
...
}
if ((ScrollY % tileHeight) == 0)
{
arrayOffset += numTilesPerRow;
//Snap Y position of grid render to origin here
...
...
}
There is one edge case when scrollX and scrollY are 0 since 0 % x = 0. I have not accounted for this in the sample code.
Some sample scrolling code:
Code:
...
int tileMapWorldWidth = numTilesPerRow * tileWidth;
int tileMapWorldHeight = numTilesPerColumn * tileHeight;
int numTilesPerRowOnScreen = (screen.maxX - screen.minX) / tileWidth;
int numTilesPerColumnOnScreen = (screen.maxY - screen.minY) / tileHeight;
maxScrollX = tileMapWorldWidth - (numTilePerRowOnScreen * tileWidth);
maxScrollY = tileMapWorldHeight - (numTilesPerColumnOnScreen * tileHeight);
bool canScrollX = false;
bool canScrollY = false;
if ( (scrollX > 0) && (scrollX < maxScrollX))
{
canScrollX = true;
}
if ((scrollY > 0) && (scrollY < maxScrolly))
{
canScrollY = true;
}
f (canScrollX)
{
scrollX += scrollXIncrement;
}
if (canScrollY)
{
scrollY += scrollYIncrement;
}
...
Now your rendering code will compute where to start drawing the grid based on scrollX and scrollY. To draw the tiles you start at an x,y and an arrayOffset.
Some sample rendering code:
Code:
int renderX = -(scrollX % tileWidth);
int renderY = -(scrollY % tileHeight);
int arrayOffset = (scrollY / tileHeight) * numTilesPerRow + (scrollX / tileWidth);
int orig_renderX = renderX;
while (renderY < screen.maxY)
{
int tileNumber = TileMap.GetTileAt(arrayOffset);
Tile *pTile = TileManager.GetTile(tileNumber);
if (pTile)
{
DrawTileAt(pTile,renderX,renderY);
}
renderX += tileWidth;
arrayOffset ++;
if (renderX > screen.maxX)
{
renderX = orig_renderX;
renderY += tileHeight;
}
}
Please understand that I wrote this from memory while sitting here at the computer. I make no guarantees that it will work as is. However it should give you some idea of how to go about coding this. It would also be more efficient to draw from top to bottom, left to right rather than left to right, top to bottom as I have shown.
Other pieces you need are:
- A 2D array that represents the tile numbers that make up the map
- A container that can map from tile number to tile object
- A renderer that places the sprites on the tile map
- Tile graphics
I usually prefer to have my sprites separate from the tile map but still check the tile map to check for collisions with tiles that cannot be moved onto.
Also if you are using one image to represent all your sprites make sure you set your texture addressing mode to CLAMP or you will get seams around your textures.
There are other optimizations to really make a tile map fly but I won't get into those here since the rendering code becomes a bit more complex.
And to prove I'm not full of it I've attached screenshots of my tile engine and my tile editor written using C++ and MFC.
If you need an editor I might be able to help you. I wouldn't mind breaking out the old editor and using it to make some maps for you...provided you have the graphics ready.