C#XNA绘制方法和冲突错误

C#XNA绘制方法和冲突错误,c#,xna,draw,collision,C#,Xna,Draw,Collision,在从一本创建3个游戏的书中学习了C#XNA之后,我一直在尝试制作一个2D RPG游戏,但是这些错误让我发疯,我不得不放弃,因为我找不到任何修复方法 首先是绘制方法,我在屏幕上绘制了岩石,它们在相同的深度绘制,但按顺序绘制,使其沿着X轴,然后增加Y轴并重置X,依此类推。因此,它们应该与上面或左边的其他岩石重叠,但这不起作用。当我四处走动或射箭时,它们会随机地相互重叠,如果有帮助,下面是我的代码: Game1.cs绘制方法 Protected override void Draw(GameTime

在从一本创建3个游戏的书中学习了C#XNA之后,我一直在尝试制作一个2D RPG游戏,但是这些错误让我发疯,我不得不放弃,因为我找不到任何修复方法

首先是绘制方法,我在屏幕上绘制了岩石,它们在相同的深度绘制,但按顺序绘制,使其沿着X轴,然后增加Y轴并重置X,依此类推。因此,它们应该与上面或左边的其他岩石重叠,但这不起作用。当我四处走动或射箭时,它们会随机地相互重叠,如果有帮助,下面是我的代码:

Game1.cs绘制方法

Protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin(
            SpriteSortMode.BackToFront,
            BlendState.AlphaBlend);

        TileMap.Draw(spriteBatch);
        ObjectManager.Draw(spriteBatch);
        player.Draw(spriteBatch);
        WeaponManager.Draw(spriteBatch);

        spriteBatch.End();

        base.Draw(gameTime);
    }
static public void Draw(SpriteBatch spriteBatch)
    {
        // Get the tile locations of each corner tile on the screen
        int startX = (((int)Camera.Position.X) / 32) - 2;
        int endX = ((int)Camera.Position.X + Camera.ViewPortWidth) / 32;

        int startY = (((int)Camera.Position.Y) / 32) - 2;
        int endY = ((int)Camera.Position.Y + Camera.ViewPortHeight) / 32;

        // Go through all possible objects and draw them to the screen if they exist
        for (int y = startY; y <= endY; y++)
            for (int x = startX; x <= endX; x++)
            {
                if ((x > 0) && (y > 0) && (x < MapWidth - 1) && (y < MapHeight - 1))
                {
                    if (objects[x, y] != null)
                    {
                        spriteBatch.Draw(
                                texture,
                                Camera.Transform(objects[x, y].destinationRectangle),
                                objects[x, y].Frame,
                                new Color(256, 256, 256, objects[x, y].Transparency),
                                0,
                                new Vector2(0, 0),
                                SpriteEffects.None,
                                objects[x, y].Depth);
                    }
                }
            }
    }
ObjectManager绘制方法

Protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin(
            SpriteSortMode.BackToFront,
            BlendState.AlphaBlend);

        TileMap.Draw(spriteBatch);
        ObjectManager.Draw(spriteBatch);
        player.Draw(spriteBatch);
        WeaponManager.Draw(spriteBatch);

        spriteBatch.End();

        base.Draw(gameTime);
    }
static public void Draw(SpriteBatch spriteBatch)
    {
        // Get the tile locations of each corner tile on the screen
        int startX = (((int)Camera.Position.X) / 32) - 2;
        int endX = ((int)Camera.Position.X + Camera.ViewPortWidth) / 32;

        int startY = (((int)Camera.Position.Y) / 32) - 2;
        int endY = ((int)Camera.Position.Y + Camera.ViewPortHeight) / 32;

        // Go through all possible objects and draw them to the screen if they exist
        for (int y = startY; y <= endY; y++)
            for (int x = startX; x <= endX; x++)
            {
                if ((x > 0) && (y > 0) && (x < MapWidth - 1) && (y < MapHeight - 1))
                {
                    if (objects[x, y] != null)
                    {
                        spriteBatch.Draw(
                                texture,
                                Camera.Transform(objects[x, y].destinationRectangle),
                                objects[x, y].Frame,
                                new Color(256, 256, 256, objects[x, y].Transparency),
                                0,
                                new Vector2(0, 0),
                                SpriteEffects.None,
                                objects[x, y].Depth);
                    }
                }
            }
    }
