【问题标题】:Collision Detection not working with two lists of objects?碰撞检测不适用于两个对象列表?
【发布时间】:2023-03-03 00:23:01
【问题描述】:

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

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() 中调用碰撞检测方法。任何帮助将不胜感激。

【问题讨论】:

  • 您的问题格式错误。缺少几个尾随花括号。请更新它。解决您的问题,我很乐意为您解答。
  • 谢谢!

标签: c# xna collision-detection


【解决方案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 约定。

【讨论】:

  • rect是什么意思?当我尝试添加它时,它说该类型不存在
  • 如果我把我的一个类而不是 rect,Intersects 方法不起作用
  • "rect" 是Rectangle 的变量命名简写。您在哪里使用“rect”作为类型?
  • 好吧,我做到了。原来我不得不将位置变量更改为整数
  • 位置是Vector2,因此它可以同时保存水平和垂直轴值。使用int 可以防止亚像素定位并将您限制在一个轴上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-19
  • 1970-01-01
相关资源
最近更新 更多