0

我的碰撞检测似乎正在工作,尽管它检测到的一些碰撞很奇怪,因为它会说碰撞发生在平台的底部,而实际上它不是。然而,这不是主要问题。

当玩家与平台发生碰撞时,他并没有移动到平台的表面,而是移动到平台的上方,并且在我的重力到位的情况下,他看起来像是在不断地弹跳。我不知道为什么。

如果你们能提供帮助,将不胜感激。因为我是 XNA 和 C# 的新手,所以我可能会错过一些非常简单的东西。

我将在下面列出我的 Game1、Player 和 Platoform 类。(我的碰撞检测在播放器类中)

谢谢

游戏1类

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    Texture2D background;
    Movement character;
    Platform[] platforms;
    //private Vector2 SnapePosition = Vector2.Zero;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.PreferredBackBufferHeight = 440;
        graphics.PreferredBackBufferWidth = 782;

    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here
        platforms = new Platform[15];


        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);


        for (int i = 0; i < platforms.Length; i++)
        {
            platforms[i] = new Platform(
                Content.Load<Texture2D>("Platforms/lvl2_platform"), new Rectangle(i*100, 410, 100, 30));
        }
        character = new Movement(Content.Load<Texture2D>("snape"), new Rectangle(0, 360, 50, 50), platforms);

        // TODO: use this.Content to load your game content here
        background = Content.Load<Texture2D>("Backgrounds/lvl2_background");
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        //Allows the player to move
        character.Update();

        // TODO: Add your update logic here


        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here

        spriteBatch.Begin();
        spriteBatch.Draw(background, Vector2.Zero, Color.White);
        character.Draw(spriteBatch);

        foreach (Platform platform in platforms)
        {
            platform.Draw(spriteBatch);
        }
        spriteBatch.End();

        base.Draw(gameTime);
    }
}

玩家等级

class Player
{
    public Texture2D Snape;
    public Rectangle SnapePosition;

    public enum CollisionPosition { None, Top, Bottom, Left, Right };
    public CollisionPosition collisionType;
    public bool inCollision;
    public int collisionDepth;
    public Platform[] plat;
    public int num;

    public virtual void Update()
    {

    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Snape, SnapePosition, Color.White);
    }
}

class Movement : Player
{
        public Movement(Texture2D newSnape, Rectangle newSnapePosition, Platform[] a)
    {
        Snape = newSnape;
        SnapePosition = newSnapePosition;
        plat = a; 
    }

        public override void Update()
        {
            // Check for collision
            Collisions();

            // Determine collision type
            //DetermineCollisionType();

            // Separate snape
            //SeparateSnape();

            KeyboardState keyBoard = Keyboard.GetState();

            if (keyBoard.IsKeyDown(Keys.A))
            {
                SnapePosition.X -= 5;
            }
            if (keyBoard.IsKeyDown(Keys.D))
            {
                SnapePosition.X += 5;
            }
            if (keyBoard.IsKeyDown(Keys.W))
            {
                SnapePosition.Y -= 5;
            }
            //if (keyBoard.IsKeyDown(Keys.S))
            //{
                SnapePosition.Y += 5;
           // }



          //  if (SnapePosition.X < 0)
          //      SnapePosition.X = 0;
          //  if (SnapePosition.Y < 0)
          //      SnapePosition.Y = 0;
          //  if (SnapePosition.X > GraphicsDevice.Viewport.Width - Snape.Width)
          //      SnapePosition.X = GraphicsDevice.Viewport.Width - Snape.Width;
          //  if (SnapePosition.Y > GraphicsDevice.Viewport.Height - Snape.Height)
          //      SnapePosition.Y = GraphicsDevice.Viewport.Height - Snape.Height;

        }


        public void Collisions()
        {
            for (int i = 0; i < plat.Length; i++)
            {
                if (plat[i].rectangle.Intersects(SnapePosition))
                {
                    inCollision = true;
                    num = i;
                    DetermineCollisionType();
                }

            }

        }

        public void DetermineCollisionType()
        {
            if (inCollision == false)
            {
                collisionType = CollisionPosition.None;
                collisionDepth = 0;
            }
            else
            {
                // Determine the side of *least intersection* for snape
                int minColDepth = int.MaxValue;

                // Check the top side                    
                int tColDepth = (plat[num].rectangle.Y + plat[num].texture.Height / 2) - (SnapePosition.Y - Snape.Height / 2);

                if (tColDepth > 0 && tColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Top;
                    minColDepth = tColDepth;
                }

                // Check the bottom side            
                int bColDepth = (SnapePosition.Y + Snape.Height / 2) - (plat[num].rectangle.Y - plat[num].texture.Height / 2);

                if (bColDepth > 0 && bColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Bottom;
                    minColDepth = bColDepth;
                }

                // Check the right overlap
                int rColDepth = (SnapePosition.X + Snape.Width / 2) - (plat[num].rectangle.X - plat[num].texture.Width / 2);

                if (rColDepth > 0 && rColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Right;
                    minColDepth = rColDepth;
                }

                // Check the left overlap
                int lColDepth = (plat[num].rectangle.X + plat[num].texture.Width / 2) - (SnapePosition.X - Snape.Width / 2);

                if (lColDepth > 0 && lColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Left;
                    minColDepth = lColDepth;
                }

                // Update the collision depth
                collisionDepth = minColDepth;
                SeparateSnape();
            }
        }



        public void SeparateSnape()
        {
            switch (collisionType)
            {
                case CollisionPosition.None:
                    break;

                case CollisionPosition.Top:
                    SnapePosition.Y += (collisionDepth);
                    break;

                case CollisionPosition.Bottom:
                    SnapePosition.Y -= collisionDepth;
                    break;

                case CollisionPosition.Right:
                    SnapePosition.X -= collisionDepth;
                    break;

                case CollisionPosition.Left:
                    SnapePosition.X += collisionDepth;
                    break;
            }
        }
}

平台类

class Platform
{
    public Texture2D texture;
    public Rectangle rectangle;

    public Platform(Texture2D newTexture, Rectangle newRectangle)
    {
        texture = newTexture;
        rectangle = newRectangle;
    }

    public void Update()
    {

    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, rectangle, Color.White);
    }


}
4

1 回答 1

0

我修好了你的碰撞。

你所有的深度计算都不正确。你是根据实体(玩家/平台)的中心来做的,并使用它们的纹理大小而不是它们的矩形大小。

您可能一直认为一切都是从中间绘制的,但默认情况下它从 XNA 的左上角绘制。

这是位于“DetermineCollisionType()”函数下的“Movement”类中的新深度计算。

顶部深度需要在平台顶部 (Y) 和 snape 底部 (Y + 高度) 工作。

int tColDepth = 
    (SnapePosition.Y + SnapePosition.Height) - (plat[num].rectangle.Y);

底部深度需要在playform的底部(Y + Height)和Snape的顶部(Y)起作用。

int bColDepth = 
    (plat[num].rectangle.Y + plat[num].rectangle.Height) - (SnapePosition.Y);

正确的深度需要在平台的左侧 (X) 和 snape 的右侧 (X + Width) 起作用。

int rColDepth = 
    (SnapePosition.X + SnapePosition.Width) - (plat[num].rectangle.X);

左侧深度需要在平台右侧(X + Width)和 Snape 左侧(X)起作用。

int lColDepth = 
    (plat[num].rectangle.X + plat[num].rectangle.Width) - (SnapePosition.X);

这将从现在开始起作用。但是您可能希望为您的平台使用列表。当/如果您使用关卡编辑器时,列表会更容易,因为您不必说“我想要 15 个平台”。

于 2012-10-21T12:37:07.327 回答