碰撞检测不适用于两个对象列表?
Collision Detection not working with two lists of objects?
我的碰撞检测不起作用。我有一个弹丸清单和一个方块清单。我尝试使用循环来检测碰撞检测,如我的代码所示,但它不起作用。我的碰撞检测代码是:
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
}
}
}
}
我的射弹class是:
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_1class:
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 是我的 Level 1 class 的列表名称。我在主 class 中调用 Update() 中的碰撞检测方法。任何帮助将不胜感激。
问题是您比较的是纹理子矩形,而不是对象的边界。 Projectile.logRect
和 Wood_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 约定保持一致。
我的碰撞检测不起作用。我有一个弹丸清单和一个方块清单。我尝试使用循环来检测碰撞检测,如我的代码所示,但它不起作用。我的碰撞检测代码是:
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
}
}
}
}
我的射弹class是:
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_1class:
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 是我的 Level 1 class 的列表名称。我在主 class 中调用 Update() 中的碰撞检测方法。任何帮助将不胜感激。
问题是您比较的是纹理子矩形,而不是对象的边界。 Projectile.logRect
和 Wood_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 约定保持一致。