/// <summary> /// Creates a new bullet visualisation. /// </summary> /// <param name="quarter">Town quarter where the bullet is located</param> /// <param name="start">Starting position</param> /// <param name="azimuth">The flight direction</param> /// <param name="range">The flight range</param> /// <param name="startHeight">Starting height</param> /// <param name="endHeight">Ending height</param> public BulletVisualisation(TownQuarter quarter, Vector2 start, float azimuth, float range, float startHeight, float endHeight) { Vector2 end = start.Go(range, azimuth); Vector2 startL = start.Go(Width, azimuth - MathHelper.PiOver2); Vector2 startR = start.Go(Width, azimuth + MathHelper.PiOver2); Vector2 endL = end.Go(Width, azimuth - MathHelper.PiOver2); Vector2 endR = end.Go(Width, azimuth + MathHelper.PiOver2); horizontalPlate = new Plate(quarter, startL.ToVector3(startHeight), startR.ToVector3(startHeight), endL.ToVector3(endHeight), endR.ToVector3(endHeight), Texture, Texture, false); verticalPlate = new Plate(quarter, start.ToVector3(startHeight + Width), start.ToVector3(startHeight - Width), end.ToVector3(endHeight + Width), end.ToVector3(endHeight - Width), Texture, Texture, false); }
/// <summary> /// Generates road and sidewalks interfaces - street for joining with other quarters. /// </summary> /// <param name="degree">Number of'quarters neighbors - degree of vertex</param> /// <param name="roadTexture">Used road texture</param> /// <param name="sidewalkTexture">Used sidewalk texture</param> private void GenerateInterfaces(int degree, Texture2D roadTexture, Texture2D sidewalkTexture) { Dictionary<TownQuarterInterfacePosition, List<Range>> emptyRanges = new Dictionary<TownQuarterInterfacePosition, List<Range>>(4); emptyRanges.Add(TownQuarterInterfacePosition.Top, new List<Range>(new Range[] { new Range(BlockWidth + 1, bitmapSize.Width - BlockWidth - 1) })); emptyRanges.Add(TownQuarterInterfacePosition.Bottom, new List<Range>(new Range[] { new Range(BlockWidth + 1, bitmapSize.Width - BlockWidth - 1) })); emptyRanges.Add(TownQuarterInterfacePosition.Left, new List<Range>(new Range[] { new Range(BlockWidth + 1, bitmapSize.Height - BlockWidth - 1) })); emptyRanges.Add(TownQuarterInterfacePosition.Right, new List<Range>(new Range[] { new Range(BlockWidth + 1, bitmapSize.Height - BlockWidth - 1) })); for (int i = 0; i < degree; i++) { TownQuarterInterfacePosition side; List<TownQuarterInterfacePosition> possibleSides = new List<TownQuarterInterfacePosition>( from key in emptyRanges.Keys where emptyRanges[key].Count(rangeItem => rangeItem.Length > 2 * BlockWidth + 1) > 0 select key ); if (possibleSides.Count < 1) { throw new NoSpaceForInterfaceException("This quarter has already full all sides of interfaces. Degree argument is too big."); } side = possibleSides[game.Random.Next(0, possibleSides.Count - 1)]; List<Range> possibleRanges = emptyRanges[side].FindAll(rangeItem => rangeItem.Length > 2 * BlockWidth + 1); int rangeIndex = game.Random.Next(0, possibleRanges.Count - 1); Range range = possibleRanges[rangeIndex]; emptyRanges[side].Remove(range); int position = range.Begin + (int)((0.35 + game.Random.NextDouble() * 0.3) // percentage position in range * range.Length); emptyRanges[side].Add(new Range(range.Begin, position - 1)); emptyRanges[side].Add(new Range(position + 1, range.End)); AxisDirection direction = (side == TownQuarterInterfacePosition.Right || side == TownQuarterInterfacePosition.Left) ? AxisDirection.Horizontal : AxisDirection.Vertical; TownQuarterInterface iface = new TownQuarterInterface { SidePosition = side, Quarter = this, OppositeInterface = null }; for (int p = 0; p < BlockWidth; p++) { int rx, ry, slx, sly, srx, sry; switch (direction) { case AxisDirection.Horizontal: rx = (p + (side == TownQuarterInterfacePosition.Left ? 0 : bitmapSize.Width - BlockWidth)); ry = position; slx = rx; srx = rx; sly = ry - 1; sry = ry + 1; break; case AxisDirection.Vertical: rx = position; ry = (p + (side == TownQuarterInterfacePosition.Top ? 0 : bitmapSize.Height - BlockWidth)); slx = rx - 1; srx = rx + 1; sly = ry; sry = ry; break; default: throw new InvalidOperationException("Unknown AxisDirection value."); } if (direction == AxisDirection.Horizontal) iface.BitmapPosition = ry; if (direction == AxisDirection.Vertical) iface.BitmapPosition = rx; mapBitmap[rx * bitmapSize.Height + ry] = MapFillType.Road; mapBitmap[slx * bitmapSize.Height + sly] = MapFillType.Sidewalk; mapBitmap[srx * bitmapSize.Height + sry] = MapFillType.Sidewalk; FlatObject road = new FlatObject(new PositionInTown(this, new Vector2(rx * SquareWidth, ry * SquareWidth)), 0, new Vector2(SquareWidth, SquareWidth), roadTexture); FlatObject sidewalkL = new FlatObject(new PositionInTown(this, new Vector2(slx * SquareWidth, sly * SquareWidth)), 0, new Vector2(SquareWidth, SquareWidth), sidewalkTexture); FlatObject sidewalkR = new FlatObject(new PositionInTown(this, new Vector2(srx * SquareWidth, sry * SquareWidth)), 0, new Vector2(SquareWidth, SquareWidth), sidewalkTexture); groundObjects.AddLast(road); groundObjects.AddLast(sidewalkL); groundObjects.AddLast(sidewalkR); } //wall generator { Texture2D wallTexture = game.ContentRepository.InterfaceWall; float wallWidth = 6f; //m const float wallHeight = 4.5f; int count = (int)((BlockWidth - 1) * SquareWidth / wallWidth); //minus sidewalk wallWidth = (BlockWidth - 1) * SquareWidth / count; const float ifaceWallEpsilon = 0.006f; // 3mm for (int p = 0; p < count; p++) { Vector2 beginL, endL, beginR, endR; switch (direction) { case AxisDirection.Horizontal: beginL.X = p * wallWidth + (side == TownQuarterInterfacePosition.Left ? 0 : bitmapSize.Width - BlockWidth + 1) * SquareWidth; beginL.Y = (position - 1) * SquareWidth + ifaceWallEpsilon; endL = beginL; endL.X += wallWidth; beginR.X = p * wallWidth + (side == TownQuarterInterfacePosition.Left ? 0 : bitmapSize.Width - BlockWidth + 1) * SquareWidth; beginR.Y = (position + 2) * SquareWidth - ifaceWallEpsilon; endR = beginR; endR.X += wallWidth; break; case AxisDirection.Vertical: beginL.Y = p * wallWidth + (side == TownQuarterInterfacePosition.Top ? 0 : bitmapSize.Height - BlockWidth + 1) * SquareWidth; beginL.X = (position - 1) * SquareWidth + ifaceWallEpsilon; endL = beginL; endL.Y += wallWidth; beginR.Y = p * wallWidth + (side == TownQuarterInterfacePosition.Top ? 0 : bitmapSize.Height - BlockWidth + 1) * SquareWidth; beginR.X = (position + 2) * SquareWidth - ifaceWallEpsilon; endR = beginR; endR.Y += wallWidth; break; default: throw new InvalidOperationException("Unknown AxisDirection value."); } Plate wallL = new Plate(this, beginL.ToVector3(wallHeight), endL.ToVector3(wallHeight), beginL.ToVector3(0), endL.ToVector3(0), wallTexture, wallTexture, true); solidPlates.AddLast(wallL); Plate wallr = new Plate(this, beginR.ToVector3(wallHeight), endR.ToVector3(wallHeight), beginR.ToVector3(0), endR.ToVector3(0), wallTexture, wallTexture, true); solidPlates.AddLast(wallr); } } interfaces.Add(iface); } GenerateRestOfBorderSidewalks(emptyRanges, sidewalkTexture); GenerateBorderBuildings(emptyRanges); }
/// <summary> /// Builds the roadsigns for the neighbor quarters. /// </summary> public void BuildInterfaceRoadSigns() { const float vPosition = 8; float height = 2f; const float width = 6f; const float halfWidth = width / 2; Model handleModel = game.Content.Load<Model>("Objects/roadSignHandle"); Vector3 handleModelSize = handleModel.GetSize(game.Drawer.WorldTransformMatrix); foreach (TownQuarterInterface iface in interfaces) { Vector2 handlePos = Vector2.Zero; float handleAzimuth = 0f; Vector3 upperLeft = iface.Position().ToVector3(vPosition); Vector3 upperRight = upperLeft; const float handleEpsilon = 0.02f; //2cm switch (iface.SidePosition) { case TownQuarterInterfacePosition.Top: upperLeft.X -= halfWidth; upperRight.X += halfWidth; upperLeft.Z += (BlockWidth - 2) * SquareWidth; upperRight.Z += (BlockWidth - 2) * SquareWidth; handlePos = upperLeft.XZToVector2(); handlePos.X += halfWidth; handlePos.X -= handleModelSize.X * 0.5f; handlePos.Y -= handleModelSize.Z + handleEpsilon; handleAzimuth = 0f; break; case TownQuarterInterfacePosition.Right: upperLeft.Z -= halfWidth; upperRight.Z += halfWidth; upperLeft.X -= (BlockWidth - 2) * SquareWidth; upperRight.X -= (BlockWidth - 2) * SquareWidth; handlePos = upperLeft.XZToVector2(); handlePos.Y += halfWidth; //handlePos.Y -= handleModelSize.X * 0.5f; handlePos.X += handleModelSize.Z + handleEpsilon - handleModelSize.X * 0.5f - handleModelSize.Z * 0.5f; handleAzimuth = MathHelper.PiOver2; break; case TownQuarterInterfacePosition.Bottom: upperLeft.X += halfWidth; upperRight.X -= halfWidth; upperLeft.Z -= (BlockWidth - 2) * SquareWidth; upperRight.Z -= (BlockWidth - 2) * SquareWidth; handlePos = upperLeft.XZToVector2(); handlePos.X -= halfWidth; handlePos.X -= handleModelSize.X * 0.5f; handlePos.Y += handleEpsilon; handleAzimuth = 0f; break; case TownQuarterInterfacePosition.Left: upperLeft.Z += halfWidth; upperRight.Z -= halfWidth; upperLeft.X += (BlockWidth - 2) * SquareWidth; upperRight.X += (BlockWidth - 2) * SquareWidth; handlePos = upperLeft.XZToVector2(); handlePos.Y -= halfWidth; //handlePos.Y -= handleModelSize.X * 0.5f; handlePos.X -= handleModelSize.Z + handleEpsilon + handleModelSize.X * 0.5f - handleModelSize.Z * 0.5f; handleAzimuth = MathHelper.PiOver2; break; default: break; } Vector3 lowerLeft = upperLeft, lowerRight = upperRight; lowerLeft.Y -= height; lowerRight.Y -= height; Plate signPlate = new Plate(this, upperLeft, upperRight, lowerLeft, lowerRight, iface.OppositeInterface.Quarter.RoadSignTexture, game.Content.Load<Texture2D>("Textures/metal"), true); magicPlates.AddLast(signPlate); iface.OppositeInterface.Quarter.RegisterNewRoadSign(signPlate); SpatialObject handle = new SpatialObject(handleModel, new PositionInTown(this, handlePos), handleAzimuth, game.Drawer.WorldTransformMatrix); solidObjects.AddLast(handle); } }
/// <summary> /// Registers a roadsign that is pointing to this quarter /// </summary> /// <param name="roadSign">The roadsign</param> public void RegisterNewRoadSign(Plate roadSign) { roadSignsPointingToMe.Add(roadSign); }