带有对象列表的 C# XNA 碰撞检测
C# XNA Collision Detection with list of objects
我目前正在学习 C# 和 XNA,但在让碰撞检测正常工作方面遇到了一些麻烦。我希望我的玩家在 Enemy 对象相交时消失。
下面显示了我在 Obj 中的代码 class
class Obj
{
public Vector2 position;
public float rotation = 0.0f;
public Texture2D spriteIndex;
public string spriteName;
public float speed = 0.0f;
public float scale = 1.0f;
public bool alive = true;
public Rectangle area;
public bool solid = false;
public Obj(Vector2 pos)
{
position = pos;
}
private Obj()
{
}
public virtual void Update()
{
if (!alive) return;
UpdateArea();
pushTo(speed, rotation);
}
public virtual void LoadContent(ContentManager content)
{
spriteIndex = content.Load<Texture2D>("sprites\" + spriteName);
area = new Rectangle(0, 0, spriteIndex.Width, spriteIndex.Height);
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (!alive) return;
Rectangle Size;
Vector2 center = new Vector2(spriteIndex.Width / 2, spriteIndex.Height / 2);
spriteBatch.Draw(spriteIndex, position, null, Color.White, MathHelper.ToRadians(rotation), center, scale, SpriteEffects.None, 0);
}
public bool Collision(Vector2 pos, Obj obj)
{
Rectangle newArea = new Rectangle(area.X, area.Y, area.Width, area.Height);
newArea.X += (int)pos.X;
newArea.Y += (int)pos.Y;
foreach (Obj o in Items.objList)
{
if (o.GetType() == obj.GetType() && o.solid)
if (o.area.Intersects(newArea))
return true;
}
return false;
}
public Obj Collision(Obj obj)
{
foreach (Obj o in Items.objList)
{
if (o.GetType() == obj.GetType())
if (o.area.Intersects(area))
return o;
}
return new Obj();
}
public void UpdateArea()
{
area.X = (int)position.X - (spriteIndex.Width / 2);
area.Y = (int)position.Y - (spriteIndex.Height / 2);
}
public T CheckCollisionAgainst<T>() where T : Obj
{
// If collision detected, returns the colliding object; otherwise null.
return Items.objList
.OfType<T>()
.FirstOrDefault(o => o.solid && o.area.Intersects(area));
}
public virtual void pushTo(float pix, float dir)
{
float newX = (float)Math.Cos(MathHelper.ToRadians(dir));
float newY = (float)Math.Sin(MathHelper.ToRadians(dir));
position.X += pix * (float)newX;
position.Y += pix * (float)newY;
}
}
我循环遍历我的 objList 中的每个项目,看看它们是否相互交叉,在这种情况下,如果敌人与它们相交,我希望我的玩家消失,但这并没有发生。
此代码来自我的播放器class
class Player : Obj
{
KeyboardState keyboard;
KeyboardState prevKeyboard;
float spd;
public static Player player;
public Player(Vector2 pos)
: base(pos)
{
position = pos;
spd = 4;
spriteName = "WhiteBall";
solid = false;
player = this;
}
public override void Update()
{
player = this;
//If the player is NOT alive, end.
if (!alive) return;
keyboard = Keyboard.GetState();
//Keyboard controls for game
if(keyboard.IsKeyDown(Keys.W) && !Collision(new Vector2(0, -spd), new Enemy(new Vector2(0, 0))))
{
position.Y -= spd;
}
if (keyboard.IsKeyDown(Keys.A) && !Collision(new Vector2(-spd, 0), new Enemy(new Vector2(0, 0))))
{
position.X -= spd;
}
if (keyboard.IsKeyDown(Keys.S) && !Collision(new Vector2(0, spd), new Enemy(new Vector2(0, 0))))
{
position.Y += spd;
}
if (keyboard.IsKeyDown(Keys.D) && !Collision(new Vector2(spd, 0), new Enemy(new Vector2(0, 0))))
{
position.X += spd;
}
prevKeyboard = keyboard;
//Collision with enemy
Enemy enemy = CheckCollisionAgainst<Enemy>();
if (enemy != null)
{
alive = false;
}
base.Update();
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.DrawString(Game1.font, "Pick Up The Crew", new Vector2(350, 0), Color.White);
base.Draw(spriteBatch);
}
}
如果它与敌人相交,它应该会消失,但这似乎并没有发生。
根据您提供的评论,我在这里拍摄并提供可能的解决方案(确保在调用此之前调用 UpdateArea
):
public T CheckCollisionAgainst<T>() where T : Obj
{
// If collision detected, returns the colliding object; otherwise null.
return Items.objList
.OfType<T>()
.FirstOrDefault(o => o.area.Intersects(area));
}
Enemy enemy = CheckCollisionAgainst<Enemy>();
if (enemy != null)
{
alive = false;
}
我目前正在学习 C# 和 XNA,但在让碰撞检测正常工作方面遇到了一些麻烦。我希望我的玩家在 Enemy 对象相交时消失。
下面显示了我在 Obj 中的代码 class
class Obj
{
public Vector2 position;
public float rotation = 0.0f;
public Texture2D spriteIndex;
public string spriteName;
public float speed = 0.0f;
public float scale = 1.0f;
public bool alive = true;
public Rectangle area;
public bool solid = false;
public Obj(Vector2 pos)
{
position = pos;
}
private Obj()
{
}
public virtual void Update()
{
if (!alive) return;
UpdateArea();
pushTo(speed, rotation);
}
public virtual void LoadContent(ContentManager content)
{
spriteIndex = content.Load<Texture2D>("sprites\" + spriteName);
area = new Rectangle(0, 0, spriteIndex.Width, spriteIndex.Height);
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (!alive) return;
Rectangle Size;
Vector2 center = new Vector2(spriteIndex.Width / 2, spriteIndex.Height / 2);
spriteBatch.Draw(spriteIndex, position, null, Color.White, MathHelper.ToRadians(rotation), center, scale, SpriteEffects.None, 0);
}
public bool Collision(Vector2 pos, Obj obj)
{
Rectangle newArea = new Rectangle(area.X, area.Y, area.Width, area.Height);
newArea.X += (int)pos.X;
newArea.Y += (int)pos.Y;
foreach (Obj o in Items.objList)
{
if (o.GetType() == obj.GetType() && o.solid)
if (o.area.Intersects(newArea))
return true;
}
return false;
}
public Obj Collision(Obj obj)
{
foreach (Obj o in Items.objList)
{
if (o.GetType() == obj.GetType())
if (o.area.Intersects(area))
return o;
}
return new Obj();
}
public void UpdateArea()
{
area.X = (int)position.X - (spriteIndex.Width / 2);
area.Y = (int)position.Y - (spriteIndex.Height / 2);
}
public T CheckCollisionAgainst<T>() where T : Obj
{
// If collision detected, returns the colliding object; otherwise null.
return Items.objList
.OfType<T>()
.FirstOrDefault(o => o.solid && o.area.Intersects(area));
}
public virtual void pushTo(float pix, float dir)
{
float newX = (float)Math.Cos(MathHelper.ToRadians(dir));
float newY = (float)Math.Sin(MathHelper.ToRadians(dir));
position.X += pix * (float)newX;
position.Y += pix * (float)newY;
}
}
我循环遍历我的 objList 中的每个项目,看看它们是否相互交叉,在这种情况下,如果敌人与它们相交,我希望我的玩家消失,但这并没有发生。
此代码来自我的播放器class
class Player : Obj
{
KeyboardState keyboard;
KeyboardState prevKeyboard;
float spd;
public static Player player;
public Player(Vector2 pos)
: base(pos)
{
position = pos;
spd = 4;
spriteName = "WhiteBall";
solid = false;
player = this;
}
public override void Update()
{
player = this;
//If the player is NOT alive, end.
if (!alive) return;
keyboard = Keyboard.GetState();
//Keyboard controls for game
if(keyboard.IsKeyDown(Keys.W) && !Collision(new Vector2(0, -spd), new Enemy(new Vector2(0, 0))))
{
position.Y -= spd;
}
if (keyboard.IsKeyDown(Keys.A) && !Collision(new Vector2(-spd, 0), new Enemy(new Vector2(0, 0))))
{
position.X -= spd;
}
if (keyboard.IsKeyDown(Keys.S) && !Collision(new Vector2(0, spd), new Enemy(new Vector2(0, 0))))
{
position.Y += spd;
}
if (keyboard.IsKeyDown(Keys.D) && !Collision(new Vector2(spd, 0), new Enemy(new Vector2(0, 0))))
{
position.X += spd;
}
prevKeyboard = keyboard;
//Collision with enemy
Enemy enemy = CheckCollisionAgainst<Enemy>();
if (enemy != null)
{
alive = false;
}
base.Update();
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.DrawString(Game1.font, "Pick Up The Crew", new Vector2(350, 0), Color.White);
base.Draw(spriteBatch);
}
}
如果它与敌人相交,它应该会消失,但这似乎并没有发生。
根据您提供的评论,我在这里拍摄并提供可能的解决方案(确保在调用此之前调用 UpdateArea
):
public T CheckCollisionAgainst<T>() where T : Obj
{
// If collision detected, returns the colliding object; otherwise null.
return Items.objList
.OfType<T>()
.FirstOrDefault(o => o.area.Intersects(area));
}
Enemy enemy = CheckCollisionAgainst<Enemy>();
if (enemy != null)
{
alive = false;
}