【问题标题】:Side scrolling a tile map, Map getting messed up横向滚动平铺地图,地图变得混乱
【发布时间】:2012-01-14 06:05:10
【问题描述】:

我成功生成了我的瓦片地图,它可以工作,但是当我想滚动它时,瓦片的顶行正在移动,所有瓦片都被拖到屏幕上。这很难解释,

想象一下这是瓷砖:X

XXXXXXXXXXXXXXXXXXXXXXXXXXX //这里开始在相机移动时逐块移除。

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //使所有其他瓷砖都向上移动我的线。

XXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXX

看看我的代码:

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.
        }
    }
}

CameraX 变量是 Player 类的一个 getter。按住键盘上的左键时它会递减。

这是我从数组中绘制的瓦片图(1 = 天空,2 = 草,3 = 石头:

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};

有什么想法吗?

【问题讨论】:

  • 我强烈建议您将网格存储为二维数组,并使用 2(嵌套)循环。它会让代码更清晰,更容易理解。

标签: c# xna side-scroller


【解决方案1】:

我相信您的问题是,当您到达一行末尾时,您将CameraX 设置为0

您不想在每行的末尾移动相机,您只想重置 x 绘图位置(就像在下一行中所做的那样)。

所以,删除cameraX = 0;

我不能 100% 确定这会导致您描述的问题,但绝对不正确,正如您所说的播放器控件 cameraX,因此不应在您的绘图函数中更改它。

【讨论】:

  • 我试过了,但结果是瓦片地图甚至没有在正确的位置绘制瓦片,而且当我减小 cameraX 时,就像所有瓦片都在随机位置一样。
  • 当您尝试绘图时,您是否确认 cameraX 和 cameraY 是合理的值? (设置你的游戏,按一下键盘,然后添加一个断点以便你检查它们)
  • 我在做cameraX--;当注意到按键时。那就是地图应该滚动的时候,但我在代码中遇到的问题是:我将所有图块绘制在一起我认为解决方案是将每条图块分开绘制并将它们全部向后滚动。
【解决方案2】:

我不太了解您的代码,但我建议您使用二维数组或以array[ Y * ARRAY_Width + X] 之类的正确方式访问一维数组。除此之外,你为什么要在整个关卡上开始循环。相机内部的内容很重要,否则您将遍历很多无论如何都不可见的图块。

从您的相机 X 和 Y 开始,计算您在相机视口内绘制了多少水平和垂直平铺:这些应该是您需要迭代的唯一平铺。此外,您似乎正在移动瓷砖。你想移动相机,而不是你的瓷砖。 SpriteBatch.Begin 有一个重载来设置一个包含你的相机移动的矩阵。如果您现在不知道如何使用 Matrix,只需调用

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

并将其作为视图矩阵传递给 BeginSprite 方法。

这些更改将使您的代码更容易。

希望对您有所帮助。

【讨论】:

  • 二维数组的基础是什么? X&Y??我不明白它的内容是什么。
  • 首先,如果你有一个二维数组,那当然是你的水平和垂直数量的瓷砖。如果要使用一维数组,并且需要访问水平 X 和垂直 Y 上的图块,则需要将适当的偏移量计算到一维数组中。像数组[ Y * total_amount_of_horizo​​ntal_tiles + X ]。
  • 我必须说这听起来比我这样做的方式要复杂得多。但如果这种方式更好,我愿意更改我的代码。
【解决方案3】:

看起来您总是在整个地图中绘制所有图块(我从 0 开始并循环遍历每个图块)。但是,您并不总是在每行上绘制相同数量的图块。如果 CameraX 为 0,那么您将每行绘制 28 个图块,因为您将在 32*28 (896) 像素之后移动到下一行。但是如果 CameraX 是 480,那么你将只在每一行上绘制 13 个 ((896-480)/32) 个图块,而第一行的其余图块将在第二行上绘制(因为你仍在尝试绘制 所有瓷砖)。我认为您应该遍历要绘制的每一行和每一列,并从中计算图块索引,而不是遍历地图中的每个图块并独立计算位置。

编辑 下面是一些示例代码,用于在给定列和行索引的情况下计算一维数组中的图块索引,假设您知道列数。 (或者你可以切换到使用二维数组):

i = row * columnCount + column;

【讨论】:

  • 是的,喜欢将每一行瓷砖分开吗?
  • 看起来这就是问题所在(以及我仍然认为不应该存在的cameraX = 0;
  • if (currentX &gt;= 896) 应该是 if (currentX &gt;= CameraX + 896) 以解决您当前的问题。不过我会接受dowhilefor's answer 的建议。
  • 你是怎么知道的??
  • @TheCompBoy 你在问谁?
猜你喜欢
  • 2011-12-03
  • 1970-01-01
  • 2014-10-23
  • 1970-01-01
  • 2016-01-24
  • 2012-02-12
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
相关资源
最近更新 更多