public override void Remove(Item item) { if (_cluster.ContainsKey(item.Id)) { PhysicsUnit cluster = _cluster[item.Id]; // Im Falle von Kollisionen aus der Liste entfernen if (cluster.CanCollide) { _collidables.Remove(cluster); } cluster.Dispose(); _cluster.Remove(item.Id); } }
public override void Insert(Item item) { // Relevante Elemente finden if ((item.ContainsProperty <WalkingProperty>() || item.ContainsProperty <CollidableProperty>() || item.ContainsProperty <CarrierProperty>() || item.ContainsProperty <PortableProperty>()) && !_cluster.ContainsKey(item.Id)) { var cluster = new PhysicsUnit(item, _cluster); _cluster.Add(item.Id, cluster); // Im Falle von Kollisionen in die Liste einsortieren if (cluster.CanCollide) { _collidables.Add(cluster); } } }
/// <summary> /// Das tragende Teil wurde geändert - Abhängigkeiten neu prüfen /// </summary> /// <param name="item"></param> /// <param name="newValue"></param> private void carrier_OnCarrierLoadChanged(Item item, PortableProperty newValue) { if (newValue != null) { int id = newValue.Item.Id; if (!items.ContainsKey(id)) { throw new IndexOutOfRangeException("Item does not exist"); } load = items[id]; } else { load = null; } Recalc(); }
/// <summary> /// Das tragende Teil wurde geändert - Abhängigkeiten neu prüfen /// </summary> /// <param name="item"></param> /// <param name="newValue"></param> private void carrier_OnCarrierLoadChanged(Item item, PortableProperty newValue) { if (newValue != null) { int id = newValue.Item.Id; if (!items.ContainsKey(id)) throw new IndexOutOfRangeException("Item does not exist"); load = items[id]; } else load = null; Recalc(); }
/// <summary> /// Kümmert sich um eine Kollision zweier Elemente. /// </summary> /// <param name="cluster"></param> public void Collide(PhysicsUnit cluster) { float max = Radius + cluster.Radius; float dist = (Position - cluster.Position).Length(); // Auflösung if (!IsFixed || !cluster.IsFixed) { // Richtungsvektor Item1->Item2 Vector3 direction = (cluster.Position - Position); // Fallback 1, falls direction == [0,0]: // vorherige Positionen zum Diff verwenden if (direction.LengthSquared() < Vector3.EPS_MIN) direction = ((cluster.Position - cluster.AppliedVelocity) - (Position - AppliedVelocity)); // Fallback 2, falls direction == [0,0]; // fixe Achse if (direction.LengthSquared() < Vector3.EPS_MIN) direction = new Vector3(1, 0, 0); // Richtungsvektor Normalisieren direction = direction.Normalize(); float diff = max - dist; var bounce = new Vector3(); // Item1 fixed, item2 not fixed if (IsFixed) { // Nur Item2 bewegen // Ignore Result, da eh nix zu retten ist cluster.SetPosition(cluster.Position + (direction*diff), ref bounce, true); } // Item1 not fixed, item2 fixed else if (cluster.IsFixed) { // Nur Item1 bewegen // Result unwichtig, da eh nichts zu retten ist SetPosition(Position + (direction.InvertXYZ()*diff), ref bounce, true); } else { // Über Masse auflösen float totalmass = AppliedMass + cluster.AppliedMass; float spanItem1 = diff*(cluster.AppliedMass/totalmass); float spanItem2 = diff*(AppliedMass/totalmass); Vector3 diffItem1 = direction.InvertXYZ()*spanItem1; Vector3 diffItem2 = direction*spanItem2; // Apply // Im Falle eines Blocks wird der Bounce auf das andere Element übertragen. bounce = Vector3.Zero; if (SetPosition(Position + diffItem1, ref bounce, true) == PositionResult.Blocked) diffItem2 += bounce; // Im Falle eines Bounce beim zweiten Element wird der Bounce ein letztes mal an Element 1 weiter gegeben. bounce = Vector3.Zero; if (cluster.SetPosition(cluster.Position + diffItem2, ref bounce, true) == PositionResult.Blocked) SetPosition(Position + bounce, ref bounce, true); } } // Kollision melden if (collidable != null) collidable.CollideItem(cluster.Item); if (cluster.collidable != null) cluster.collidable.CollideItem(Item); }
private void KillUnit(PhysicsUnit unit) { // Remove Engine.RemoveItem(unit.Item); }
/// <summary> /// Kümmert sich um eine Kollision zweier Elemente. /// </summary> /// <param name="cluster"></param> public void Collide(PhysicsUnit cluster) { float max = Radius + cluster.Radius; float dist = (Position - cluster.Position).Length(); // Auflösung if (!IsFixed || !cluster.IsFixed) { // Richtungsvektor Item1->Item2 Vector3 direction = (cluster.Position - Position); // Fallback 1, falls direction == [0,0]: // vorherige Positionen zum Diff verwenden if (direction.LengthSquared() < Vector3.EPS_MIN) { direction = ((cluster.Position - cluster.AppliedVelocity) - (Position - AppliedVelocity)); } // Fallback 2, falls direction == [0,0]; // fixe Achse if (direction.LengthSquared() < Vector3.EPS_MIN) { direction = new Vector3(1, 0, 0); } // Richtungsvektor Normalisieren direction = direction.Normalize(); float diff = max - dist; var bounce = new Vector3(); // Item1 fixed, item2 not fixed if (IsFixed) { // Nur Item2 bewegen // Ignore Result, da eh nix zu retten ist cluster.SetPosition(cluster.Position + (direction * diff), ref bounce, true); } // Item1 not fixed, item2 fixed else if (cluster.IsFixed) { // Nur Item1 bewegen // Result unwichtig, da eh nichts zu retten ist SetPosition(Position + (direction.InvertXYZ() * diff), ref bounce, true); } else { // Über Masse auflösen float totalmass = AppliedMass + cluster.AppliedMass; float spanItem1 = diff * (cluster.AppliedMass / totalmass); float spanItem2 = diff * (AppliedMass / totalmass); Vector3 diffItem1 = direction.InvertXYZ() * spanItem1; Vector3 diffItem2 = direction * spanItem2; // Apply // Im Falle eines Blocks wird der Bounce auf das andere Element übertragen. bounce = Vector3.Zero; if (SetPosition(Position + diffItem1, ref bounce, true) == PositionResult.Blocked) { diffItem2 += bounce; } // Im Falle eines Bounce beim zweiten Element wird der Bounce ein letztes mal an Element 1 weiter gegeben. bounce = Vector3.Zero; if (cluster.SetPosition(cluster.Position + diffItem2, ref bounce, true) == PositionResult.Blocked) { SetPosition(Position + bounce, ref bounce, true); } } } // Kollision melden if (collidable != null) { collidable.CollideItem(cluster.Item); } if (cluster.collidable != null) { cluster.collidable.CollideItem(Item); } }