   Vertical Scrolling Help
  Hey All!Ok so first off here is some background info:Language: C++IDE: VS 2008GameLIB: DirectX 9 March 2008 SDKOk so I am making a vertical scrolling top down plane shooter. I am using a book entitled : Beginning Game Programming Second Edition by Johnathan S. Harbour.I have been able to implement the function shown in the book ,which I will show you guys in a sec, but the background scrolls downward and not upward like a top down plane shooter should.So basically I am still new to all this and was hoping that someone could help me out with this little dilema. I am certain that it is an easy fix its just that I am not seeing it:First off the array that holds the tile numbers:int MAPDATA[MAPWIDTH*MAPHEIGHT] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191};Next the function calls://create the scroll buffer surface in memory, slightly bigger//than the screenresult = d3ddev->CreateOffscreenPlainSurface(SCROLLBUFFERWIDTH, SCROLLBUFFERHEIGHT, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,&scrollbuffer, NULL);void Game_Run(HWND hwnd){    //make sure the Direct3D device is valid    if (d3ddev == NULL)   return;Poll_Mouse();Poll_Keyboard();   //after short delay, ready for next frame?   //this keeps the game running at a steady frame rate   if (GetTickCount() - start >= 30)   {  //reset timing  start = GetTickCount();  //move the sprite  Player.CallMovement(); //update the scrolling view    UpdateScrollPosition();   //start rendering   if (d3ddev->BeginScene())   {    //erase the entire background    d3ddev->StretchRect(tiles, NULL, backbuffer, NULL, D3DTEXF_NONE);  //start sprite handler  sprite_handler->Begin(D3DXSPRITE_ALPHABLEND); //create vector to update sprite position   D3DXVECTOR3 position((float)Player.x, (float)Player.y, 0);    //draw tiles onto the scroll buffer    DrawTiles();//draw the scroll window onto the back bufferDrawScrollWindow();//draw the sprite  sprite_handler->Draw( player_ship,  NULL, NULL, &position, D3DCOLOR_XRGB(255,255,255));   sprite_handler->End();//stop renderingd3ddev->EndScene();}}    //display the back buffer on the screen    d3ddev->Present(NULL, NULL, NULL, NULL);    //check for escape key (to exit program)    if (Key_Down(DIK_ESCAPE))  DestroyWindow(hwnd);}And now the functions://This function updates the scrolling position and speedvoid UpdateScrollPosition(){SpeedY = 4;//update horizontal scrolling position and speed    ScrollX += SpeedX;    if (ScrollX < 0) {   ScrollX = 0;   SpeedX = 0;}    else if (ScrollX > GAMEWORLDWIDTH - WINDOWWIDTH){   ScrollX = GAMEWORLDWIDTH - WINDOWWIDTH;   SpeedX = 0;}    //update vertical scrolling position and speed    ScrollY += SpeedY;if (ScrollY < 0){   ScrollY = 0;   SpeedY = 0;}    if (ScrollY > GAMEWORLDHEIGHT - WINDOWHEIGHT){   ScrollY = GAMEWORLDHEIGHT - WINDOWHEIGHT;   SpeedY = 0;}}//This function does the real work of drawing a single tile from the //source image onto the tile scroll buffer. Parameters provide much //flexibility.void DrawTile(LPDIRECT3DSURFACE9 source,// source surface imageint tilenum,// tile #int width,// tile widthint height,// tile heightint columns,// columns of tilesLPDIRECT3DSURFACE9 dest,// destination surfaceint destx,// destination xint desty)// destination y{   //create a RECT to describe the source image    RECT r1;    r1.left = (tilenum % columns) * width;    r1.top = (tilenum / columns) * height;    r1.right = r1.left + width;    r1.bottom = r1.top + height;   //set destination rectRECT r2 = {destx,desty,destx+width,desty+height};   //draw the tiled3ddev->StretchRect(source, &r1, dest, &r2, D3DTEXF_NONE);}//This function fills the tilebuffer with tiles representing//the current scroll display based on scrollx/scrolly.void DrawTiles(){    int tilex, tiley;    int columns, rows;    int x, y;    int tilenum;   //calculate starting tile position    tilex = ScrollX / TILEWIDTH;    tiley = ScrollY / TILEHEIGHT;   //calculate the number of columns and rows    columns = WINDOWWIDTH / TILEWIDTH;    rows = WINDOWHEIGHT / TILEHEIGHT;   //draw tiles onto the scroll buffer surface    for (y=0; y<=rows; y++){   for (x=0; x<=columns; x++){//retrieve the tile number from this position  tilenum = MAPDATA[((tiley + y) * MAPWIDTH + (tilex + x))];//draw the tile onto the scroll buffer  DrawTile(tiles,tilenum,TILEWIDTH,TILEHEIGHT,16,scrollbuffer, x*TILEWIDTH,y*TILEHEIGHT);}}}//This function draws the portion of the scroll buffer onto the back buffer//according to the current "partial tile" scroll position.void DrawScrollWindow(){    //calculate the partial sub-tile lines to draw using modulus    int partialx = ScrollX % TILEWIDTH;    int partialy = ScrollY % TILEHEIGHT;   //set dimensions of the source image as a rectangleRECT r1 = {partialx,partialy,partialx+WINDOWWIDTH,partialy+WINDOWHEIGHT};  //set the destination rectangle    //This line draws the virtual scroll buffer to the screen exactly as is,    //without scaling the image to fit the screen. If your screen does not    //divide evenly with the tiles, then you may want to scale the scroll    //buffer to fill the entire screen. It's better to use a resolution that    //divides evenly with your tile size.    //use this line for scaled display//RECT r2 = {0, 0, WINDOWWIDTH-1, WINDOWHEIGHT-1};//use this line for non-scaled display    RECT r2 = {0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1};    //draw the "partial tile" scroll window onto the back buffer    d3ddev->StretchRect(scrollbuffer, &r1, backbuffer, &r2, D3DTEXF_NONE);}I understand that this is alot of code but Im sure you would need to know what all these functions looked like in order to understand how everything works.If anyone could help me and tell me how to make the background scroll upwards instead of downwards that would be amazing!Thanks!Mike   
  I didn't read the whole lot of the code but why do you set the speed to 0 if the Y position is 0. I don't think that should be there, make it your scroll speed   ;Quote:Original post by I Am LegendI didn't read the whole lot of the code but why do you set the speed to 0 if the Y position is 0. I don't think that should be there, make it your scroll speedI believe that just stop the window so it doesnt go past the background then you would just have black. However I did change it and everything still worked exactly the same.   ;  You do know that looking at the screen +Y is down and -Y so your code is doing exactly what you are telling it to scroll downwards and not upwards!So an easy fix would be to change the sign if you want it to go the other way.;Quote:Original post by daviangelYou do know that looking at the screen +Y is down and -Y so your code is doing exactly what you are telling it to scroll downwards and not upwards!So an easy fix would be to change the sign if you want it to go the other way.Yes I know how the x and y axises work on the screen but simply changing it to - y isnt enough because then the screen doesnt move it is already at the top. I need to know how to make it start at the bottom.   ;  Maybe try flipping your drawing routine to start at the bottom of the screen and work its way up.change this:  //draw tiles onto the scroll buffer surface    for (y=0; y<=rows; y++) to this:  //draw tiles onto the scroll buffer surface    for (y=rows; y<=0; y--)That will invert the map data as well so the first row will be at the bottom of the map with each row atop that.But if that isn't what you are looking for then figure out how tall the map is in pixel space (Map_Y * Tile_height) subtract the screen display height in pixels (-480 if 640X480 display) and start the camera there  ;Quote:Original post by MSWMaybe try flipping your drawing routine to start at the bottom of the screen and work its way up.change this:  //draw tiles onto the scroll buffer surface    for (y=0; y<=rows; y++) to this:  //draw tiles onto the scroll buffer surface    for (y=rows; y<=0; y--)That will invert the map data as well so the first row will be at the bottom of the map with each row atop that.But if that isn't what you are looking for then figure out how tall the map is in pixel space (Map_Y * Tile_height) subtract the screen display height in pixels (-480 if 640X480 display) and start the camera there  I am trying to better understand your last statement could you perhaps elaborate like with pseudocode?Thanks!   ;  Where are ScrollX and ScrollY declared, and what are they initialized with? I would really like to see that. It seems that everything should work, you just need to make SpeedY negative, and set ScrollX and ScrollY to where they would be at the bottom of the map. That'll be somthing like ScrollY = world_height - screen_height, in either tile coords or pixels.It appears that your scroll speeds and positions are globals. That's really not necessary.   ;  Okay lets say you have a set of tiles 32 by 32 pixels. And you have a map that is 20 tiles wide by 800 tiles tall.So if you were to draw out the map completely, each tile in the correct place. The picture you end up with would be 640 pixels wide (32 tile pixel width * 20 tiles wide) and 25,600 pixels tall (32 * 800).Now if your game screen is 640 pixels wide by 480 pixels tall and you draw the huge map image at 0,0. It would only draw the top area of the map.However if you told it to draw the huge map image at 0,-25,120 (25,600 pixels - 480 screen pixels) then it would draw the bottom of the image onscreen.Then if you were to draw the same image again at 0,-25,119 it would appear to have moved down one row of pixels. Then again at 0,-25,118 it would move down another row of pixels. Then draw it at 0,-25,117, another row...and on and on until you draw it at 0,0.This is NOT to say that you need to create a huge image of your map in memory. Rather think of the map and tiles as a form of image compression. Thats basicly all it is...one big image that has been reduced to a number of identical same size tiles and a simple data structure (the map) describeing how to put the image back together again.Except we don't need to draw the whole image, only the stuff thats onscreen. We do that by figureing out what section of the imaginary huge image would be onscreen.Or screens upper left corner is at 0,0. The bottom right corner is at 639 and 479 (640 pixels wide by 480 tall includeing 0,0).Or imaginary huge image's upper left corner is 0,0. And the lower right is 639 and 25,599.So if we try to draw that huge image at 0, -25,120. We are actualy inverting the sign and trying to draw the huge image pixel  at 0, 25,120 onto screen pixel at 0,0. In effect we are going to draw from 0, 25,120 to 639, 25,599 (0+ 639 screen width and 25,120 + 479 screen height)Now you know that you can calculate the map location of these two points by divideing by the tile size (32 pixels). So 0, 25,120 upper left corner = map location 0,785 (truncate the remainder) and the lower right corner of 639, 25,599 = map location map location 19, 799 (again truncated remainder).So if we set up our loop to draw map tiles from 0,785 to 19,799 we will have the correct section of map. So how much offset do we need inorder to draw the tiles correctly?Thats easy, simply take the location we were to draw this imaginary huge image at ( 0, -25,120 ) and use the MOD function with the tile size ( Offset_X = 0 MOD 32 = 0 and Offset_Y = -25,120 MOD 32 = 0 ). So we draw the first tile (map location 0,785) at screen location 0 + Offset_X, 0 + Offset_Y. Then next tile (map location 1, 785) is drawn at 0 + tile_width + Offset_X , 0 + Tile_height + Offset_Y. simply moveing over one map location and tile_width pixels each time until we move down another map location collom and tile_height to draw the next row of tiles. And yadda, yadda, yadda until the whole visable section of the map is drawn.  ;Quote:Original post by MSWOkay lets say you have a set of tiles 32 by 32 pixels. And you have a map that is 20 tiles wide by 800 tiles tall.So if you were to draw out the map completely, each tile in the correct place. The picture you end up with would be 640 pixels wide (32 tile pixel width * 20 tiles wide) and 25,600 pixels tall (32 * 800).Now if your game screen is 640 pixels wide by 480 pixels tall and you draw the huge map image at 0,0. It would only draw the top area of the map.However if you told it to draw the huge map image at 0,-25,120 (25,600 pixels - 480 screen pixels) then it would draw the bottom of the image onscreen.Then if you were to draw the same image again at 0,-25,119 it would appear to have moved down one row of pixels. Then again at 0,-25,118 it would move down another row of pixels. Then draw it at 0,-25,117, another row...and on and on until you draw it at 0,0.This is NOT to say that you need to create a huge image of your map in memory. Rather think of the map and tiles as a form of image compression. Thats basicly all it is...one big image that has been reduced to a number of identical same size tiles and a simple data structure (the map) describeing how to put the image back together again.Except we don't need to draw the whole image, only the stuff thats onscreen. We do that by figureing out what section of the imaginary huge image would be onscreen.Or screens upper left corner is at 0,0. The bottom right corner is at 639 and 479 (640 pixels wide by 480 tall includeing 0,0).Or imaginary huge image's upper left corner is 0,0. And the lower right is 639 and 25,599.So if we try to draw that huge image at 0, -25,120. We are actualy inverting the sign and trying to draw the huge image pixel  at 0, 25,120 onto screen pixel at 0,0. In effect we are going to draw from 0, 25,120 to 639, 25,599 (0+ 639 screen width and 25,120 + 479 screen height)Now you know that you can calculate the map location of these two points by divideing by the tile size (32 pixels). So 0, 25,120 upper left corner = map location 0,785 (truncate the remainder) and the lower right corner of 639, 25,599 = map location map location 19, 799 (again truncated remainder).So if we set up our loop to draw map tiles from 0,785 to 19,799 we will have the correct section of map. So how much offset do we need inorder to draw the tiles correctly?Thats easy, simply take the location we were to draw this imaginary huge image at ( 0, -25,120 ) and use the MOD function with the tile size ( Offset_X = 0 MOD 32 = 0 and Offset_Y = -25,120 MOD 32 = 0 ). So we draw the first tile (map location 0,785) at screen location 0 + Offset_X, 0 + Offset_Y. Then next tile (map location 1, 785) is drawn at 0 + tile_width + Offset_X , 0 + Tile_height + Offset_Y. simply moveing over one map location and tile_width pixels each time until we move down another map location collom and tile_height to draw the next row of tiles. And yadda, yadda, yadda until the whole visable section of the map is drawn.Thanks so much MSW and theOcelot!You guys have both helped me tremendously and I now have it scrolling correctly. Only one thing seems weird once the window reaches the top of the map it begins to flash and look weird. Any ideas as to why? Like why doesnt it just stop moving and thats it?Also what would be the best way to make the map go on for a while at least 2 mins worth of scrolling?Thank you all so much I am learning alot from you guys.   