public void Paint() { // draw the map Background.Draw(Surface); // add center indicator if (Human.Z == Constants.Ground) { var centerAngle = Collision.CalculateAngleFromPoint(Human.X, Human.Y, Background.X, Background.Y); float x1, y1, x2, y2; var distance = Math.Min(Surface.Width, Surface.Height) * 0.9f; Collision.CalculateLineByAngle(Surface.Width / 2, Surface.Height / 2, centerAngle, (distance / 2), out x1, out y1, out x2, out y2); Surface.DisableTranslation(); { // draw an arrow var endX = x2; var endY = y2; x1 = endX; y1 = endY; Collision.CalculateLineByAngle(x1, y1, (centerAngle + 180) % 360, 50, out x1, out y1, out x2, out y2); Surface.Line(RGBA.Black, x1, y1, x2, y2, 10); x1 = endX; y1 = endY; Collision.CalculateLineByAngle(x1, y1, (centerAngle + 135) % 360, 25, out x1, out y1, out x2, out y2); Surface.Line(RGBA.Black, x1, y1, x2, y2, 10); x1 = endX; y1 = endY; Collision.CalculateLineByAngle(x1, y1, (centerAngle + 225) % 360, 25, out x1, out y1, out x2, out y2); Surface.Line(RGBA.Black, x1, y1, x2, y2, 10); } Surface.EnableTranslation(); } // draw all elements var hidden = new HashSet <int>(); var visiblePlayers = new List <Player>(); foreach (var elem in Map.WithinWindow(Human.X, Human.Y, Surface.Width * (1 / ZoomFactor), Surface.Height * (1 / ZoomFactor))) { if (elem.IsDead) { continue; } if (elem is Player) { visiblePlayers.Add(elem as Player); continue; } if (elem.IsTransparent) { // if the player is intersecting with this item, then do not display it if (Map.IsTouching(Human, elem)) { continue; } // check if one of the bots is hidden by this object for (int i = 0; i < Players.Length; i++) { if (Players[i].Id == Human.Id) { continue; } if (Map.IsTouching(Players[i], elem)) { hidden.Add(Players[i].Id); } } } elem.Draw(Surface); } // draw the players foreach (var player in visiblePlayers) { if (hidden.Contains(player.Id)) { continue; } player.Draw(Surface); } // add any ephemerial elements lock (Ephemerial) { var toremove = new List <EphemerialElement>(); var messageShown = false; foreach (var b in Ephemerial) { if (b is Message) { // only show one message at a time if (messageShown) { continue; } messageShown = true; } b.Draw(Surface); b.Duration--; if (b.Duration < 0) { toremove.Add(b); } } foreach (var b in toremove) { Ephemerial.Remove(b); } } // display the player counts Surface.DisableTranslation(); { Surface.Text(RGBA.Black, Surface.Width - 200, 10, string.Format("Alive {0} of {1}", Alive, Players.Length)); Surface.Text(RGBA.Black, Surface.Width - 200, 30, string.Format("Kills {0}", Human.Kills)); } Surface.EnableTranslation(); // show a menu if present if (Map.IsPaused) { if (Menu == null) { throw new Exception("Must initalize a menu to display"); } Menu.Draw(Surface); } }
// paint callbacks private void Paint(IGraphics graphics) { // pre-load images if (Preloading) { if (AllResources == null) { // clear graphics.Clear(RGBA.White); // get all the image resources AllResources = Cat.GetImagesFromResources(); CurrentResourceIndex = 0; PreloadItemCount = Platform.IsType(PlatformType.Blazor) ? (AllResources.Count() / 2) - 1 : AllResources.Count() - 1; } if (CurrentResourceIndex < AllResources.Count()) { // load one image from a resource at a time var kvp = AllResources.ElementAt(CurrentResourceIndex++); var name = kvp.Key; if (Platform.IsType(PlatformType.Blazor)) { if (!name.StartsWith("t_", StringComparison.OrdinalIgnoreCase)) { return; } // remove the 't_' name = name.Substring(2); } var img = new ImageSource(name, kvp.Value); // load image graphics.Image(img.Image, x: 0, y: 0, width: 1, height: 1); } // display the loading bar if (PreloadCurrent > 0) { graphics.Rectangle(new RGBA() { B = 255, A = 255 }, x: 0, y: 100, width: (300 * ((float)PreloadCurrent / (float)PreloadItemCount)), 50, fill: true, border: false); } graphics.Rectangle(RGBA.Black, 0, 100, 300, 50, fill: false, border: true); PreloadCurrent++; // exit condition if (CurrentResourceIndex >= AllResources.Count()) { Preloading = false; AllResources = null; } return; } // clear graphics.Clear(RGBA.White); // paint the board try { LibraryLock.EnterReadLock(); // draw the title (relative to the typing text) var titleX = TextXStart; var titleY = TextYStart; graphics.Rectangle(new RGBA() { R = 200, G = 200, B = 200, A = 255 }, titleX, titleY, width: Board.Width - (TextXStart * 2) - 20f, height: 90, fill: true, border: false); graphics.Text(RGBA.Black, titleX, titleY + (TextSpacing * 0f), string.Format($"{CurrentBook.Title} by {CurrentBook.Author}"), TitleFontSize, TitleFontName); graphics.Text(RGBA.Black, titleX, titleY + (TextSpacing * 1.2f), CurrentPoem.Section, TitleFontSize, TitleFontName); graphics.Text(RGBA.Black, titleX, titleY + (TextSpacing * 2.4f), CurrentPoem.Title, TitleFontSize, TitleFontName); // draw the stats (based on the window height var statsX = TextXStart; var statsY = Board.Height - 150f; graphics.Rectangle(RGBA.Black, statsX, statsY, width: Board.Width - (TextXStart * 2) - 20f, height: 100, fill: true, border: true, thickness: 1f); graphics.Text(RGBA.White, statsX + 10f, statsY + (TextSpacing * 0.35f), string.Format($"Round {Stats.Round}"), TitleFontSize, TitleFontName); graphics.Text(RGBA.White, statsX + 10f, statsY + (TextSpacing * 2f), string.Format($"Words per minute {Stats.WordsPerMinute:f2} :: Wins {Stats.Wins} :: Losses {Stats.Losses}"), FontSize, FontName); graphics.Text(RGBA.White, statsX + 10f, statsY + (TextSpacing * 3f), string.Format($"Correct characters {Stats.CorrectCharacters} :: Wrong characters {Stats.WrongCharacters}"), FontSize, FontName); // add the cursor if (CurrentLine < Lines.Length) { var cursor = "_"; var x = TextXStart + (Lines[CurrentLine].Input.Length * FontWidth); graphics.Text(new RGBA() { R = 255, A = 255 }, x, TextYStart + (TextSpacing * (CurrentLine + 5)), cursor, FontSize, FontName); } // draw all the strings on the board for (int i = 0; i < Lines.Length; i++) { graphics.Text(RGBA.Black, TextXStart, TextYStart + (TextSpacing * (i + 5)), Lines[i].Text, FontSize, FontName); if (Lines[i].Input.Length > 0) { graphics.Text(RGBA.White, TextXStart, TextYStart + (TextSpacing * (i + 5)), Lines[i].Input.ToString(), FontSize, FontName); } } } finally { LibraryLock.ExitReadLock(); } // draw the cat if (Stats.IsRunning) { Cat.Draw(graphics); } // draw any ephemerial elements lock (Ephemerials) { Ephemerial active = null; if (Ephemerials.Count > 0) { active = Ephemerials[0]; active.Duration--; // check if it should be removed if (active.Duration <= 0) { Ephemerials.RemoveAt(0); if (active is NextRoundEphemerial) { ReadyToStartNextRound = true; } } } else { // show a message to start typing if (!IsDone && !Stats.IsRunning) { active = TypeToStart; } } if (active != null) { graphics.Text(active.Color, x: Board.Width - 400, y: Board.Height - 200, active.Text, fontsize: 12f); if (active is NextRoundEphemerial) { graphics.Text(RGBA.Black, x: Board.Width - 400, y: Board.Height - 200 + TextSpacing, string.Format($"Next round starts in {(active.Duration / 10) + 1}"), fontsize: 12f); } } } }