/// <summary> /// 计算并输出一个伤害.若只对护盾造成伤害而无法对护甲造成伤害则为0,若需要对护甲按 /// 剩余护盾比例造成伤害则介于0~1之间 默认为0.02 若m为单位护盾值与最大护盾值得比对单位的伤害计算式为: /// 护盾伤害=foldShield*BasicDamage*(1-crossValue)护甲伤害=foldArmor*BasicDamage*crossValue /// </summary> /// <param name="unit">伤害的单位</param> /// <param name="shield">对护盾的伤害</param> /// <param name="armor">对护甲的伤害</param> public void OutDamage(VioableUnit unit, ref float shield, ref float armor) { shield = 0.0f; armor = 0.0f; float dmg = BasicDamage * Fold; if (IsShieldUseless == false) { if (unit.Shield > FoldShield * dmg * (1 - CrossValue)) { shield = FoldShield * dmg * (1 - CrossValue); armor = FoldArmor * dmg * CrossValue; } else { shield = unit.Shield; if (FoldShield != 0 && CrossValue != 0 && CrossValue != 1) { float d = shield / FoldShield; armor = (dmg - d) * FoldArmor; } } } else { shield = 0.0f; armor = dmg * FoldArmor; } }
public static bool IsCollided(VioableUnit unit, BoundingSphere boundingSphere) { if (Vector3.Distance(unit.Position, boundingSphere.Center) <= GameConsts.BoundingDistance) { if (isCollided(unit.Model.TransformedMajorSphere, boundingSphere)) { foreach (BoundingSphere k in unit.Model.TransformedBoundingSpheres) { if (k != null) { if (isCollided(k, boundingSphere)) { return(true); } } } } } return(false); }
public static bool IsCollided(VioableUnit unit, Barrel b) { bool ins = false; if (b.Intersects(unit.Model.TransformedMajorSphere)) { foreach (BoundingSphere k in unit.Model.TransformedBoundingSpheres) { if (k != null) { if (b.Intersects(k)) { ins = true; return(ins); } } } } return(ins); }
/// <summary> /// 处理弹药和单位的碰撞,返回碰撞点 /// </summary> /// <param name="unit"></param> /// <param name="bullet"></param> /// <returns></returns> public static Vector3?IsCollided(VioableUnit unit, Bullet bullet) { if (Vector3.Distance(unit.Position, bullet.position) <= GameConsts.BoundingDistance) { if (bullet.position != bullet.positionl) { Ray ray1; Ray ray2; if (bullet.weapon.isInstant == false) { ray1 = new Ray(bullet.positionl, Vector3.Normalize(bullet.position - bullet.positionl)); ray2 = new Ray(bullet.position, Vector3.Normalize(bullet.positionl - bullet.position)); } else { Vector3 v1 = bullet.position; Vector3 v2 = bullet.position + Vector3.Normalize(bullet.velocity) * bullet.Range; ray1 = new Ray(v1, Vector3.Normalize(v2 - v1)); ray2 = new Ray(v2, Vector3.Normalize(v1 - v2)); } if (unit.Model.TransformedMajorSphere.Intersects(ray1) != null && unit.Model.TransformedMajorSphere.Intersects(ray2) != null) { foreach (BoundingSphere k in unit.Model.TransformedBoundingSpheres) { if (k.Intersects(ray1) != null && k.Intersects(ray2) != null) { return(k.GetCollisionPoint(ray1)); } } } } return(null); } return(null); }
/// <summary> /// 通过球体的碰撞检测检查出目标是否在导弹爆炸范围内 /// </summary> /// <param name="unit">目标</param> /// <param name="missile">导弹</param> /// <param name="explosionRadiusFold">半径缩放倍数,在是否爆炸判断时可比1稍小</param> /// <returns></returns> public static bool IsCollided(VioableUnit unit, Missile missile, float explosionRadiusFold) { if (Vector3.Distance(unit.Position, missile.Position) <= GameConsts.BoundingDistance) { BoundingSphere b = new BoundingSphere(missile.Position, missile.missileType.explosionRadius * explosionRadiusFold); ContainmentType ct = b.Contains(unit.Model.TransformedMajorSphere); ContainmentType ct2 = unit.Model.TransformedMajorSphere.Contains(b); if (ct != ContainmentType.Disjoint || ct2 != ContainmentType.Disjoint) { foreach (BoundingSphere k in unit.Model.TransformedBoundingSpheres) { ContainmentType ct3 = b.Contains(k); ContainmentType ct4 = k.Contains(b); if (ct3 != ContainmentType.Disjoint || ct4 != ContainmentType.Disjoint) { return(true); } } } } return(false); }
public override void Update(GameTime gameTime) { float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; #region 更新单位 removingUnits.Clear(); for (int i = 0; i < units.Count; i++) { Unit u = units[i]; if (u != null) { u.Update(gameTime); if (u.UnitState == UnitState.dead) { removingUnits.Add(u);//收集要被移除的单位 } } } #endregion #region 回收多余的单位 foreach (Unit u in removingUnits) { if (u != null) { units.Remove(u); } } #endregion #region 环境物 removingDecorations.Clear();//晕,终于发现这里居然错误地写成了removingMissiles.Clear(); foreach (Decoration d in decorations) { if (AODGameLibrary.Helpers.RandomHelper.WithinRange(d.Position, GameWorld.CurrentStage.Player.Position, GameConsts.GameViewDistance) || d.Far) { d.Update(gameTime); if (d.UnitState == UnitState.dead) { removingDecorations.Add(d);//收集要被移除的单位 } } } #endregion #region 回收多余的单位 foreach (Decoration d in removingDecorations) { if (d != null) { decorations.Remove(d); } } #endregion #region 更新导弹 removingMissiles.Clear(); foreach (Missile m in missiles) { if (m != null) { m.Update(gameTime); if (m.UnitState == UnitState.dead) { removingMissiles.Add(m); } } } foreach (Missile m in removingMissiles) { if (m != null) { missiles.Remove(m); } } #endregion #region 更新LOOT { removingLoots.Clear(); foreach (LootItem loot in lootItems) { if (AODGameLibrary.Helpers.RandomHelper.WithinRange(loot.Position, GameWorld.CurrentStage.Player.Position, GameConsts.GameViewDistance)) { loot.Update(gameTime); if (loot.UnitState == UnitState.dead) { removingLoots.Add(loot); } } } foreach (LootItem loot in removingLoots) { if (loot != null) { lootItems.Remove(loot); } } if (lootItems.Count > GameConsts.MaxLootNum) { lootItems.Remove(lootItems[0]); } } #endregion #region 更新弹药 removingBullets.Clear(); //终于。。不再慢了。。。 foreach (Bullet bullet in bullets) { if (bullet != null) { bullet.Update(gameTime); if (bullet.IsDead) { removingBullets.Add(bullet); } } } foreach (Bullet bullet in removingBullets) { if (bullet != null) { bullets.Remove(bullet); } } #endregion #region 单位间碰撞检测 VioableUnit a; VioableUnit b; for (int m = 0; m < boundingCollection.Count; m++) { a = boundingCollection[m]; if (a.Dead) { continue; } for (int n = m + 1; n < boundingCollection.Count; n++) { b = boundingCollection[n]; if (b.Dead) { continue; } if (b != null && a != b) { bool ts = b.Heavy || a.Heavy; if (a.Bounding && b.Bounding && (AODGameLibrary.Helpers.RandomHelper.WithinRange(a.Position, b.Position, GameConsts.BoundingDistance) || ts)) { if (Collision.IsCollided(a, b)) { if ((!a.Heavy && !b.Heavy) || (a.Heavy && b.Heavy && a is Unit && b is Unit)) { //float t = Vector3.Dot(a.Thrust, Vector3.Normalize(b.position - a.position));//推力在两单位中心线的投影 //if (t > 0) // //a.GetThrust(-1 * t * Vector3.Normalize(b.position - a.position)); // a.Thrust = Vector3.Zero; //float x = Vector3.Dot(a.velocity, Vector3.Normalize(b.position - a.position));//速度在两单位中心线的投影 //if (x > 0) // a.GetThrust(-2f * x * Vector3.Normalize(b.position - a.position) * a.mass); if (a.collided == false && b.collided == false) { if (a.Position != b.Position) { { float s1 = Vector3.Dot(a.Velocity, Vector3.Normalize(b.Position - a.Position)); float s2 = Vector3.Dot(b.Velocity, Vector3.Normalize(a.Position - b.Position)); if (s1 > 0) { a.GetImpulse(-1 * Vector3.Normalize(b.Position - a.Position) * s1 * a.Mass); a.GetImpulse(Vector3.Normalize(a.Position - b.Position) * s2 * b.Mass); } } { float s1 = Vector3.Dot(b.Velocity, Vector3.Normalize(a.Position - b.Position)); float s2 = Vector3.Dot(a.Velocity, Vector3.Normalize(b.Position - a.Position)); if (s1 > 0) { b.GetImpulse(-1 * Vector3.Normalize(a.Position - b.Position) * s1 * b.Mass); b.GetImpulse(Vector3.Normalize(b.Position - a.Position) * s2 * a.Mass); } } } } if (a.Position != b.Position) { a.GetImpulse(-1 * Vector3.Normalize(b.Position - a.Position) * a.FrictionForce * elapsedTime); b.GetImpulse(-1 * Vector3.Normalize(a.Position - b.Position) * b.FrictionForce * elapsedTime); } else { a.GetImpulse(Vector3.Left * a.FrictionForce * elapsedTime); b.GetImpulse(Vector3.Right * b.FrictionForce * elapsedTime); } a.collided = true; b.collided = true; } else { VioableUnit l = null; VioableUnit h = null; if (a.Heavy != b.Heavy) { if (b.Heavy) { h = b; l = a; } else { h = a; l = b; } } else { if (b is Decoration && !(a is Decoration)) { h = b; l = a; } if (a is Decoration && !(b is Decoration)) { h = a; l = b; } } if (l != null && h != null) { if (l.Position != h.Position) { float t = Vector3.Dot(l.Thrust, Vector3.Normalize(h.Position - l.Position));//推力在两单位中心线的投影 if (t > 0) { // a.GetThrust(-1 * t * Vector3.Normalize(b.position - a.position)); l.Thrust = Vector3.Zero; } float x = Vector3.Dot(l.Velocity, Vector3.Normalize(h.Position - l.Position));//速度在两单位中心线的投影 if (x > 0) { l.GetImpulse(-1 * x * Vector3.Normalize(h.Position - l.Position) * l.Mass); } l.GetImpulse(-1 * Vector3.Normalize(h.Position - l.Position) * l.FrictionForce * elapsedTime); //if (a.Thrust != Vector3.Zero) // if (Collision.IsCollided(b, new Ray(a.position, Vector3.Normalize(a.Thrust)))) // a.Thrust = Vector3.Zero; //if (a.velocity != Vector3.Zero) // if (Collision.IsCollided(b, new Ray(a.position, Vector3.Normalize(a.velocity)))) // a.velocity *= -1.1f; } } else { l.GetThrust(-1 * l.Velocity * Vector3.Forward * l.Mass / elapsedTime); } } } } } } } #endregion #region 更新位置 foreach (Unit u in units) { if (u != null) { u.UpdateLocation(gameTime); } } foreach (Decoration d in decorations) { if (AODGameLibrary.Helpers.RandomHelper.WithinRange(d.Position, GameWorld.CurrentStage.Player.Position, GameConsts.GameViewDistance) || d.Far) { d.UpdateLocation(gameTime); } } foreach (Missile m in missiles) { if (m != null) { m.UpdateLocation(gameTime); } } foreach (LootItem loot in lootItems) { if (AODGameLibrary.Helpers.RandomHelper.WithinRange(loot.Position, GameWorld.CurrentStage.Player.Position, GameConsts.GameViewDistance)) { loot.UpdateLocation(gameTime); } } for (int i = 0; i < units.Count; i++) { Unit u = units[i]; if (u != null) { u.UpdateWeapons(gameTime); } } #endregion base.Update(gameTime); }
/// <summary> /// 将弹药和附近的单位单位做碰撞检测,对是敌方且发生碰撞的最近单位造成伤害且弹药消失 /// </summary> /// <param name="unit">做碰撞检测的目标</param> public void CheckCollision(List <VioableUnit> units) { VioableUnit hitingUnit = null; float hitingUnitRange = 0; Vector3 hittingPoint = Vector3.Zero; Vector3? v1; foreach (VioableUnit unit in units) { if (unit != null) { if (Vector3.Distance(unit.Position, this.position) <= GameConsts.BulletCheckingRange) { //if (weapon.isInstant == false) //{ // if (bulletOver == false) // { // if (Collision.IsCollided(unit, this) && unit.Group != Group && unit.Dead != true) // { // Damage result; // result = new Damage(weapon, num); // unit.GetDamage(result); // Hit(); // } // } //} //else{} v1 = Collision.IsCollided(unit, this); if (v1 != null && unit.Group != Group && unit.UnitState != UnitState.dead) { if (hitingUnit != null) { float k = Vector3.Dot(v1.Value - this.positionl, this.Face); if (k < hitingUnitRange) { hitingUnitRange = k; hitingUnit = unit; hittingPoint = v1.Value; } } else { hitingUnit = unit; hitingUnitRange = Vector3.Dot(unit.Position - this.positionl, this.Face); hittingPoint = v1.Value; } } } } } if (hitingUnit != null) { Damage result; result = new Damage(weapon, num); hitingUnit.GetDamage(result); //position = (positionl + position) / 2; if (hitingUnit.Model != null && position0 != position) { Ray br = new Ray(position0, Vector3.Normalize(position - position0)); Vector3?v = hittingPoint; if (v != null) { position = v.Value; positionl = v.Value; } } Hit(); } }