在其他SpriteBatch.Begin()中使用SpriteBatch.Begin()

时间:2011-03-14 18:04:02

标签: c# xna sprite

嘿伙计们,我正在尝试使用以下绘图逻辑:

Class Game
{
    Character x;

    public Draw(...)
    {
        spriteBatch.Begin(transformation1);
        x.Draw();
        spriteBatch.End();

        spriteBatch.Begin(transformation2);
        otherThing.Draw();
        spriteBatch.End();
    }
}

Class Character
{
    Animation[] animations;
    int currentAnimation;

    public Draw(...)
    {
        this.animations[this.currentAnimation].Draw();
    }
}

Class Animation
{
    Frame[] frames;
    int currentFrame;

    public Draw(...)
    {
        this.frames[this.currentFrame].Draw();
    }
}
Class Frame
{
    Texture2D texture;
    Texture2D shadow;

    public Draw(...)
    {
        spriteBatch.Begin(sub_transformation1);
        spriteBatch.Draw(texture1, ...);
        spriteBatch.End();

        spriteBatch.Begin(sub_transformation2);
        spriteBatch.Draw(shadow, ...);
        spriteBatch.End();
    }
}

如果我尝试这个逻辑,我会得到一个“在成功调用End之前不能再次调用Begin”。错误。所以我问这个逻辑是否可行/有意义?我在Begin()中使用Begin()进行加法转换。如果我有一个x = 100和y = 100的字符,我想要框架的纹理和阴影以及我想要的其他所有东西(边界框等),使用100,100平移,加上-Xscale或+ Xscale绘制水平翻转角色(我知道我可以在.Draw中使用SpriteEffects.FlipHorizo​​ntally,但我想要一些自动应用到底层(动画和框架)),最后在Frame级别,纹理有一个转换角色的顶部和阴影的另一个。不知道我是否解释得很好,但问你是否有任何疑问。

非常感谢。

2 个答案:

答案 0 :(得分:2)

我知道你来自哪里,但这是不可能的。 SpriteBatch不能像你想要的那样分层。但是,你的对象可以。

稍微编辑以解决您的问题:

Class Frame
{
    // World - parent transformation to build from, passed 
    // from animation, from character, on up the chain...
    // localTransform - local coordinates
    // shadowTransform - maybe not needed?
    public Draw(Matrix world, Matrix localTransform, Matrix shadowTransform)
    {
        spriteBatch.Begin();
        spriteBatch.Draw(
            texture1, 
            ..., 
            Matrix.Transform(world * localTransform),
            ...);

        spriteBatch.Draw(
            shadowTexture, 
            ..., 
            Matrix.Transform(world * localTransform * shadowTransform), 
            ...);

        spriteBatch.End();
    }
}

您不必将所有字符或对象信息传递到帧中 - 只需要由帧父级设置转换即可。您的原始代码已经从某处接收到转换(sub_transformation1和2) - 这里我们只是将该值传递给Draw函数。你也可以使localTransform成为一个类变量,在实例化时设置它。

Animation类将具有类似的Draw(Matrix world ...)签名。我认为它实现了你正在寻找的东西,类似于OpenGL处理​​事物的方式 - 只是更多的手动(从我多年前的记忆中来看)。

旁注,游戏相关问题也有gamedev.stackexchange.com

答案 1 :(得分:0)

如果您根据传统的World / View / Project转型模型考虑SpriteBatch:

您应该在Draw电话中进行“世界”转型。也就是说,如果你的精灵位于position,你应该在position画出它。如果它在position + 100处有阴影,也可以在那里绘制。

你应该在Begin电话中进行你的观察(以及项目,如果你正在变得有趣)转换 - 这是你的“相机”变换。

(在某些情况下,您只能通过矩阵获得所需的世界变换,但这很不寻常。)

你不能用SpriteBatch“堆叠”转换,你必须在外部实现这样的事情。