碰撞检测无法使用两个对象列表?

时间:2018-01-22 02:20:41

标签: c# xna collision-detection

我的碰撞检测不起作用。我有一个我的弹丸列表和另一个我的块。我尝试使用循环来检测碰撞检测,如我的代码所示,但它不起作用。我的碰撞检测代码是:

public void Collision_Detection()
    {
     for (int p = 0; p < projectile.Count; p++)
        {
         for (int i = 0; i < level_1.Count; i++)
            {

             if (projectile_obj[p].logRect.Intersects(level_1_blocks[i].rectangle))
               {
                //Subprogram here          
               }
          }
     }
}

我的射弹类是:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace DestroytheFort
{

 class Projectile 
{
    public static Texture2D log;
    public static Vector2 logPos;
    public Rectangle logRect;

    public Projectile(Texture2D newLog, Vector2 newLogPos, Rectangle newLogRect)
    {
        log = newLog;
        logPos = newLogPos;
        logRect = newLogRect;
    }

    public void Initialize()
    {
    }



    static double g = 520;
    public static int keyState = 0;
    static double v, vx, vy, alpha, t2 = 0;

    public static void Update(GameTime gameTime)
    {
        // TODO: Add your update code here
        if ((ISU.mouse.LeftButton == ButtonState.Pressed) && ISU.isInLevel == true)
        {
            keyState = 1;
            v = -820;
            alpha = MathHelper.ToRadians(33f);
            vx = v * Math.Cos(alpha);
            vy = v * Math.Sin(alpha);
        }
        if (keyState == 1)
        {
            logPos.Y = (float)(vy * t2 + g * t2 * t2 / 2) + 540 - log.Height;
            logPos.X = (float)((vx * -1) * t2) + 60;
            t2 = t2 + gameTime.ElapsedGameTime.TotalSeconds;
        }
        if (logPos.Y > ISU.graphics.GraphicsDevice.Viewport.Height - log.Height)
        {
            logPos.Y = ISU.graphics.GraphicsDevice.Viewport.Height - log.Height;
            keyState = 0;
            t2 = 0;
        }
        if (logPos.X > ISU.graphics.GraphicsDevice.Viewport.Width - log.Width)
        {
            logPos.X = ISU.graphics.GraphicsDevice.Viewport.Width - log.Width;
            keyState = 0;
            t2 = 0;
        }
  }
   public void Draw(SpriteBatch spriteBatch)
    {

        spriteBatch.Draw(log, logPos, logRect, Color.White); 

    }
}

我的level_1课程:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace DestroytheFort
{

class Wood_Level_1
{
    public Texture2D texture;
    public Rectangle rectangle;


    public Wood_Level_1(Texture2D newTexture, Rectangle newRect)
    {
        texture = newTexture;
        rectangle = newRect;
    }
    /// <summary>
    /// Allows the game component to perform any initialization it needs to before starting
    /// to run.  This is where it can query for any required services and load content.
    /// </summary>
    public void Initialize()
    {
        // TODO: Add your initialization code here


    }

    /// <summary>
    /// Allows the game component to update itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    public void Update(GameTime gameTime)
    {
        // TODO: Add your update code here


    }

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

}

level_1是我的1级课程列表的名称。我在我的主类中调用Update()中的碰撞检测方法。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

问题是你要比较纹理子图,而不是对象的边界。 Projectile.logRectWood_Level_1.rectangle是纹理子图,用于碰撞检测和绘图。您需要存储和更新每个对象的当前位置,以便检查它们在世界上的界限。

class Projectile
{
    // Removed 'static' and renamed from 'log' and 'logRect', as static limits
    // instancing and a class called "Projectile" shouldn't be limited to logs.
    public Texture2D texture;
    public Rectangle srcRect;
    public Vector2 position;
    // I suggest moving this to your input system. It's out of place here.
    public static int keyState; // = 0 is the default.

    public Projectile(Texture2D texture, Rectangle srcRect, Vector2 position)
    {
        this.texture = texture;
        this.srcRect = srcRect;
        this.position = position;
    }

    public void Update(GameTime gameTime)
    {
        // You use static variables where locals will suffice.
        double v = 0;
        double vx = 0, vy = 0;
        double alpha = 0;
        double t2 = 0;

        // I haven't thoroughly analyzed your math, but assuming it's correct, bounds should be computed correctly.
        if ((ISU.mouse.LeftButton == ButtonState.Pressed) && ISU.isInLevel == true)
        {
            keyState = 1;
            v = -820;
            alpha = MathHelper.ToRadians(33f);
            vx = v * Math.Cos(alpha);
            vy = v * Math.Sin(alpha);
        }

        if (keyState == 1)
        {
            position.Y = (float)(vy * t2 + g * t2 * t2 / 2) + 540 - srcRect.Height;
            position.X = (float)((vx * -1) * t2) + 60;
            t2 = t2 + gameTime.ElapsedGameTime.TotalSeconds;
        }

        // Clamp to the left of the viewport.
        if (position.X < 0) 
        {
            position.X = 0;
            keyState = 0;
        }
        // Clamp to the right of the viewport.
        var right = ISU.graphics.GraphicsDevice.Viewport.Width - srcRect.Width;
        if (position.X > right)
        {
            position.X = right;
            keyState = 0;
        }
        // Clamp to the top of the viewport.
        if (position.Y < 0) 
        {
            position.Y = 0;
            keyState = 0;
        }
        // Clamp to the bottom of the viewport.
        var bottom = ISU.graphics.GraphicsDevice.Viewport.Height - srcRect.Height;
        if (position.Y > bottom)
        {
            position.Y = bottom;
            keyState = 0;
        }
    }

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

最后,在Collision_Detection的最里面的循环中:

var proj = projectile_obj[p];
var projBounds = new Rectangle(
    proj.position.X, proj.position.Y,
    proj.srcRect.Width, proj.srcRect.Height);
if (projBounds.Intersects(level_1_blocks[i].rectangle))
{
    //Subprogram here          
}

我建议将Wood_Level_1重命名为Level,因此它似乎不限于您的第一级。如果您不打算这样做,至少将其重命名为WoodLevel1以符合.NET约定。