public void RemoveAt(int index, int count = 1) { if (index < 0 || index > InnerList.Count || count < 0 || count > InnerList.Count) { throw new ArgumentException("Bad arguments!"); } var afterRemoved = FindAt(index + count); var beforeRemoved = index == 0 ? FindLast() : FindAt(index - 1); beforeRemoved.Next = afterRemoved; if (index + count > Count) { Head = afterRemoved; var range1 = Count - index; InnerList.RemoveRange(index, range1); InnerList.RemoveRange(0, count - range1); } else { if (index == 0) { Head = count == Count ? null : FindAt(count); } InnerList.RemoveRange(index, count); } }
internal void ShowInfo() { CircleListNode <VisiBordPoint> checkCur = this.visiBorder.First; for (int i = 0; i < this.visiBorder.Length; i++) { Console.WriteLine(checkCur.value.index); checkCur = checkCur.next; } }
public void ApplyShelterObj(Rader rader, IShelterObj obj) { Matrix worldMatrix = obj.WorldTrans; CircleList <BorderPoint> border = obj.BorderData; CircleListNode <BorderPoint> lastB = border.First.pre; Vector2 pInRader = rader.TranslateToRaderSpace(Vector2.Transform(ConvertHelper.PointToVector2(lastB.value.p), worldMatrix)); int lastIndex = IndexOf(pInRader.X); float lastDepth = pInRader.Y; CircleListNode <BorderPoint> cur = border.First; for (int i = 0; i < border.Length; i++) { pInRader = rader.TranslateToRaderSpace(Vector2.Transform(ConvertHelper.PointToVector2(cur.value.p), worldMatrix)); int curIndex = IndexOf(pInRader.X); float curDepth = pInRader.Y; if (pInRader.X >= -1.1f && pInRader.X <= 1.3f) { //this[pInRader.X] = Math.Min( this[pInRader.X], pInRader.Y ); SetValueAtIndex(curIndex, pInRader.Y, obj, i, cur.value.p); if (curIndex - lastIndex > 1) { int overIndex = lastIndex + 1; while (overIndex != curIndex) { float lerp = MathHelper.Lerp(lastDepth, curDepth, (curIndex - overIndex) / (curIndex - lastIndex)); SetValueAtIndex(overIndex, lerp, obj, i, cur.value.p); overIndex++; } } else if (curIndex - lastIndex < -1) { int overIndex = lastIndex - 1; while (overIndex != curIndex) { float lerp = MathHelper.Lerp(lastDepth, curDepth, (curIndex - overIndex) / (curIndex - lastIndex)); SetValueAtIndex(overIndex, lerp, obj, i, cur.value.p); overIndex--; } } } lastIndex = curIndex; lastDepth = curDepth; cur = cur.next; } }
private void AddFirst(Circle value) { var newEl = new CircleListNode(value); if (Count == 0) { newEl.Next = newEl; Head = newEl; } else { newEl.Next = Head; FindLast().Next = newEl; Head = newEl; } InnerList.Insert(0, value); }
private static ObjVisiBorder CalNonShelterVisiBorder(IHasBorderObj obj, Rader rader) { CircleListNode <BorderPoint> curNode = obj.BorderData.First; CircleList <BordPoint> points = new CircleList <BordPoint>(); for (int i = 0; i < obj.BorderData.Length; i++) { if (rader.PointInRader(Vector2.Transform(ConvertHelper.PointToVector2(curNode.value.p), obj.WorldTrans))) { points.AddLast(new BordPoint(i, curNode.value.p)); } curNode = curNode.next; } if (points.Length != 0) { return(new ObjVisiBorder(obj, points)); } else { return(null); } }
private Point[] SurroundQueue(Point point, Point prePoint) { CircleList <Point> result = SurroundPoint.Clone(); result.ForEach(delegate(ref Point p) { p = new Point(p.X + point.X, p.Y + point.Y); }); CircleListNode <Point> find = result.FindFirst(delegate(Point p) { if (p == prePoint) { return(true); } else { return(false); } }); return(result.ToArray(find, true)); }
/// <summary> /// 检测是否在边界矩形外 /// </summary> /// <param name="BorderRect"></param> /// <returns></returns> public CollisionResult CheckOutBorder(Rectanglef BorderRect) { if (!this.mSupportIntersectDect) { throw new Exception("the sprite doesn't support IntersectDect!"); } UpdateTransformBounding(); CollisionResult result = new CollisionResult(); Rectanglef screenRect = BorderRect; if (!this.mBounding.Intersects(screenRect)) { result.IsCollided = false; return(result); } int widthA = this.mTexture.Width; int heightA = this.mTexture.Height; // Calculate a matrix which transforms from A's local space into // world space Matrix transformAToWorld = mTransform; Vector2 stepX = Vector2.TransformNormal(Vector2.UnitX, transformAToWorld); Vector2 stepY = Vector2.TransformNormal(Vector2.UnitY, transformAToWorld); Vector2 oriPosInWorld = Vector2.Transform(Vector2.Zero, transformAToWorld); CircleList <BorderPoint> list = mBorder.BorderCircle; CircleListNode <BorderPoint> cur = list.First; bool justStart = true; bool find = false; CircleListNode <BorderPoint> firstNode = cur; int length = 0; #region 找出第一个相交点和该连续相交线的长度 for (int i = 0; i < list.Length; i++) { Point bordPointA = cur.value.p; if (PointOutBorder(oriPosInWorld, stepX, stepY, bordPointA, screenRect)) { if (!justStart) { if (!find) { find = true; firstNode = cur; } else { length++; } } else { CircleListNode <BorderPoint> temp = cur.pre; int leftLength = list.Length; while (PointOutBorder(oriPosInWorld, stepX, stepY, temp.value.p, screenRect) && leftLength >= 0) { temp = temp.pre; leftLength--; } cur = temp; i--; justStart = false; } } else { justStart = false; if (find) { break; } } cur = cur.next; } #endregion if (find) { cur = firstNode; for (int i = 0; i < Math.Round((float)length / 2); i++) { cur = cur.next; } Point bordPointA = cur.value.p; result.IsCollided = true; Vector2 InterPos = Vector2.Transform(new Vector2(bordPointA.X, bordPointA.Y), mTransform); result.NormalVector = Vector2.Transform(mBorder.GetNormalVector(cur, mAverageSum), mTransform) - Vector2.Transform(Vector2.Zero, mTransform); result.NormalVector.Normalize(); result.InterPos = InterPos; return(result); } // No intersection found result.IsCollided = false; return(result); }
/// <summary> /// Determines if there is overlap of the non-transparent pixels between two /// sprites. /// 检查两个精灵是否发生碰撞 /// </summary> /// <returns>True if non-transparent pixels overlap; false otherwise</returns> public static CollisionResult IntersectPixels(Sprite spriteA, Sprite spriteB) { if (!spriteA.mSupportIntersectDect || !spriteB.mSupportIntersectDect) { throw new Exception("At lest one of the two sprite doesn't support IntersectDect!"); } spriteA.UpdateTransformBounding(); spriteB.UpdateTransformBounding(); CollisionResult result = new CollisionResult(); if (!spriteA.mBounding.Intersects(spriteB.mBounding)) { result.IsCollided = false; return(result); } int widthA = spriteA.mTexture.Width; int heightA = spriteA.mTexture.Height; int widthB = spriteB.mTexture.Width; int heightB = spriteB.mTexture.Height; // Calculate a matrix which transforms from A's local space into // world space and then into B's local space Matrix transformAToB = spriteA.mTransform * Matrix.Invert(spriteB.mTransform); // When a point moves in A's local space, it moves in B's local space with a // fixed direction and distance proportional to the movement in A. // This algorithm steps through A one pixel at a time along A's X and Y axes // Calculate the analogous steps in B: Vector2 stepX = Vector2.TransformNormal(Vector2.UnitX, transformAToB); Vector2 stepY = Vector2.TransformNormal(Vector2.UnitY, transformAToB); // Calculate the top left corner of A in B's local space // This variable will be reused to keep track of the start of each row Vector2 oriPosInB = Vector2.Transform(Vector2.Zero, transformAToB); CircleList <BorderPoint> list = spriteA.mBorder.BorderCircle; CircleListNode <BorderPoint> cur = list.First; bool justStart = true; bool find = false; CircleListNode <BorderPoint> firstNode = cur; int length = 0; #region 找出第一个相交点和该连续相交线的长度 for (int i = 0; i < list.Length; i++) { Point bordPointA = cur.value.p; if (SpriteBBlockAtPos(spriteB, oriPosInB, stepX, stepY, bordPointA)) { if (!justStart) { if (!find) { find = true; firstNode = cur; } else { length++; } } else { CircleListNode <BorderPoint> temp = cur.pre; while (SpriteBBlockAtPos(spriteB, oriPosInB, stepX, stepY, temp.value.p) && temp != cur) { temp = temp.pre; } cur = temp; i--; justStart = false; } } else { justStart = false; if (find) { break; } } cur = cur.next; } #endregion if (find) { cur = firstNode; for (int i = 0; i < Math.Round((float)length / 2); i++) { cur = cur.next; } Point bordPointA = cur.value.p; result.IsCollided = true; Vector2 InterPos = Vector2.Transform(new Vector2(bordPointA.X, bordPointA.Y), spriteA.mTransform); result.NormalVector = Vector2.Transform(spriteA.mBorder.GetNormalVector(cur, spriteA.mAverageSum), spriteA.mTransform) - Vector2.Transform(Vector2.Zero, spriteA.mTransform); result.NormalVector.Normalize(); result.InterPos = InterPos; return(result); } // No intersection found result.IsCollided = false; return(result); }
//public ObjVisiBorder ( IGameObj obj ) //{ // this.obj = obj; // this.visiBorder = new CircleList<BordPoint>(); //} internal bool Combine(CircleList <VisiBordPoint> borderB) { CircleListNode <VisiBordPoint> curA = this.visiBorder.First; int iA = 0; bool borderUpdated = false; if (curA.value.index > borderB.First.value.index) { this.visiBorder.AddFirst(borderB.First.value); curA = this.visiBorder.First; borderUpdated = true; } bool objborderChanged = false; foreach (VisiBordPoint pB in borderB) { while (curA.value.index < pB.index && iA < this.visiBorder.Length) { curA = curA.next; iA++; } if (curA.value.index == pB.index) { if (curA.value.p != pB.p) { objborderChanged = true; break; } } else { borderUpdated = true; this.visiBorder.InsertAfter(pB, curA.pre); curA = curA.pre; } } if (objborderChanged) { this.visiBorder = borderB; } #region Check Code //CircleListNode<BordPoint> checkCur = this.visiBorder.First; //int lastIndex = -1; //for (int i = 0; i < this.visiBorder.Length; i++) //{ // if (checkCur.value.index <= lastIndex) // { // Console.WriteLine( "this.visiBorder :" ); // this.ShowInfo(); // Console.WriteLine(); // Console.WriteLine( "borderB :" ); // foreach (BordPoint p in borderB) // { // Console.WriteLine( p.index ); // } // throw new Exception(); // } // lastIndex = checkCur.value.index; // checkCur = checkCur.next; //} #endregion return(borderUpdated); }
public void BuildConvexHall(CircleList <BordPoint> border, float minOptimizeDest) { #region 获得原始凸包 if (border.Length < 2) { return; } Stack <BordPoint> stack = new Stack <BordPoint>(); CircleListNode <BordPoint> cur = border.First; stack.Push(cur.value); cur = cur.next; stack.Push(cur.value); cur = cur.next; for (int i = 2; i < border.Length; i++) { BordPoint p1 = stack.Pop(); BordPoint p0 = stack.Peek(); BordPoint p2 = cur.value; if (CountWise(p1, p0, p2)) { stack.Push(p1); stack.Push(p2); cur = cur.next; } else { if (stack.Count == 1) { stack.Push(p2); cur = cur.next; } else { i--; } } } List <BordPoint> templist = new List <BordPoint>(stack); if (templist.Count > 3) { if (!CountWise(templist[0], templist[1], templist[templist.Count - 1])) { templist.RemoveAt(0); } if (!CountWise(templist[templist.Count - 1], templist[0], templist[templist.Count - 2])) { templist.RemoveAt(templist.Count - 1); } } else if (templist.Count == 3) { if (!CountWise(templist[0], templist[1], templist[templist.Count - 1])) { templist.RemoveAt(0); BordPoint temp = templist[0]; templist[0] = templist[1]; templist[1] = temp; } } #endregion #region 对凸包进行化简 if (templist.Count > 3) { for (int i = 0; i < templist.Count; i++) { Vector2 p1 = ConvertHelper.PointToVector2(templist[i].p); Vector2 p2 = ConvertHelper.PointToVector2(templist[(i + 1) % templist.Count].p); Vector2 p3 = ConvertHelper.PointToVector2(templist[(i + 2) % templist.Count].p); Vector2 p4 = ConvertHelper.PointToVector2(templist[(i + 3) % templist.Count].p); if (Vector2.Distance(p2, p3) > minOptimizeDest) { continue; } Vector2 seg1 = p2 - p1; Vector2 seg2 = p4 - p3; float ang = (float)Math.Acos(Vector2.Dot(seg1, seg2) / (seg1.Length() * seg2.Length())); if (ang > MathHelper.PiOver2) { continue; } Line line1 = new Line(p1, seg1); Line line2 = new Line(p4, seg2); Vector2 interPoint; if (!MathTools.InterPoint(line1, line2, out interPoint)) { continue; } templist[(i + 1) % templist.Count] = new BordPoint(templist[(i + 1) % templist.Count].index, ConvertHelper.Vector2ToPoint(interPoint)); templist.RemoveAt((i + 2) % templist.Count); i--; } } #endregion convexPoints = templist; }