好,所以我有一个CollisionManager来更新我的碰撞。我有一个弹丸类,一个玩家类和一个敌人类。在Player类中,我创建了一个弹丸列表(Projectile objs),Player类对其进行更新以增加或减少其数量。到目前为止,一切都很好。
现在是问题,当检查冲突时,播放器obj被敌人obj识别。但是,敌人不会识别投射物obj,除非我遍历整个投射物列表并手动检查其对撞机是否相交。除非特别检查,否则实际上看起来是射弹对撞机并且不存在。
代码如下:
玩家冲突代码(工作):
public override void OnCollision(Collidable obj)
{
Enemies enemy = obj as Enemies;
if (enemy != null)
{
health -= enemy.dmg; //if player collides with enemy, take dmg damage
}
}
弹丸碰撞代码(WORKING):
public override void OnCollision(Collidable obj)
{
Enemies enemy = obj as Enemies;
if (enemy != null)
{
exists = false;
if (!exists) FlaggedForRemoval = true;
}
}
敌人的碰撞代码(仅适用于玩家)
public override void OnCollision(Collidable obj)
{
//Check collision with player
Player pl = obj as Player;
if (pl != null)
{
exists = false;
ScoreManager.UpdateScore(pointsWorth);
}
//Check collision with projectile
Projectile pr = obj as Projectile;
if (pr != null)
{
health -= dmgReceived;
if (health <= 0)
{
ScoreManager.UpdateScore(pointsWorth);
exists = false;
FlaggedForRemoval = true;
}
}
}
仅当在Main.Update()期间,如果我遍历整个弹丸列表并手动检查与敌人的碰撞,敌对对象与弹丸的碰撞(针对敌人的对象-因为proj起作用)才起作用
foreach (Enemies e in enemyList)
{
e.Update(gameTime);
e.dmgReceived = player.dmg;
for (int i = 0; i < player.projList.Count; i++)
{
if (player.projList[i].collider.Intersects(e.BoundingRectangle))
{
//Some code
}
}
那是什么问题?在我看来,由于某种原因,在敌方碰撞代码中,obj类型未被识别为投射物,可能是因为它在列表中吗?
第一次在这里发布,所以我希望我做对了。感谢您的帮助!
更新以包含碰撞代码
public class Collidable
{
protected Rectangle boundingRectangle = new Rectangle();
public bool FlaggedForRemoval { get; protected set; }
//Constructor
public Collidable()
{
FlaggedForRemoval = false;
}
public Rectangle BoundingRectangle
{
get { return boundingRectangle; }
}
public virtual bool CollisionTest(Collidable obj)
{
return false;
}
public virtual void OnCollision(Collidable obj)
{
}
}
碰撞类:
public class CollisionComparer : IEqualityComparer<Collision>
{
public bool Equals(Collision a, Collision b)
{
if ((a == null) || (b == null))
{
return false;
}
return a.Equals(b);
}
public int GetHashCode(Collision a)
{
return a.GetHashCode();
}
}
public class Collision
{
public Collidable A;
public Collidable B;
public Collision(Collidable a, Collidable b)
{
A = a;
B = b;
}
public bool Equals(Collision other)
{
if (other == null) return false;
if ((this.A.Equals(other.A) && this.B.Equals(other.B))) return true;
return false;
}
public void Resolve()
{
this.A.OnCollision(this.B);
}
}
Collision Manager类:
public class CollisionManager
{
//List of classes inheriting from Collidables
private List<Collidable> m_Collidables = new List<Collidable>();
//Hashset to collect all collisions in a single update
private HashSet<Collision> m_Collisions = new HashSet<Collision>(new CollisionComparer());
public void AddCollidable(Collidable c)
{
m_Collidables.Add(c);
}
public void RemoveCollidable(Collidable c)
{
m_Collidables.Remove(c);
}
public void Update()
{
UpdateCollisions();
ResolveCollisions();
}
//Check Collisions hashset
private void UpdateCollisions()
{
if (m_Collisions.Count > 0) m_Collisions.Clear();
//Iterate thgouh collidable objects to check for collisions
for(int i =0; i<m_Collidables.Count; i++)
{
for (int j = 0; j < m_Collidables.Count; j++)
{
Collidable collidable1 = m_Collidables[i];
Collidable collidable2 = m_Collidables[j];
//Ensure we are not checking object with itself
if (!collidable1.Equals(collidable2))
{
//if two objects colliding then add them to the set
if (collidable1.CollisionTest(collidable2))
{
m_Collisions.Add(new Collision(collidable1, collidable2));
}
}
}
}
}
private void ResolveCollisions()
{
foreach (Collision c in m_Collisions)
{
c.Resolve();
}
}
}
基于上面的代码,这三个类(玩家,敌人,投射物)的碰撞检测为:
//Collision Detection
public override bool CollisionTest(Collidable obj)
{
if (obj != null)
{
return collider.Intersects(obj.BoundingRectangle);
}
else
return false;
}
我使用游戏main.Update()中的crashManager.Update()更新所有碰撞。
抱歉,代码太长!
更新2个已添加到列表中的显示项目
以下两者均在Player类下,而UpdateProjectile属于player.Update();
public void PlayerShoots()
{
//Fire only if projectile delay resets
if (projDelay >= 0)
projDelay--;
// if projectile delay is at 0 then create a new projectile(add to list)
if(projDelay <=0)
{
Projectile newProj = new Projectile(projTexture);
collisionManager.AddCollidable(newProj);
newProj.position = new Vector2(position.X + 100 - newProj.texture.Width / 2, position.Y ); //+ newProj.texture.Height/10
newProj.collider = new Rectangle((int)newProj.position.X, (int)newProj.position.Y, newProj.texture.Width, newProj.texture.Height);
newProj.exists = true;
if (projList.Count() < 80)
{
projList.Add(newProj);
}
}
//reset projectile delay
if (projDelay == 0)
projDelay = 50;
}
和
// update projectile functioN
public void UpdateProjectile()
{
// for each projectile in the list update its position and remove it if it reaches right screen boundary
foreach(Projectile p in projList)
{
//Update collider for every projectile in our list
p.collider = new Rectangle((int)p.position.X, (int)p.position.Y, p.texture.Width, p.texture.Height);
//Projectile motion
p.position.X = p.position.X + p.speed+1;
if (p.position.X >= 1118)
p.exists = false;
}
for(int i = 0; i<projList.Count; i++)
{
if(!projList[i].exists)
{
projList.RemoveAt(i);
i--;
}
}