/// <summary> /// Called whenever the underlying frame changes to redraw the frame. /// </summary> public void DrawFrame(PlayFrame frame, Graphics display, PitchScreenCoordConverter converter, VisualOverlay overlay, Rectangle displayRectangle) { BufferedGraphicsContext currentContext; BufferedGraphics myBuffer; currentContext = BufferedGraphicsManager.Current; myBuffer = currentContext.Allocate(display, displayRectangle); myBuffer.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; myBuffer.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; myBuffer.Graphics.Clear(mBackColor); // Draw the pitch itself. DrawPitch(myBuffer.Graphics, converter); // This moves items around based on what the user is doing. // e.g. If a user is dragging a cut at the moment it adds a new cut for // the given player. PlayFrame adjustableFrame = FrameRenderer.AdjustFrameForOverlay(frame, overlay, converter); foreach (Player player in adjustableFrame.PlayerMovement.Keys) { List<LinearMovement> playerMoves = adjustableFrame.PlayerMovement[player]; if (playerMoves.Count > 0) { DrawPlayer(player, playerMoves[0].FinalPosition, myBuffer.Graphics, converter, false); if (playerMoves.Count > 1) { List<Point> cutLocations = new List<Point>(); foreach (LinearMovement playerMove in playerMoves) { cutLocations.Add(converter.pitchToScreenCoords(playerMove.FinalPosition)); } myBuffer.Graphics.DrawLines(mCutPen, cutLocations.ToArray<Point>()); } } } foreach (Trigger trigger in adjustableFrame.Triggers) { DrawTrigger(myBuffer.Graphics, trigger, converter); } // Draw the disc after the players because the sprite sits on top of the // player sprite who is holding it. if (adjustableFrame.DiscFrameMovement.Thrower != null) { DrawDisc(myBuffer.Graphics, adjustableFrame.DiscFrameMovement.StartPosition(), converter); if (adjustableFrame.DiscFrameMovement.HasMoved) { DrawDiscFlight(myBuffer.Graphics, adjustableFrame.DiscFrameMovement.StartPosition(), adjustableFrame.DiscFrameMovement.ControlPoint, adjustableFrame.DiscFrameMovement.EndPosition(), converter); } } else if (overlay.PlacingDisc) { // The mouse location is stored in the overlay but we need to pass the // pitch coordinates to the drawing function. DrawDisc(myBuffer.Graphics, converter.screenToPitchCoords(overlay.MouseLocation), converter); } myBuffer.Render(); myBuffer.Dispose(); }
/// <summary> /// Render a small square for a player. This is used when we're rendering /// into a small space. /// </summary> /// <param name="graphics"></param> /// <param name="player"></param> /// <param name="location"></param> /// <param name="converter"></param> private void DrawSmallPlayer(Graphics graphics, Player player, PointF location, PitchScreenCoordConverter converter) { Point screenCoords = converter.pitchToScreenCoords(location); Brush playerBrush = player.PlayerTeam.UniqueId == Team.RED_TEAM.UniqueId ? Brushes.Red : Brushes.Blue; graphics.FillRectangle(playerBrush, screenCoords.X, screenCoords.Y, 4, 4); }
/// <summary> /// Draw the disc flight. /// /// Currently simply a straight line from A to B. Could enhance this so /// that it draws a cardinal spline instead at some point. The UI to draw /// that is the more difficult area. /// </summary> /// <param name="display"></param> /// <param name="startLocation"></param> /// <param name="controlPoint"></param> /// <param name="endLocation"></param> /// <param name="converter"></param> private void DrawDiscFlight(Graphics display, PointF startLocation, PointF controlPoint, PointF endLocation, PitchScreenCoordConverter converter) { Point screenCoordsStart = converter.pitchToScreenCoords(startLocation); Point screenCoordsEnd = converter.pitchToScreenCoords(endLocation); Point screenControlPoint = converter.pitchToScreenCoords(controlPoint); QuadraticBezierCurve curve = new QuadraticBezierCurve(screenCoordsStart, screenControlPoint, screenCoordsEnd); display.DrawBeziers(mDiscFlightPen, curve.ToCubic()); display.DrawRectangle(mDiscFlightPen, screenControlPoint.X - 1, screenControlPoint.Y - 1, 2, 2); }
/// <summary> /// Draw a string onto the pitch at the given pitch coordinates. Does /// the conversion from pitch to screen internally. /// </summary> /// <param name="display"></param> /// <param name="converter"></param> /// <param name="text"></param> /// <param name="position"></param> /// <param name="font"></param> /// <param name="brush"></param> public void DrawString(Graphics display, PitchScreenCoordConverter converter, String text, PointF position, Font font, Brush brush) { Point screenCoords = converter.pitchToScreenCoords(position); display.DrawString(text, font, brush, screenCoords); }
/// <summary> /// Draw a single sprite on the pitch at the given coordinates. Does the /// conversion of pitch -> screen internally. /// </summary> /// <param name="display">The display on which to draw.</param> /// <param name="converter">The converter utility used to turn pitch /// coordinates into screen coordinates</param> /// <param name="image">The image to draw</param> /// <param name="position">The pitch coordinates</param> /// <param name="width">Pitch width</param> /// <param name="length">Pitch height/length</param> public void DrawSprite(Graphics display, PitchScreenCoordConverter converter, Image image, PointF position, float width, float length) { Rectangle imagePlacement = new Rectangle(); Point screenCoords = converter.pitchToScreenCoords(position); PointF imageSize = new PointF(width, length); Point convertedImageSize = converter.pitchToScreenSize(imageSize); imagePlacement.Location = screenCoords; imagePlacement.Width = convertedImageSize.X; imagePlacement.Height = convertedImageSize.Y; display.DrawImage(image, imagePlacement); }
/// <summary> /// The pitch is drawn as a pair of rectangles rather than as a sprite. /// /// All conversion between pitch coordinates and screen coordinates is done /// internally. /// </summary> /// <param name="display"></param> /// <param name="converter"></param> public void DrawPitch(Graphics display, PitchScreenCoordConverter converter) { Rectangle outerPitch = new Rectangle(); Rectangle innerPitch = new Rectangle(); using (Pen linePen = new Pen(mLineColor, mLineWidth)) { Point bottomRight = converter.pitchToScreenCoords( new PointF(sPitchWidth, sPitchLength)); Point innerBottomRight = converter.pitchToScreenCoords( new PointF(sPitchWidth, (sPitchLength - 2.0f * sEndzoneDepth))); Point leftBrick = converter.pitchToScreenCoords( new PointF(sPitchWidth / 2.0f, sEndzoneDepth + sBrickDistance)); Point rightBrick = converter.pitchToScreenCoords( new PointF(sPitchWidth / 2.0f, sPitchLength - sEndzoneDepth - sBrickDistance)); int brickDistanceScreen = converter.pitchToScreenLength(sBrickRadius); outerPitch.Location = converter.pitchToScreenCoords(new PointF(0.0f, 0.0f)); outerPitch.Width = bottomRight.X; outerPitch.Height = bottomRight.Y; innerPitch.Location = converter.pitchToScreenCoords(new PointF(0.0f, sEndzoneDepth)); innerPitch.Width = innerBottomRight.X; innerPitch.Height = innerBottomRight.Y; display.FillRectangle(mPitchBrush, outerPitch); display.DrawRectangle(linePen, outerPitch); display.DrawRectangle(linePen, innerPitch); DrawCross(display, linePen, leftBrick, brickDistanceScreen); DrawCross(display, linePen, rightBrick, brickDistanceScreen); } }