2

I succesfully generate my tile map and it works but when i want to scroll it the top line of tiles is moving and all the tiles is dragged of screen.. Its hard to explain,

Imagine this is the tiles: X

XXXXXXXXXXXXXXXXXXXXXXXXXX //Here it starts to remove tile by tile when camera is moving.

XXXXXXXXXXXXXXXXXXXXXXXXXX //Causing all the other tiles to move up line my line.

XXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXX

Take a look at my code:

public void Draw(SpriteBatch spriteBatch)
{
    currentLevel = level1;
    //Its here i need the value from Player class!
    int currentX = cameraX; //The current x cordiate to draw the tile too
    int currentY = 0; //The current y cordiate to draw the tile too
    for (int i = 0; i < currentLevel.Length; i++)
    {
        /*
         * A switch statement to see if the current level1[i] is either a grass, sky or stone tile
         */
        switch(currentLevel[i])
        {
            case 1:
                //Draw a sky tile
                spriteBatch.Draw(tileSheet, new Rectangle(currentX, currentY, 32, 32), skyTile, Color.White);
                break;

            case 2:
                //Draw a grass tile
                spriteBatch.Draw(tileSheet, new Rectangle(currentX, currentY, 32, 32), grassTile, Color.White);
                break;

            case 3:
                //Draw a stone tile
                spriteBatch.Draw(tileSheet, new Rectangle(currentX, currentY, 32, 32), stoneTile, Color.White);
                break;
        }

        //Add 32 to the current cordinate so we don't draw to the same spot all the time
        currentX = currentX + 32; 
        if (currentX >= 896) //If we hit the width of the map we want:
        {
            //Start drawing from X cordinate zero
            cameraX = 0;
            currentX = cameraX;
            //And Y cordinate + 32
            currentY = currentY + 32;
            //This will make so we draw one line and when we hit a full line on the map then we draw next line and soo on.
        }
    }
}

The CameraX variable is a getter from the Player class.. Which is decremented while holding the left button on the keyboard.

Here is the tile map that i draw from array(1 = sky, 2 = grass, 3 = stone:

int[] level1 = { 1, 1, 1, 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, 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, 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, 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, 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, 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, 3,
                         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 3,
                         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 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, 3,
                         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 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, 3,
                         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 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, 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, 3};

Any ideas?

User
  • 1,458
  • 3
  • 16
  • 40
  • I strongly recommend storing your grid as a 2D array, and using 2 (nested) for loops. it'll make the code a lot clearer and easier to follow. – George Duckett Dec 06 '11 at 16:37

3 Answers3

4

It looks like you are always drawing all the tiles in your entire map (i starts at 0 and loops through every tile). However, you are not always drawing the same number of tiles on each row. If CameraX is 0, then you will draw 28 tiles per row because you will move to the next row after 32*28 (896) pixels. But if CameraX is 480, then you will only draw 13 ((896-480)/32) tiles on each row, and the rest of the first row's tiles will draw on the second row (because you are still trying to draw all tiles). I think you should loop through each row and column that you want to draw, and calculate the tile index from those instead of looping through every tile in the map and calculating the position independently.

EDIT Here's some example code for calculating a tile index in a 1-dimensional array given a column and row index assuming you know the number of columns. (Or you could just switch to using a 2-d array):

i = row * columnCount + column;
BlueMonkMN
  • 25,079
  • 9
  • 80
  • 146
  • Yea like drawing every line of tiles separate? – User Dec 06 '11 at 16:48
  • Looks like that's the issue (as well as the `cameraX = 0;` which i still don't think should be there) – George Duckett Dec 06 '11 at 16:48
  • `if (currentX >= 896)` should be `if (currentX >= CameraX + 896)` to fix your current problem. I'd take the advice of [dowhilefor's answer](http://stackoverflow.com/a/8403537/593627) though. – George Duckett Dec 06 '11 at 16:53
  • How did you figure that out?? – User Dec 06 '11 at 16:57
  • @TheCompBoy Who are you asking? – BlueMonkMN Dec 06 '11 at 17:17
  • @BlueMonkMN Im asking GeorgeDuckett how he found that out. – User Dec 06 '11 at 17:18
  • George Duckett's suggestion simply forces currentX to not be reset until it has drawn all 28 columns (by adding 896 to the starting position). It would be similar to `if (i % 28 == 27)` or (at the beginning of the loop instead) `currentX = (i % 28) * 32 + CameraX;`. – BlueMonkMN Dec 06 '11 at 18:41
1

I believe your problem is that when you get to the end of a line you set the CameraX to 0.

You don't want to move the camera at the end of each line, you just want to reset the x drawing position (as you do in the next line).

So, remove cameraX = 0;

I'm not 100% sure that would cause the issue you describe, but it's definitely not right, as you say the player controls cameraX, so it shouldn't be changed in your draw function.

George Duckett
  • 31,770
  • 9
  • 95
  • 162
  • I tried that but it resulted in the tile map didn't even draw the tiles in correct place and soon as i decremented cameraX like all tiles went on random places. – User Dec 06 '11 at 16:41
  • Have you confirmed that cameraX and cameraY are reasonable values when you're trying to draw? (set your game going, press on the keyboard for a bit, then add a breakpoint so you can check them) – George Duckett Dec 06 '11 at 16:42
  • im doing cameraX--; when key press is noticed. And thats when the map should scroll but problem i have in my code is: I draw all the tiles together i think a solution would be drawing each line of tile separate and scroll them all backwards. – User Dec 06 '11 at 16:45
1

I don't really understand your code, but i advice you to use a 2 dimensional array or access the one dimensional array in a proper way like array[ Y * ARRAY_Width + X]. Besides that, why do you start your loop over the whole Level. Whats inside the camera is important, otherwise you will iterate over alot of tiles which arent visible anyway.

Start at your camera X an Y, calculate how many horizontal and vertical tiles you draw inside your camera viewport: These should be the only tiles you need to iterate. Also it seems like you are moving the tiles. You want to move the camera, not your tiles. SpriteBatch.Begin has an overload to set a Matrix containing your camera movement. If you don't now how to work with Matrix, just call

Matrix view = Matrix.CreateTranslate(new Vector3( myCam.X, myCam.Y, 0));

and pass that as the view matrix into the BeginSprite method.

These changes will make your code much easier.

Hope that helps.

dowhilefor
  • 10,971
  • 3
  • 28
  • 45
  • What would the two dimensional array be based of? X & Y?? I can't understand what would be the content of it. – User Dec 06 '11 at 17:11
  • First of all if you have a two dimensional array, it would of course be your horizontal and vertical amount of tiles. If you want to use a one dimensional array and you need to access the tile on horizontal X and vertical Y you need to calc the proper offset into your one dimensional array. like array[ Y * total_amount_of_horizontal_tiles + X ]. – dowhilefor Dec 06 '11 at 17:15
  • I must say that this sounds much more complicated than my way of doing this. But if this way is better im willing to change my code. – User Dec 06 '11 at 17:20