/// <summary> /// Creates and generates the whole town. /// </summary> /// <param name="game">The game</param> /// <param name="loadingFrom">Loading form where the generating progress will be shown</param> public Town(ActionGame game, Loading loadingFrom) : base(game) { EmptyTownQuarterOwner.LoadContent(game.Content); quarters = new TownQuarter[game.Settings.TownQuarterCount]; //Town graph creation loadingFrom.SetLabel("Generating town graph..."); loadingFrom.SetValue(0); int[] degrees = new int[game.Settings.TownQuarterCount]; bool[,] edges = new bool[game.Settings.TownQuarterCount, game.Settings.TownQuarterCount]; // Graph is unoriented (symetric). edges[i, j] can be true only if i<j! for (int i = 0; i < game.Settings.TownQuarterCount - 1; i++) // First is made path through all. Graph has to have only one component. { int j = i + 1; degrees[i]++; degrees[j]++; edges[i, j] = true; } for (int i = 0; i < game.Settings.TownQuarterCount; i++) { loadingFrom.SetValue(100 * i / game.Settings.TownQuarterCount); for (int j = i + 1; j < game.Settings.TownQuarterCount; j++) //graph isn't oriented and reflexion is denied { if (!edges[i, j] && degrees[i] < MaxQuarterDegree && degrees[j] < MaxQuarterDegree) { if (game.Random.NextDouble() < 0.65) { degrees[i]++; degrees[j]++; edges[i, j] = true; } } } } //Quarter creating by degrees loadingFrom.SetLabel("Generating quarters and streets..."); loadingFrom.SetValue(0); for (int i = 0; i < game.Settings.TownQuarterCount; i++) { loadingFrom.SetValue(100 * i / game.Settings.TownQuarterCount); float perimeterLength = MinSideLengthPerInterface * Math.Max(degrees[i], 4); // Even interface isn't needed the side must be there perimeterLength *= (float)game.Random.NextDouble() + 1f; //Minimal length can be doubled float width = (perimeterLength / 2f) * (float)(game.Random.NextDouble() * 0.3 + 0.35); //aspect ratio float height = (perimeterLength / 2f) - width; if (width < MinQuarterSideLength) width = MinQuarterSideLength; if (height < MinQuarterSideLength) height = MinQuarterSideLength; do { try { TownQuarter quarter = new TownQuarter(game, new Vector2(width, height), degrees[i]); quarters[i] = quarter; } catch (NoSpaceForInterfaceException) { float widthIncement = MinSideLengthPerInterface * (float)game.Random.NextDouble(); width += widthIncement; height += MinSideLengthPerInterface - widthIncement; } } while (quarters[i] == null); } //Joining interfaces loadingFrom.SetLabel("Building town..."); loadingFrom.SetValue(0); for (int i = 0; i < game.Settings.TownQuarterCount; i++) { loadingFrom.SetValue(100 * i / game.Settings.TownQuarterCount); for (int j = i + 1; j < game.Settings.TownQuarterCount; j++) { if (edges[i, j]) { TownQuarterInterface ifaceI = (from iface in quarters[i].Interfaces where iface.OppositeInterface == null orderby game.Random.Next() select iface).First(); TownQuarterInterface ifaceJ = (from iface in quarters[j].Interfaces where iface.OppositeInterface == null orderby game.Random.Next() select iface).First(); ifaceI.OppositeInterface = ifaceJ; ifaceJ.OppositeInterface = ifaceI; ifaceI.LeftPathGraphVertex.AddNeighborBothDirection(ifaceJ.RightPathGraphVertex, TownQuarter.SquareWidth); ifaceI.RightPathGraphVertex.AddNeighborBothDirection(ifaceJ.LeftPathGraphVertex, TownQuarter.SquareWidth); } } } foreach (var quarter in quarters) { quarter.BuildInterfaceRoadSigns(); } //Town map base creating { Bitmap mapRaster = new Bitmap(MapImageWidth, MapImageHeight); using (Graphics graphics = Graphics.FromImage(mapRaster)) { graphics.FillRectangle(Brushes.White, 0, 0, mapRaster.Width, mapRaster.Height); float angleJump = MathHelper.TwoPi / Game.Settings.TownQuarterCount; float radius = Math.Min(MapImageWidth, MapImageHeight) / 2f - 20f; PointF center = new PointF(MapImageWidth / 2f, MapImageHeight / 2f); for (int i = 0; i < Game.Settings.TownQuarterCount; i++) { for (int j = i + 1; j < Game.Settings.TownQuarterCount; j++) { if (edges[i, j]) { graphics.DrawLine(Pens.Green, center.X + (float)Math.Cos(i * angleJump) * radius, center.Y + (float)Math.Sin(i * angleJump) * radius, center.X + (float)Math.Cos(j * angleJump) * radius, center.Y + (float)Math.Sin(j * angleJump) * radius ); } } } for (int i = 0; i < Game.Settings.TownQuarterCount; i++) { graphics.FillEllipse(Brushes.Black, center.X + (float)Math.Cos(i * angleJump) * radius - 3.5f, center.Y + (float)Math.Sin(i * angleJump) * radius - 3.5f, 7, 7); graphics.DrawString(quarters[i].Name, new Font("Verdana", 12), Brushes.Black, center.X + (float)Math.Cos(i * angleJump) * radius, center.Y + (float)Math.Sin(i * angleJump) * radius - 16); } } mapImage = mapRaster; } GC.Collect(); //Selecting starting quarter currentQuarter = quarters[0]; }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { if (running) { using (Loading loadingForm = new Loading()) { GameTime gameTime = new GameTime(TimeSpan.Zero, TimeSpan.Zero); loadingForm.Show(); loadingForm.SetLabel("Loading graphics device tools..."); spriteBatch = new SpriteBatch(GraphicsDevice); loadingForm.SetLabel("Loading content..."); contentRepository.LoadContent(); loadingForm.SetLabel("Loading gun types..."); LoadGunTypes(); player = new Player(this); opponent = new Opponent(this); town = new Town(this, loadingForm); loadingForm.SetLabel("Loading player..."); loadingForm.SetValue(0); Point playerPoint = town.CurrentQuarter.GetRandomSquare(s => s == MapFillType.Sidewalk); PositionInTown playerPosition = new PositionInTown(town.CurrentQuarter, playerPoint.ToVector2() * TownQuarter.SquareWidth + Vector2.One * 0.5f * TownQuarter.SquareWidth); player.Load(contentRepository.Player, playerPosition, MathHelper.PiOver2, drawer.WorldTransformMatrix); town.CurrentQuarter.SpaceGrid.AddObject(player); town.CurrentQuarter.SetOwner(player, gameTime); player.AddEnemy(opponent); loadingForm.SetLabel("Loading opponent..."); loadingForm.SetValue(0); TownQuarter oppQuarter = (from q in town.Quarters where q != town.CurrentQuarter orderby random.Next() select q).First(); Point oppPoint = oppQuarter.GetRandomSquare(s => s == MapFillType.Sidewalk); PositionInTown oppPosition = new PositionInTown(oppQuarter, oppPoint.ToVector2() * TownQuarter.SquareWidth); opponent.Load(contentRepository.Opponent, oppPosition, 0, drawer.WorldTransformMatrix); oppQuarter.BeEnteredBy(opponent); oppQuarter.SetOwner(opponent, gameTime); opponent.AddEnemy(player); Components.Add(town); BulletVisualisation.Texture = Content.Load<Texture2D>("Textures/white"); backgroundSound = Content.Load<SoundEffect>("Sounds/background").CreateInstance(); loadingForm.SetLabel("Cleaning memory..."); loadingForm.SetValue(0); GC.Collect(); loadingForm.SetValue(100); loadingForm.SetLabel("Content loaded. Get ready to play!"); loadingForm.SetValue(100); loadingForm.Close(); backgroundSound.IsLooped = true; backgroundSound.Play(); drawer.ShowMessage(new GameTime(), String.Format("Wellcome in the game. You're in {0}.", player.Position.Quarter.Name)); } if (settings.Fullscreen) { graphics.ToggleFullScreen(); } } }