|
using System;
using System.Collections.Generic;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Bornander.Games.Direct3D;
namespace Bornander.Games.BoardGame.Direct3D
{
/// <summary>
/// This class is a renderer for a <code>CheckersLogic</code> object.
/// </summary>
class VisualBoard
{
#region Private members
private IBoardGameLogic gameLogic;
private IBoardGameModelRepository boardGameModelRepository;
private Square selectedSquare = Square.Negative;
// This is used to determine which one is the grabbed piece so that rendering
// of that one can be skipped since that is handeled bu the GamePanel.
private Square currentPieceOrigin = Square.Negative;
#endregion
public VisualBoard(IBoardGameLogic gameLogic, IBoardGameModelRepository boardGameModelRepository)
{
this.gameLogic = gameLogic;
this.boardGameModelRepository = boardGameModelRepository;
}
public void Render(Device device)
{
for (int row = 0; row < gameLogic.Rows; ++row)
{
for (int column = 0; column < gameLogic.Columns; ++column)
{
Square currentSquare = new Square(row, column);
Model boardSquare = boardGameModelRepository.GetBoardSquareModel(currentSquare);
boardSquare.Position = new Vector3((float)column, 0.0f, (float)row);
boardSquare.Selected = currentSquare.Equals(selectedSquare);
boardSquare.Render(device);
// Check that the current piece isn't grabbed by the mouse, because in that case we
// don't render it.
if (!currentPieceOrigin.Equals(currentSquare))
{
// Check which kind of model we need to render, move our "template" to the
// right position and render it there.
Model pieceModel = boardGameModelRepository.GetBoardPieceModel(gameLogic[currentSquare]);
if (pieceModel != null)
{
pieceModel.Position = new Vector3((float)column, 0.0f, (float)row);
pieceModel.Render(device);
}
}
}
}
}
/// <summary>
/// This method allows to check for "MouseOver" on Models in 3D space.
/// </summary>
public bool GetMouseOverBlockModel(Device device, int mouseX, int mouseY, out Square square, List<Square> highlightIfHit)
{
selectedSquare = Square.Negative;
square = new Square();
bool foundMatch = false;
float closestMatch = int.MaxValue;
for (int row = 0; row < gameLogic.Rows; ++row)
{
for (int column = 0; column < gameLogic.Columns; ++column)
{
Square currentSquare = new Square(row, column);
Model boardSquare = boardGameModelRepository.GetBoardSquareModel(currentSquare);
boardSquare.Position = new Vector3((float)column, 0.0f, (float)row);
Vector3 near = new Vector3(mouseX, mouseY, 0.0f);
Vector3 far = new Vector3(mouseX, mouseY, 1.0f);
// Unproject a vector from the screen X,Y space into 3D space using the World matrix of the mesh we're checking.
near.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, boardSquare.World);
far.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, boardSquare.World);
far.Subtract(near);
// Find the closes match of all blocks, that is the one the mouse is over.
IntersectInformation closestIntersection;
if (boardSquare.Mesh.Intersect(near, far, out closestIntersection) && closestIntersection.Dist < closestMatch)
{
closestMatch = closestIntersection.Dist;
square = new Square(row, column);
// If a list of squares is passed in we're over one of those squares we highlight that
// this is used to indicated valid moves to the user
if (highlightIfHit != null)
{
foreach (Square highlightSquare in highlightIfHit)
{
if (highlightSquare.Equals(square))
{
selectedSquare = new Square(row, column);
}
}
}
foundMatch = true;
}
}
}
return foundMatch;
}
/// <summary>
/// Picks up a piece, simply marking the currentPieceLocaiton with the location of the picked piece's
/// square so that it not gets rendered by this class.
/// </summary>
/// <param name="pieceLocation"></param>
/// <returns></returns>
public Model PickUpPiece(Square pieceLocation)
{
if (pieceLocation.Row < 0 || pieceLocation.Row >= gameLogic.Rows || pieceLocation.Column < 0 || pieceLocation.Column >= gameLogic.Columns)
return null;
if (gameLogic[pieceLocation] > 0) // TODO: Fix constant for this magic value
{
currentPieceOrigin = pieceLocation;
return boardGameModelRepository.GetBoardPieceModel(gameLogic[pieceLocation]);
}
else
{
return null;
}
}
public void DropPiece()
{
currentPieceOrigin = Square.Negative;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Article videos
Oakmead Apps Android Games
21 Feb 2014: Best VB.NET Article of January 2014 - Second Prize
18 Oct 2013: Best VB.NET article of September 2013
23 Jun 2012: Best C++ article of May 2012
20 Apr 2012: Best VB.NET article of March 2012
22 Feb 2010: Best overall article of January 2010
22 Feb 2010: Best C# article of January 2010