public void Remove(Rib rib) { if (times.ContainsKey(rib)) { rib.Collision.times.Remove(self); times.Remove(rib); } }
public Rib(Rib other) { speed = other.speed; pos0 = other.pos0; pos1 = other.pos1; time0 = other.time0; time1 = other.time1; sprite = other.sprite; }
public double GetTime(Rib rib) { double res; if (!times.TryGetValue(rib, out res)) { throw new KeyNotFoundException(string.Format("the rib {0} is not found", rib.Sprite.Id)); } return(res); }
public void Clip(List <Rib> ribs) { var radius = sprite.Radius; bool hit = false; double poshit = 0.0; if (speed.X < 0) { if (pos1.X < radius) { hit = true; poshit = radius; } } else if (pos1.X > U.WX - radius) { hit = true; poshit = U.WX - radius; } if (hit) { // clipped by X double thit = (poshit - pos0.X) / speed.X; Rib next = Split(thit); next.setSpeed(new Vec(-speed.X, speed.Y)); next.Clip(ribs); ribs.Add(next); hit = false; } if (speed.Y < 0) { if (pos1.Y < radius) { hit = true; poshit = radius; } } else if (pos1.Y > U.WY - radius) { hit = true; poshit = U.WY - radius; } if (hit) { double thit = (poshit - pos0.Y) / speed.Y; Rib next = Split(thit); next.setSpeed(new Vec(speed.X, -speed.Y)); next.Clip(ribs); ribs.Add(next); hit = false; } }
public Rib Split(double deltat) { Rib next = new Rib(this); next.pos0 = pos0.Add(speed.Scale(deltat)); next.pos1 = pos1; pos1 = next.pos0; next.time0 = time0 + deltat; next.time1 = time1; time1 = next.time0; return(next); }
public Rib GetFirstHit(out double time) { Rib rib = null; time = 0.0; foreach (KeyValuePair <Rib, double> kv in times) { if (rib == null || kv.Value < time) { rib = kv.Key; time = kv.Value; } } return(rib); }
public RibRect(Rib r) { var radius = r.Sprite.Radius; min = r.StartPos; max = r.EndPos; if (max.X < min.X) { var t = max.X; max.X = min.X; min.X = t; } if (max.Y < min.Y) { var t = max.Y; max.Y = min.Y; min.Y = t; } min.X -= radius; min.Y -= radius; max.X += radius; max.Y += radius; }
public bool CollidesWith(Rib rib, out double hittime) { // we are working in the reference frame of this.pos0, moving with the speed this.speed Vec ribpos = rib.pos0.Subtract(pos0); Vec ribspd = rib.speed.Subtract(speed); double time = time0; if (time0 < rib.time0) { // correct the position time = rib.time0; ribpos = ribpos.Subtract(speed.Scale(time - time0)); } else if (time0 > rib.time0) { ribpos = ribpos.Add(rib.speed.Scale(time - rib.time0)); } var spd2 = ribspd.Length2; if (spd2 <= 0.00001) { hittime = 0; return(false); } // Let's only find the closest position // Xclose = X - (X*V)*V / (V*V) // Tclose = -(X*V) / (V*V) hittime = -ribpos.Scalar(ribspd) / spd2; if (hittime < time || hittime > time1 || hittime > rib.time1) { return(false); } return(true); }
public static int CompareByTime(Rib a, Rib b) { return(a.time0.CompareTo(b.time0)); }
public int CompareTo(Rib r) { return(pos0.X < r.pos0.X ? -1 : (pos0.X > r.pos0.X ? 1 : 0)); }
private static bool matchRibNull(Rib rib) { return(rib == null || rib.Sprite == null); }
public void Run(double dt) { List <Collision> collisions = new List <Collision>(); foreach (Rib rib in ribs) { if (rib.Collision.Fill(ribs)) { collisions.Add(rib.Collision); } } while (collisions.Count > 0) { U.show(string.Format("Total {0} collisions", collisions.Count)); // run through all collisions Collision first = null; double firsttime = 0.0; Rib firstrib = null; foreach (var coll in collisions) { if (coll == null || coll.IsEmpty || coll.SelfRib == null) { continue; } double time; Rib rib = coll.GetFirstHit(out time); if (rib == null) { throw new Exception("the collection must have a hit"); } if (first == null || time < firsttime) { first = coll; firsttime = time; firstrib = rib; } } if (first == null) { break; } U.show(string.Format("first collision time found: {0}", firsttime)); List <Rib> moreribs = applyCollision(first, firstrib, dt); if (moreribs != null) { // we have more ribs foreach (Rib rib in moreribs) { if (rib.Collision.Fill(ribs)) { collisions.Add(rib.Collision); } } ribs.AddRange(moreribs); } } // finally, cleanup ribs ribs.RemoveAll(rib => rib == null || rib.Sprite == null); ribs.Sort(compareRibsByEndTime); }
/* * private static int compareRibRectsByX(RibRect a, RibRect b) { * return a.min.X.CompareTo(b.min.X); * } */ private static int compareRibsByEndTime(Rib a, Rib b) { return(a.EndTime.CompareTo(b.EndTime)); }
public Collision(Rib rib) { self = rib; rect = new RibRect(rib); times = new Dictionary <Rib, double>(); }
public void Update(Rib rib) { Position = rib.EndPos; Speed = rib.Speed; alpha += omega * rib.DeltaTime; }