XNA视区投影和SpriteBatch [英] XNA ViewPort projection and SpriteBatch

查看:118
本文介绍了XNA视区投影和SpriteBatch的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的XNA游戏,我用ViewPort.Project和ViewPort.Unproject翻译,并从世界坐标。目前我使用这些,因为我与SpriteBatch绘制每个对象。我希望做的就是计算一个矩阵,我可以发送给SpriteBatch.Begin做屏幕空间转换对我来说。



下面是我目前使用的翻译,并从屏幕空间的功能:

  Vector2 ToWorldCoordinates(Vector2像素)
{
的Vector3 worldPosition = graphics.GraphicsDevice.Viewport.Unproject(新的Vector3(像素,0),
投影,视图,Matrix.Identity);
返回新Vector2(worldPosition.X,worldPosition.Y);
}

Vector2 ToScreenCoordinates(Vector2 worldCoords)
{
VAR screenPositon = graphics.GraphicsDevice.Viewport.Project(新的Vector3(worldCoords,0),
预测,视图,Matrix.Identity);
返回新Vector2(screenPositon.X,screenPositon.Y);
}

查看设置为Matrix.Identity和投影设置像这样:

 投影= Matrix.CreateOrthographic(40 * graphics.GraphicsDevice.Viewport.AspectRatio,40,0,1); 

这是我现在画的东西:

  spriteBatch.Begin(); 
的foreach(在thingsToDraw VAR东西)
{
spriteBatch.Draw(thing.Texture,ToScreenCoordinates(thing.PositionInWorldCoordinates),thing.Color);
spriteBatch.End();
}
spriteBatch.End();

这是我想要做什么,而不是(使用XNA 4.0版本SpriteBatch.Begin的())

  //我如何计算这个矩阵? 
矩阵myTransformationMatrix = GetMyTransformationMatrix();

spriteBatch.Begin(SpriteSortMode.Immediate,NULL,NULL,NULL,NULL,NULL,
myTransformationMatrix);

的foreach(在thingsToDraw VAR东西)
{
//注意:不再是每个对象的位置转换为屏幕坐标
spriteBatch.Draw(thing.Texture,东西.PositionInWorldCoordinates,thing.Color);
spriteBatch.End();
}
spriteBatch.End();


解决方案

我已经写了 SpriteBatch 和各种空间(世界的投影,客户端等)的此处这里这里 。 。这些问题的答案可能是值得一读



SpriteBatch 假定你的世界空间是同样的事情,客户的空间 - 这然而许多像素高和宽视口,产地左上角,Y +已关闭。



它看起来像(根据您的使用的CreateOrthographic ),你希望你的世界空间显示为40台高大,在屏幕上,但是和许多单位将适合widthways。你也想​​在屏幕中心的世界起源和Y +到了。



所以,你必须要坚持的另一个矩阵之间的世界空间转换为客户的空间。我相信正确的矩阵(在psudocode):规模(40 / viewport.Height)*规模(1,-1)*翻译(viewport.Width / 2,viewport.Height / 2)。缩放,翻转和翻译从世界去给客户。



您一定还记得精灵假设Y +已关闭。所以,你必须通过(1,-1)大规模进入 SpriteBatch.Draw ,否则会得出倒(并且,由于背面剔除,是不可见的)。


I'm working on an XNA game and I am using ViewPort.Project and ViewPort.Unproject to translate to and from world coordinates. Currently I use these for each object I draw with SpriteBatch. What I would like to do is calculate a Matrix that I can send to SpriteBatch.Begin to do the screen-space transformation for me.

Here are the functions I currently use to translate to and from screenspace:

        Vector2 ToWorldCoordinates(Vector2 pixels)
    {
        Vector3 worldPosition = graphics.GraphicsDevice.Viewport.Unproject(new Vector3(pixels, 0),
                Projection, View, Matrix.Identity);
        return new Vector2(worldPosition.X, worldPosition.Y);
    }

    Vector2 ToScreenCoordinates(Vector2 worldCoords)
    {
        var screenPositon = graphics.GraphicsDevice.Viewport.Project(new Vector3(worldCoords, 0),
                Projection, View, Matrix.Identity);
        return new Vector2(screenPositon.X, screenPositon.Y);
    }

View is set to Matrix.Identity, and Projection is set like so:

Projection = Matrix.CreateOrthographic(40 * graphics.GraphicsDevice.Viewport.AspectRatio, 40, 0, 1);

And here is how I currently draw things:

            spriteBatch.Begin();
        foreach (var thing in thingsToDraw)
        {
            spriteBatch.Draw(thing.Texture, ToScreenCoordinates(thing.PositionInWorldCoordinates), thing.Color);
            spriteBatch.End();
        }
        spriteBatch.End();

This is what I would like to do instead (using XNA 4.0 version of SpriteBatch.Begin())

            // how do I calculate this matrix?
        Matrix myTransformationMatrix = GetMyTransformationMatrix();

        spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null,
            myTransformationMatrix);

        foreach (var thing in thingsToDraw)
        {
            // note: no longer converting each object's position to screen coordinates
            spriteBatch.Draw(thing.Texture, thing.PositionInWorldCoordinates, thing.Color);
            spriteBatch.End();
        }
        spriteBatch.End();

解决方案

I've written about SpriteBatch and the various "spaces" (world, projection, client, etc) here, here and here. Those answers are probably worth reading.

SpriteBatch assumes that your World space is the same thing as Client space - which is however many pixels tall and wide the viewport is, origin top-left, Y+ is down.

It looks like (based on your use of CreateOrthographic) you want your World space to appear as 40 units tall, on screen, and however many units will fit widthways. You also want the World origin at the centre of the screen and Y+ is up.

So you have to stick another matrix in between to convert your World space to Client space. I believe the correct matrix is (in psudocode): scale(40/viewport.Height) * scale(1, -1) * translate(viewport.Width/2, viewport.Height/2). Scale, flip and translate to go from World to Client.

You must also remember that sprites assume that Y+ is down. So you have to pass a (1, -1) scale into SpriteBatch.Draw, otherwise they will be drawn inverted (and, due to backface culling, be invisible).

这篇关于XNA视区投影和SpriteBatch的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