public VergeTileGround ( VergeTileData data, Rectangle screenViewRect, Rectanglef mapSize ) { gridWidthSum = data.gridWidth; gridHeightSum = data.gridHeight; this.screenViewRect = screenViewRect; this.mapSize = mapSize; float gridScaleInWidth = mapSize.Width / (float)gridWidthSum; float gridScaleInHeight = mapSize.Height / (float)gridHeightSum; gridScale = Math.Max( gridScaleInWidth, gridScaleInHeight ); vertexTexIndexs = new int[data.vertexTexIndexs.Length]; data.vertexTexIndexs.CopyTo( vertexTexIndexs, 0 ); gridTexIndexs = new int[data.gridTexIndexs.Length]; data.gridTexIndexs.CopyTo( gridTexIndexs, 0 ); InitialTexList( data ); InitialGridTexData(); CreateSpriteBatches(); sourceWidth = gridTexData[0][0].sourceRect.Width; BaseGame.Device.DeviceReset += new EventHandler( Device_DeviceReset ); }
public NavigateMap CalNavigationMap ( NaviMapConsiderObj selectFun, Rectanglef mapBorder, float spaceForTank ) { List<EyeableBorderObjInfo> eyeableInfos = new List<EyeableBorderObjInfo>(); foreach (KeyValuePair<IHasBorderObj, EyeableBorderObjInfo> pair in memoryObjs) { if (selectFun( pair.Value )) { eyeableInfos.Add( pair.Value ); } } return new NavigateMap( eyeableInfos.ToArray(), mapBorder, spaceForTank ); }
/// <summary> /// 判断两个矩形是否有重叠部分 /// </summary> /// <param name="rectB"></param> /// <returns></returns> public bool Intersects ( Rectanglef rectB ) { if (rectB.X < this.X + this.Width && rectB.X + rectB.Width > this.X && rectB.Y + rectB.Height > this.Y && rectB.Y < this.Y + this.Height || rectB.X + rectB.Width > this.X && rectB.X < this.X + this.Width && rectB.Y + rectB.Height > this.Y && rectB.Y < this.Y + this.Height) return true; else return false; }
/// <summary> /// 在逻辑坐标中绘制矩形 /// </summary> /// <param name="rect">要绘制的矩形</param> /// <param name="borderWidth">矩形的边线的宽度,以像素为单位</param> /// <param name="color">颜色</param> /// <param name="layerDepth">深度,0表示最表层,1表示最深层</param> /// <param name="blendMode">混合模式</param> public void DrawRectangle ( Rectanglef rect, float borderWidth, Color color, float layerDepth, SpriteBlendMode blendMode ) { DrawLine( new Vector2( rect.Left, rect.Top ), new Vector2( rect.Right, rect.Top ), borderWidth, color, layerDepth, blendMode ); DrawLine( new Vector2( rect.Left, rect.Top ), new Vector2( rect.Left, rect.Bottom ), borderWidth, color, layerDepth, blendMode ); DrawLine( new Vector2( rect.Right, rect.Top ), new Vector2( rect.Right, rect.Bottom ), borderWidth, color, layerDepth, blendMode ); DrawLine( new Vector2( rect.Left, rect.Bottom ), new Vector2( rect.Right, rect.Bottom ), borderWidth, color, layerDepth, blendMode ); }
/// <summary> /// 在逻辑坐标中绘制矩形 /// </summary> /// <param name="rect">要绘制的矩形</param> /// <param name="borderWidth">矩形的边线的宽度,以像素为单位</param> /// <param name="color">颜色</param> /// <param name="layerDepth">深度,0表示最表层,1表示最深层</param> public void DrawRectangle ( Rectanglef rect, float borderWidth, Color color, float layerDepth ) { DrawRectangle( rect, borderWidth, color, layerDepth, SpriteBlendMode.AlphaBlend ); }
/// <summary> /// 在调用该函数之前,确保当前帧内调用过UpdateBoundRect()函数。 /// </summary> /// <param name="objBoundBox"></param> /// <returns></returns> public bool InRaderRect ( Rectanglef objBoundBox ) { return bouBox.Intersects( objBoundBox ); }
private void UpdateBoundRect () { float len = r / (float)Math.Cos( ang ); Vector2 CenterP = pos + N * len; Vector2 min = Vector2.Min( Vector2.Min( Vector2.Min( pos, LeftP ), RightP ), CenterP ); Vector2 max = Vector2.Max( Vector2.Max( Vector2.Max( pos, LeftP ), RightP ), CenterP ); bouBox = new Rectanglef( min.X, min.Y, max.X - min.X, max.Y - min.Y ); }
/// <summary> /// /// </summary> /// <param name="borderRect">边界矩形</param> public BorderColMethod( Rectanglef borderRect ) { this.borderRect = borderRect; }
/// <summary> /// 判断两个Rectanglef实例是否相等 /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { Rectanglef b = (Rectanglef)obj; return(this.X == b.X && this.Y == b.Y && this.Width == b.Width && this.Height == b.Height); }
/// <summary> /// 将Rectanglef类型转换为Rectangle类型,进行取整操作 /// </summary> /// <param name="rect"></param> /// <returns></returns> public static Rectangle RectanglefToRectangle ( Rectanglef rect ) { return new Rectangle( (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height ); }
/// <summary> /// /// </summary> /// <param name="borderRect">边界矩形</param> public BorderColChecker( Rectanglef borderRect ) { method = new BorderColMethod( borderRect ); }
public void BuildMap ( EyeableBorderObjInfo[] objInfos, Rectanglef mapBorder, float spaceForTank ) { #region 对每一个BorderObj生成逻辑坐标上的凸包点集,并向外扩展 borderLines = new List<Segment>(); convexs = new List<GuardConvex>(); foreach (EyeableBorderObjInfo obj in objInfos) { if (obj.ConvexHall == null || obj.IsDisappeared || obj.ConvexHall.Points == null) continue; Matrix matrix = obj.EyeableInfo.CurTransMatrix; GraphPoint<NaviPoint>[] convexHall; List<VisiBordPoint> bordPoints = obj.ConvexHall.Points; if (bordPoints.Count > 2) { List<GraphPoint<NaviPoint>> list = new List<GraphPoint<NaviPoint>>(); for (int i = 0; i < bordPoints.Count; i++) { Vector2 lastPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[i - 1 < 0 ? bordPoints.Count - 1 : i - 1].p ), matrix ); Vector2 curPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[i].p ), matrix ); Vector2 nextPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[(i + 1) % bordPoints.Count].p ), matrix ); Vector2 v1 = curPos - lastPos; Vector2 v2 = curPos - nextPos; float ang = MathTools.AngBetweenVectors( v1, v2 ); if (ang >= MathHelper.PiOver2) { float halfDes = (float)(spaceForTank / Math.Sin( ang )); Vector2 delta = halfDes * Vector2.Normalize( v1 ) + halfDes * Vector2.Normalize( v2 ); list.Add( new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[i].index, curPos + delta ), new List<GraphPath<NaviPoint>>() ) ); } else { v1.Normalize(); v2.Normalize(); Vector2 cenV = Vector2.Normalize( v1 + v2 ); Vector2 vertiV = new Vector2( cenV.Y, -cenV.X ); float ang2 = MathHelper.PiOver4 - 0.25f * ang; float vertiL = (float)(spaceForTank * Math.Tan( ang2 )); list.Add( new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[i].index, curPos + spaceForTank * cenV + vertiL * vertiV ), new List<GraphPath<NaviPoint>>() ) ); list.Add( new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[i].index, curPos + spaceForTank * cenV - vertiL * vertiV ), new List<GraphPath<NaviPoint>>() ) ); } // 添加borderLine borderLines.Add( new Segment( curPos, nextPos ) ); } convexHall = list.ToArray(); convexs.Add( new GuardConvex( convexHall ) ); } else if (bordPoints.Count == 2) { convexHall = new GraphPoint<NaviPoint>[4]; Vector2 startPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[0].p ), matrix ); Vector2 endPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[1].p ), matrix ); Vector2 dir = endPos - startPos; dir.Normalize(); Vector2 normal = new Vector2( dir.Y, -dir.X ); convexHall[0] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[0].index, startPos - dir * spaceForTank ), new List<GraphPath<NaviPoint>>() ); convexHall[1] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[0].index, startPos + spaceForTank * normal ), new List<GraphPath<NaviPoint>>() ); convexHall[2] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[1].index, endPos + spaceForTank * normal ), new List<GraphPath<NaviPoint>>() ); convexHall[3] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[1].index, endPos + dir * spaceForTank ), new List<GraphPath<NaviPoint>>() ); //if (float.IsNaN( convexHall[0].value.Pos.X ) || float.IsNaN( convexHall[1].value.Pos.X )) //{ //} // 添加borderLine borderLines.Add( new Segment( startPos, endPos ) ); convexs.Add( new GuardConvex( convexHall ) ); } } #endregion #region 得到警戒线 guardLines = new List<Segment>(); foreach (GuardConvex convex in convexs) { for (int i = 0; i < convex.points.Length; i++) { guardLines.Add( new Segment( convex[i].value.Pos, convex[(i + 1) % convex.Length].value.Pos ) ); //if (float.IsNaN( convex[i].value.Pos.X )) //{ //} } } mapBorder = new Rectanglef( mapBorder.X + spaceForTank, mapBorder.Y + spaceForTank, mapBorder.Width - 2 * spaceForTank, mapBorder.Height - 2 * spaceForTank ); guardLines.Add( new Segment( mapBorder.UpLeft, mapBorder.UpRight ) ); guardLines.Add( new Segment( mapBorder.UpRight, mapBorder.DownRight ) ); guardLines.Add( new Segment( mapBorder.DownRight, mapBorder.DownLeft ) ); guardLines.Add( new Segment( mapBorder.DownLeft, mapBorder.UpLeft ) ); #endregion #region 检查凸包内部连线是否和警戒线相交,如不相交则连接该连线并计算权值 foreach (GuardConvex convex in convexs) { for (int i = 0; i < convex.Length; i++) { // 检查连线是否超出边界 if (!mapBorder.Contains( convex[i].value.Pos )) continue; Segment link = new Segment( convex[i].value.Pos, convex[(i + 1) % convex.Length].value.Pos ); bool isCross = false; foreach (Segment guardLine in guardLines) { if (link.Equals( guardLine )) continue; if (Segment.IsCross( link, guardLine )) { isCross = true; break; } } if (!isCross) { float weight = Vector2.Distance( convex[i].value.Pos, convex[(i + 1) % convex.Length].value.Pos ); //if (float.IsNaN( weight )) //{ //} GraphPoint<NaviPoint>.Link( convex[i], convex[(i + 1) % convex.Length], weight ); } } } #endregion #region 检查凸包之间连线是否与警戒线以及边界线相交,如不相交则连接并计算权值 for (int i = 0; i < convexs.Count - 1; i++) { for (int j = i + 1; j < convexs.Count; j++) { foreach (GraphPoint<NaviPoint> p1 in convexs[i].points) { // 检查连线是否超出边界 if (!mapBorder.Contains( p1.value.Pos )) continue; foreach (GraphPoint<NaviPoint> p2 in convexs[j].points) { Segment link = new Segment( p1.value.Pos, p2.value.Pos ); bool isCross = false; foreach (Segment guardLine in guardLines) { if (Segment.IsCross( link, guardLine )) { isCross = true; break; } } if (!isCross) { foreach (Segment borderLine in borderLines) { if (Segment.IsCross( link, borderLine )) { isCross = true; break; } } } if (!isCross) { float weight = Vector2.Distance( p1.value.Pos, p2.value.Pos ); //if (float.IsNaN( weight )) //{ //} GraphPoint<NaviPoint>.Link( p1, p2, weight ); } } } } } #endregion #region 整理导航图 List<GraphPoint<NaviPoint>> points = new List<GraphPoint<NaviPoint>>(); foreach (GuardConvex convex in convexs) { foreach (GraphPoint<NaviPoint> p in convex.points) { points.Add( p ); } } naviGraph = points.ToArray(); #endregion }
public NavigateMap ( EyeableBorderObjInfo[] objInfos, Rectanglef mapBorder, float spaceForTank ) { BuildMap( objInfos, mapBorder, spaceForTank ); }
private bool PointOutBorder ( Vector2 oriPosInWorld, Vector2 stepX, Vector2 stepY, Point bordPointA, Rectanglef screenRect ) { Vector2 PInWorld = oriPosInWorld + bordPointA.X * stepX + bordPointA.Y * stepY; int xW = (int)(PInWorld.X); int yW = (int)(PInWorld.Y); if (screenRect.Contains( new Vector2( xW, yW ) )) return false; else return 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> /// 更新精灵的转换矩阵和包围盒 /// </summary> public void UpdateTransformBounding () { CalDestinRect(); mTransform = Matrix.CreateTranslation( new Vector3( -Origin, 0f ) ) * Matrix.CreateScale( new Vector3( Width / (float)mTexture.Width, Height / (float)mTexture.Height, 1 ) ) * Matrix.CreateRotationZ( Rata ) * Matrix.CreateTranslation( new Vector3( Pos, 0f ) ); mBounding = CalculateBoundingRectangle( new Rectangle( 0, 0, mTexture.Width, mTexture.Height ), mTransform ); }