Your drawing loop is still doing too much .

To draw the currently visible area of the map, we can do this:

Figure out the first tile that is visible on the screen, at the top-left position.
Calculate how far off the screen it is. Think about this: with a camera positioned at the very top-left of the world, the top-left tile would be (0,0) and it would fit snugly without any offset. However, if you scroll half a tile to the right, the top-left tile would still be [0,0], just moved a bit off the screen (i.e., you could only see its right half). If you scrolled a complete tile to the right, then the first tile would be [y=0, x=1] and there would be no offset.

So, when drawing the map, you need the following variables:

the tile x and y values in your map of the top-left-most tile
x and y values (in pixels) for calculating how far off the screen the first tile is drawn.

At that point, you know how many tiles are going to be visible on the screen (the screen size doesn't change after all!), so you can do two loops. Once you've calculated the top-left tile and offsets, you **know immediately** what tiles will be visible . This means that your code can be simplified to a few ifs (less than 10), versus 256 * 256 * 2 .

Code:
for y := start_tile_y to start_tile_y + vertical_tiles_visible_on_screen
begin
  for x := start_tile_x to start_tile_x + horizontal_tiles_visible_on_screen do
  begin
    //todo: draw the current tile at wanted offset
  end;
end;
You could hard-code the values for horizontal_tiles_on_screen and vertical_tiles_on_screen. In my ddraw one for 640x480 and 32x32 tiles, I used:

HORIZONTAL_TILES_ON_SCREEN = 20;
VERTICAL_TILES_ON_SCREEN = 16;

As long as the values are roughly correct then it doesn't matter. Clipping will take out anything slightly over the edge. Simply change the values until you get a complete screen of tiles (remembering about the initial offset-off-screen sometimes!). For example, try using the ddraw example code. If you change the horizontal tiles constant to 10, you'll see that only half of the screen gets filled with tiles.

The above is pseudocode-ish. Your current code is still checking over every tile - this ain't necessary, remember .

You can nick the camera class from my tutorial (probably copy-and-paste directly from the tutorial ). Take the ddraw example code and use the camera class there. You can remove the bit at the top of the file about waypoints and the FInternalX and FInternalY values - they're not used at present.

To use it, you'd create the camera per-level with the max width of your level:

FCamera := TCamera.Create(MapWidthInPixels, MapHeightInPixels);

(Remember to free it later.)

To get the map width/height in pixels, just multiply the width and height by your tile size (e.g. 256 * 32) for 32x32 tiles.

Other things you'll need for the code to work:

SCREEN_WIDTH - just a constant for the screen x res (e.g. 640)
SCREEN_HEIGHT - another constant for y screen res (480)
TILE_SIZE - a power of two (16 or 32, probably).
TILE_SHIFT - two-to-the-power-what = TILE_SIZE? (i.e., tile_shift = 3 for 8 pixel tiles, tile_Shift = 4 for 16 pixel tiles, or 5 for 32 pixel tiles). This is a worthless micro-optimisation.

The camera class assumes that you're using square tiles (16x16, 32x32, or whatever) and that the dimensions are powers of two. If your tiles don't fit into that category then let me know and I'll tell you how to change the code.

You'd centre on the players position using the camera's CentreOnPosition (in pixel coordinates) or CentreOnTile (in tile coordinates) method.

Both the example code zips show how to draw a map based on the current camera position - this is the same method as in the second tutorial part. Have a look at the link above, dude, and most of your questions will be answered.