static public void Draw(SpriteBatch-SpriteBatch)
{
//获取屏幕上每个角磁贴的磁贴位置
intstartx=((int)Camera.Position.X)/32)-2;
int endX=((int)Camera.Position.X+Camera.ViewPortWidth)/32;
int startY=((int)Camera.Position.Y)/32)-2;
int endY=((int)Camera.Position.Y+Camera.ViewPortHeight)/32;
//浏览所有可能的对象,并将它们绘制到屏幕上(如果存在)
对于(inty=startY;y0)和&(x
第二个问题是关于我的碰撞,我对所有的东西都使用矩形类的边界框碰撞。当我的玩家角色移动时,我会为新位置创建一个新矩形,如果他与任何对象的任何边界框发生碰撞,则移动将被取消,但有时他仍会移动到该位置,并在对象中卡住1个像素。它只是没有任何意义,有时它会发生,有时它不会发生,即使是同一个对象。如果有人知道为什么会发生这种情况,请发帖,这里有太多的代码要粘贴,所以我不说了,我更担心绘图方法的问题。

您正在这样做:

 spriteBatch.Begin(
        SpriteSortMode.BackToFront,
        BlendState.AlphaBlend);
这将根据深度对绘制调用进行重新排序

因此,如果对象具有相同的深度,则将随机绘制

最好根据您希望绘制的图形修改岩石的深度

float min_depth = 0.7f;
float max_depth = 0.5f;
int num_rocks_total;
int index_rocks;
for (rock_top_left to rock_bottom_right) 
  rock.depth = MathHelper.Lerp(min_depth, max_depth, index_rocks/ (float) num_rocks_total);

第二个错误可能是由于浮点精度造成的。

问题1

正如Blau所说,你的岩石将从前面到后面分类,因为它们有相同的深度,它们(有时)会被随机分类。这可能是由于浮点精度(或缺乏浮点精度)

您可以使用
SpriteSortMode.Deferred
,而不是更改岩石的深度,它将按顺序绘制精灵,并延迟渲染,直到调用End(或直到spriteBatch无法处理更多精灵并需要刷新)

问题2

正如Blau所说,这也可能是由于浮点精度。然而,这个问题是可以避免的。想象有一个移动的磁贴,你的玩家走到磁贴附近。然后,磁贴移动到玩家的顶部(因为我们忘记了将磁贴编码为不移动)。您现在是玩家,无法移动,因为玩家尝试移动的任何方向都是“无效”移动,因为他将触摸该瓷砖

问题是我们正在阻止角色移动。如果角色可以一直移动,我们就不会有这个问题。然而,如果角色总是可以移动,他就可以更准确地完成任务。为了防止这种情况发生,我们需要一个相反的动作,当角色移动到一个固体物体上时,它会对角色起作用

解决方案:

允许玩家移动到一个物体中,然后扫描他正在触摸的所有物体。如果他碰到任何物体,找出你应该让他离开每个物体的方向,并将所有这些方向组合成一个向量。按一定比例缩放该向量(以防止角色被显著推开)。根据该向量移动播放器

此方法存在的问题:

如果你有来自地心引力之类的力,你可能会发现你的角色“下沉”到地上。这是重力对将玩家从瓦片上推回的力的推动的结果。这个问题可以通过在对玩家施加力使其离开之前将角色从任何瓷砖上移开来解决

这是一个非常复杂的问题,已经为您解决了

Box 2D/Farseer物理引擎

你可能以前听说过这些,并且认为“哦,我会自己做,因为这听起来非常有趣!”而且,虽然编写自己的物理引擎可能非常有趣,但它也需要非常长的时间。如果你想让你的游戏在物理上快速运行(即使它们是简单的音速物理),艾琳·卡托已经为你奠定了一切基础

看看这些:

Box2D XNA:


Farseer Physics:

不使用SpriteSortMode.BackToFront,您可以使用延迟:

spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
这是文件: