如何在XNA(2D)中制作滚动地图?

时间:2012-12-08 21:53:03

标签: c# xna

我有一张地图,其中包含5000 * 5000区域内的许多物体。 我的屏幕尺寸是800 * 600。

如何滚动我的地图,我不想左右移动所有物体,我希望“相机”移动,但不幸的是我没有找到任何移动它的方法。

由于

2 个答案:

答案 0 :(得分:7)

<强>视口

首先创建相机视口。对于2D游戏,它可以像定义要开始渲染的左下角位置一样简单,并使用屏幕分辨率进行扩展,在您的情况下800x600

Rectangle viewportRect = new Rectangle(viewportX, viewportY, screenWidth, screenHeight);

以下是相机偏离300,700时的相机效果示例(图纸非常近似,只是为了让您更好看)

Viewport

可见性检查

现在,您想要找到与red square相交的每个精灵,这可以理解为您的Viewport。这可以用类似的东西来完成(这是未经测试的代码,只是它可能看起来的样本)

List<GameObject> objectsToBeRendered = new List<GameObject>();
foreach(GameObject obj in allGameObjects)
{
    Rectangle objectBounds = new Rectangle(obj.X, obj.Y, obj.Width, obj.Height);
    if(viewportRect.IntersectsWith(objectBounds))
    {
        objectsToBeRendered.Add(obj);
    }
}

以下是图形化的内容,绿色精灵是添加到objectsToBeRendered的精灵。将对象添加到单独的列表可以轻松地在渲染之前将它们从Back排序到Front

Visible

<强>渲染

现在我们发现了哪些物体相交,我们需要弄清楚屏幕上的最终位置。

spriteBatch.Begin();
foreach(GameObject obj in objectsToBeRendered)
{
    Vector2 pos = new Vector2(obj.X - viewportX, obj.Y - viewportY);
    spriteBatch.Draw(obj.GetTexture(), pos, Color.White);
}
spriteBatch.End();

如您所见,我们推导出视口的XY位置,以便将对象的世界位置置于视口中的Screen Coordinates。这意味着,400, 800World Coordinates处的小方块将在屏幕上100, 100呈现给定我们此处的视口。

修改

虽然我同意“正确答案”的更改,但请记住,我在此处发布的内容在决定要处理哪些动画,哪些AI要更新等等时仍然非常有用...让相机和GPU制作单独的工作会阻止你知道哪些对象实际上在屏幕上!

答案 1 :(得分:7)

我认为您正在寻找transformMatrixthis overload}的SpriteBatch.Begin参数。

您说您不希望对象移动,但您希望相机移动。但是,在最低级别,在2D和3D渲染中,没有“相机”的概念。渲染始终发生在同一区域 - 您必须使用变换将顶点/精灵放入该区域。

如果您想要相机的效果,则必须通过向相反方向移动整个世界来实现它。

当然,您实际上存储移动的数据。您只需在渲染数据时应用偏移量。 Emartel的答案是你为每个精灵做的。但是使用矩阵更简洁,因为您不必为每个Draw复制代码 - 您只需让GPU执行此操作。

完成一个示例:假设您希望将相机放置在(100,200)。为此,请将Matrix.CreateTranslation(-100, -200, 0)传递给SpriteBatch.Begin

(根据emartel的回答,自己进行视锥体剔除可能是浪费时间,除非你的世界真的巨大。请参阅this answer以获得性能考虑的解释。 )