Scrolling in a 2D RTS game - How to?
Guys, I've been wondering. I'm creating a 2d rts game, and i have all the basic stuff:
I have all the tiles i need and the map array ready and all that, but I've been wondering..
How do I program scrolling?
I mean, the idea I had (For example, when I'm scrolling right: ) was to 'chop' a 'pixel-size line' of the next tile to be drawn while moving all the drawn map a pixel to the left, and then draw the next 'line' until I finally draw all that tile, and so on and on.
The thing is that I don't really know how to 'chop' a picture I have in memory. Can someone please help me on how to do that?
Or if you have a better idea for scrolling, I'll thank you even more.
I'm using SDL, btw.
Oh yeah, and one small thing - I want to enter a 'quote' of a piece of code here in the forum, how do I do that (prolly [thing] and [/thing], but don't know what is that 'thing').
Thanx :)
[Edited by - Twiggy on January 4, 2005 7:24:35 AM]
Are you using the 2D SDL API or OpenGL through SDL?
If you are using the 2D SDL api: Basically what i did a long time ago using directDraw
Create a ClipBlit function that takes in: Image - Surface, DestRect - Rectangle, SourceRect - Rectangle.
Ok now i'm assuming you are blitting onto the backbuffer. Get the Rectangle associated with the backbuffer and test the DestRectangle against it as such:
The code will adjust the destination and source rectangles so that only the visible parts are copied from the source surface and the destionation rectnagle is fully on the screen. Check it out on paper and work out the tests for the other three sides of the screen.
they are [.code.] and [./code.] tags, remove the dots.
If you are using the 2D SDL api: Basically what i did a long time ago using directDraw
Create a ClipBlit function that takes in: Image - Surface, DestRect - Rectangle, SourceRect - Rectangle.
Ok now i'm assuming you are blitting onto the backbuffer. Get the Rectangle associated with the backbuffer and test the DestRectangle against it as such:
//check if the destination rectangle is going off the top of the screenif (DestRect.y < BackRect.y){ float difference = BackRect.y - DestRect.y; DestRect.y += difference; SourceRect.y += difference; }
The code will adjust the destination and source rectangles so that only the visible parts are copied from the source surface and the destionation rectnagle is fully on the screen. Check it out on paper and work out the tests for the other three sides of the screen.
they are [.code.] and [./code.] tags, remove the dots.
In addition to what Ilici said, if you use tiles you basically do the same (e.g. figure out which is the first visible tile and render the portion of the map from there). For smooth (pixel-wise) scrolling a little more effort is required, but it's the same principle.
BTW you can also use [.source] [./source.] tags (without the dots again) to post syntax-highlighted code.
HTH,
Pat.
BTW you can also use [.source] [./source.] tags (without the dots again) to post syntax-highlighted code.
HTH,
Pat.
Thank you very much, but I did not understand. I am not such an experienced proggrammer, and a very unexperienced SDL progger.
Darookie, what did you mean by...
And Ilici, the thing I needed to know was not how to know how many pixels to draw, but was how to take the portion of the tile i need and draw it.
I basically need instructions on how the system works.
Thanx again.
Darookie, what did you mean by...
Quote:figure out which is the first visible tile and render the portion of the map from there
And Ilici, the thing I needed to know was not how to know how many pixels to draw, but was how to take the portion of the tile i need and draw it.
I basically need instructions on how the system works.
Thanx again.
So you use tiles, right? Then you surely have an array of some sort that tells you where tiles are located on the map.
Say you have a map of 64x64 tiles and each tile is 32x32 pixels in size.
Your whole map is therefore 64*32 x 64*32 = 2048x2048 pixels in size and this doesn't fit on your average screen.
Now let's say your output window is 640x480 pixels in size. This leaves you with a max of 640/32 x 480/32 = 20x15 visible tiles.
If you set your initial upper-left tile to be tile (0,0) in your map, you just draw the first 20 tiles for each of the first 15 rows of you map.
Now if you scroll tile-by-tile (which I'd recommend to start with), you just change this first upper-left tile you draw:
Hope that helps,
Pat.
Say you have a map of 64x64 tiles and each tile is 32x32 pixels in size.
Your whole map is therefore 64*32 x 64*32 = 2048x2048 pixels in size and this doesn't fit on your average screen.
Now let's say your output window is 640x480 pixels in size. This leaves you with a max of 640/32 x 480/32 = 20x15 visible tiles.
If you set your initial upper-left tile to be tile (0,0) in your map, you just draw the first 20 tiles for each of the first 15 rows of you map.
Now if you scroll tile-by-tile (which I'd recommend to start with), you just change this first upper-left tile you draw:
const int MAP_SIZE_X = 64;const int MAP_SIZE_Y = 64;// let's suppose this array holds the Ids of your tiles in the mapint tileMap[MAP_SIZE_Y][MAP_SIZE_X];// these constants hold the number of visible tiles of the mapconst int visibileTilesX = WINDOW_WIDTH / TILE_SIZE_X;const int visibileTilesY = WINDOW_WIDTH / TILE_SIZE_X;// these are your start positions for simple tile-by-tile scrollingint startTileX = 0;int startTileY = 0;void drawTile(int tileNumber, int screenX, int screenY) { // blit tile image here}void drawMap() { // tile screen position in pixels int screenY = 0; for (int mapY = startTileY; mapY < visibleTilesY; ++mapY) { // tile screen position in pixels int screenX = 0; for (int mapY = startTileX; mapX < visibleTilesY; ++mapY) { drawTile(map[mapY][mapX], screenX, screenY); // set position to next tile screenX += TILE_SIZE_X; } // set position to next row on screen screenY += TILE_SIZE_Y; }}// scroll the map by the given amount of tilesvoid scrollMap(int tilesX, int tilesY) { // update start positions startTileX += tilesX; startTileY += tilesY; // make sure you don't get out of the map boundaries if (startTileX < 0) startTileX = 0; else if (startTileX > MAP_SIZE_X - visibleTilesX) startTileX = MAP_SIZE_X - visibleTilesX; if (startTileY < 0) startTileY = 0; else if (startTileY > MAP_SIZE_Y - visibleTilesY) startTileY = MAP_SIZE_Y - visibleTilesY;}
Hope that helps,
Pat.
It's not too difficult if you keep your wits about you. Once you've made it scroll a whole tile at a time at first, add a second pair of coordinates to keep track of the position of the top left corner of the viewscreen in the top left tile, and when you draw the tiles shift the whole lot up and to the left by that amount.
Basically, you change startX and startY to where the upperleft corner of the screen is on your map. So, you can move these around to where you want them.
My method of clipping tiles was simply to draw one row off screen, sort of as a buffer. It keeps the tile in memory and displays part of it if the screen doesn't show a whole tile.
NOTE: This isn't actual working code. Just typed it up as a demonstration of the row/col buffer. Probably doesn't even work. If so, let me know.
My method of clipping tiles was simply to draw one row off screen, sort of as a buffer. It keeps the tile in memory and displays part of it if the screen doesn't show a whole tile.
int startCol = (startX/tileSize) - 1;int endCol = (screenWidth/tileSize) + 1;int startRow = (startY/tileSize) - 1;int endRow = (screenHeight/tileSize) + 1;for(int i = startCol; i <= endCol; i++){ for(int j = startRow; j <= endRow; j++) { drawImage(startX + (i * tileSize), startY + (j * tileSize), tileMap[j].getImage()); }}//cleanup code here
NOTE: This isn't actual working code. Just typed it up as a demonstration of the row/col buffer. Probably doesn't even work. If so, let me know.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement