/// <summary> /// Draws horizontal and vertical coordinates for the board. /// </summary> /// <param name="resourceCreator"></param> /// <param name="drawingSession">used for rendering</param> /// <param name="boardWidth">width of the game board</param> /// <param name="boardHeight">height of the game board</param> private void DrawBoardCoordinates(ICanvasResourceCreator resourceCreator, CanvasDrawingSession drawingSession, int boardWidth, int boardHeight) { if (!this.ShowCoordinates) { return; } int startPosition = _sharedBoardControlState.OriginX; float fontSize = Math.Min(boardWidth * _cellSize, boardHeight * _cellSize) / (float)ReferenceWidth; _textFormat.FontSize = ReferenceFontSize * fontSize; // Draw horizontal char coordinates for (int i = 0; i < boardWidth; i++) { var currentPosition = startPosition + i; var charCode = GetHorizontalAxisCoordinate(currentPosition, boardWidth); CanvasTextLayout textLayout = RenderUtilities.GetCachedCanvasTextLayout(resourceCreator, ((char)(charCode)).ToString(), _textFormat, _cellSize); textLayout.VerticalAlignment = CanvasVerticalAlignment.Center; textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Center; drawingSession.DrawTextLayout( textLayout, ((i + 1) * _cellSize), 0, Colors.Black); drawingSession.DrawTextLayout( textLayout, ((i + 1) * _cellSize), _cellSize * (boardHeight + 1), Colors.Black); } // Draw vertical numerical coordinates for (int i = 0; i < boardHeight; i++) { int y = (boardHeight - i) + _sharedBoardControlState.OriginY; CanvasTextLayout textLayout = RenderUtilities.GetCachedCanvasTextLayout(resourceCreator, y.ToString(), _textFormat, _cellSize); textLayout.VerticalAlignment = CanvasVerticalAlignment.Center; textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Center; drawingSession.DrawTextLayout( textLayout, 0, ((i + 1) * _cellSize), Colors.Black); drawingSession.DrawTextLayout( textLayout, _cellSize * (boardWidth + 1), ((i + 1) * _cellSize), Colors.Black); } }
/// <summary> /// Draws the entire game board for the provided state. /// </summary> /// <param name="sender"></param> /// <param name="session"></param> /// <param name="gameState"></param> public void Draw(ICanvasResourceCreator sender, double width, double height, CanvasDrawingSession session, GameTreeNode gameState) { // Calculations double clientWidth = width; double clientHeight = height; int boardWidth = this.SharedBoardControlState.BoardWidth; int widthWithBorder = boardWidth + (this.ShowCoordinates ? 2 : 0); int boardHeight = this.SharedBoardControlState.BoardHeight; Rect boardRectangle = RenderUtilities.Scale( new Rect(0, 0, clientWidth, clientHeight), boardWidth + (this.ShowCoordinates ? 2 : 0), boardHeight + (this.ShowCoordinates ? 2 : 0)); _cellSize = (int)(boardRectangle.Width / widthWithBorder); _halfSize = _cellSize / 2; if (this.ShowCoordinates) { _boardBorderThickness = _cellSize; } else { _boardBorderThickness = 0; } this.SharedBoardControlState.LeftPadding = (int)boardRectangle.X + _boardBorderThickness; this.SharedBoardControlState.TopPadding = (int)boardRectangle.Y + _boardBorderThickness; this.SharedBoardControlState.NewCellSize = _cellSize; // The above should only be probably called on demand, not always // Draw parts DrawBoard(session, clientWidth, clientHeight, boardRectangle); // Draw coordinates session.Transform = Matrix3x2.CreateTranslation( (float)boardRectangle.X, (float)boardRectangle.Y); DrawBoardCoordinates(sender, session, boardWidth, boardHeight); // Draw grid session.Transform = Matrix3x2.CreateTranslation( (float)boardRectangle.X + _boardBorderThickness, (float)boardRectangle.Y + _boardBorderThickness); CanvasCommandList lines = new CanvasCommandList(sender); using (CanvasDrawingSession linesSession = lines.CreateDrawingSession()) { linesSession.Antialiasing = CanvasAntialiasing.Aliased; DrawBoardLines(linesSession, boardWidth, boardHeight); } session.DrawImage(lines); DrawBoardStarPoints(session, boardWidth, boardHeight); lines.Dispose(); // Shining position special case if (_sharedBoardControlState.ShiningPosition.IsDefined) { int x = this.SharedBoardControlState.ShiningPosition.X; int y = ((this.SharedBoardControlState.BoardHeight - 1) - this.SharedBoardControlState.ShiningPosition.Y); float minusWhat = (float)_flickerPercentage * _cellSize * 0.07f; session.FillRoundedRectangle( _cellSize * x + minusWhat, _cellSize * y + minusWhat, _cellSize - 2 * minusWhat, _cellSize - 2 * minusWhat, 4, 4, Color.FromArgb(140, 100, 200, 100)); } // Draw all stones for given game state DrawStones(gameState, session); Position pointerPosition = _sharedBoardControlState.PointerOverPosition; // Mouse over position special case if (pointerPosition.IsDefined && _sharedBoardControlState.IsShadowDrawingEnabled) { if (SharedBoardControlState.IsAnalyzeModeEnabled) { // Set actual pointer position for the tools // This has to be done here and not in InputService because we might get caught in race condition // - pointerPosition.IsDefined returns true and in mean time user moves pointer outside of the board and IToolServices advertises Position.Undefined // - and finally in this step we ask ITool for its shadow. ITools should not worry about handling Position.Undefined for GetShadow SharedBoardControlState.AnalyzeToolServices.SetPointerPosition(pointerPosition); // Analyze mode is enabled, draw selected tool shadow item. DrawAnalyzeToolShadow(session, SharedBoardControlState.AnalyzeModeTool); } else { // TODO (future work) Petr : only if legal - use Ruleset IsLegalMove? // But it would be slow, you can implement caching to check for each intersection only once if (_sharedBoardControlState.PointerOverShadowColor != StoneColor.None && ( _sharedBoardControlState.TEMP_MoveLegality == null || _sharedBoardControlState.TEMP_MoveLegality[pointerPosition.X, pointerPosition.Y] == MoveResult.Legal)) { DrawStone(session, pointerPosition.X, pointerPosition.Y, _sharedBoardControlState.PointerOverShadowColor, 0.5); } } } // Draw markups if enabled if (SharedBoardControlState.IsAnalyzeModeEnabled) { session.Blend = CanvasBlend.SourceOver; DrawMarkups(session, gameState.Markups); } // Draw debug FPS session.Transform = Matrix3x2.Identity; if (!SimpleRenderService) { _fpsCounter.Draw(session, new Rect(clientWidth - 100, 10, 80, 30)); } }