- Home /
About my Game project which is 2D chess Game: ,I am have a problem with my game project it is a 2D chess game.
I want to add 2 functions to it and then I am finished. The first function is I want instead of dragging a piece on the chess board to move it I want to click on it then it will show where the chess piece can go and then click on the place where I want to move it after that the chess piece should move. The second function I want is when I move a chess piece I want it to show from where the chess piece moved as you can see where the blue arrow is pointing just to show you what I mean in the picture below it came from the chess titan game from Windows 7 if you didn't know, you can see that the king moved from the place where the blue arrow is point to, that's what I want the second function do it doesn't have to be the same shape as in the picture I just wanted it to do the same.
I almost finished everything. I am a beginner in Unity and programming I just wanted to try to make a game with help of YouTube of course. Please if you how to do these functions just let me know if you could write the code for me I would be more than happy instead of just explaining how to do it because I know what I want to do but I don't know how to write it in codes. If you don't want to write the code its fine with me maybe an explanation will gives me some idea on what to search for or what to do.
This is the script that is responsible for the pieces. This is my first time using this website. Also When I added the OnPointerClick function whenever I click on a chess pieces it gives me "NullRefrenceException: Object reference not set to an instance of an object" why is that?
One last thing I forgot to say is that the OnPointerClick function it worked for me perfectly but the only problem with me was I can't move the chess pieces. It always gave me this null reference exception error that I talked about above. I saw so many videos and so many links in google and none of them helped me even a little bit to be fair just one of the 30+ videos i saw helped me a little on what types of click functions are there for the mouse and that's it.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using UnityEngine.Events;
using System;
public abstract class BasePiece : EventTrigger, IPointerClickHandler
{
[HideInInspector]
public Color mColor = Color.clear;
public bool mIsFirstMove = true;
protected Cell mOriginalCell = null;
protected Cell mCurrentCell = null;
protected RectTransform mRectTransform = null;
protected PieceManager mPieceManager;
protected Cell mTargetCell = null;
protected Vector3Int mMovement = Vector3Int.one;
protected List<Cell> mHighlightedCells = new List<Cell>();
public virtual void Setup(Color newTeamColor, Color32 newSpriteColor, PieceManager newPieceManager)
{
mPieceManager = newPieceManager;
mColor = newTeamColor;
GetComponent<Image>().color = newSpriteColor;
mRectTransform = GetComponent<RectTransform>();
}
public virtual void Place(Cell newCell)
{
// Cell stuff
mCurrentCell = newCell;
mOriginalCell = newCell;
mCurrentCell.mCurrentPiece = this;
// Object stuff
transform.position = newCell.transform.position;
gameObject.SetActive(true);
}
public void Reset()
{
Kill();
mIsFirstMove = true;
Place(mOriginalCell);
}
public virtual void Kill()
{
// Clear current cell
mCurrentCell.mCurrentPiece = null;
// Remove piece
gameObject.SetActive(false);
}
#region Movement
private void CreateCellPath(int xDirection, int yDirection, int movement)
{
// Target position
int currentX = mCurrentCell.mBoardPosition.x;
int currentY = mCurrentCell.mBoardPosition.y;
// Check each cell
for (int i = 1; i <= movement; i++)
{
currentX += xDirection;
currentY += yDirection;
// Get the state of the target cell
CellState cellState = CellState.None;
cellState = mCurrentCell.mBoard.ValidateCell(currentX, currentY, this);
// If enemy, add to list, break
if (cellState == CellState.Enemy)
{
mHighlightedCells.Add(mCurrentCell.mBoard.mAllCells[currentX, currentY]);
break;
}
// If the cell is not free, break
if (cellState != CellState.Free)
break;
// Add to list
mHighlightedCells.Add(mCurrentCell.mBoard.mAllCells[currentX, currentY]);
}
}
protected virtual void CheckPathing()
{
// Horizontal
CreateCellPath(1, 0, mMovement.x);
CreateCellPath(-1, 0, mMovement.x);
// Vertical
CreateCellPath(0, 1, mMovement.y);
CreateCellPath(0, -1, mMovement.y);
// Upper diagonal
CreateCellPath(1, 1, mMovement.z);
CreateCellPath(-1, 1, mMovement.z);
// Lower diagonal
CreateCellPath(-1, -1, mMovement.z);
CreateCellPath(1, -1, mMovement.z);
}
protected void ShowCells()
{
foreach (Cell cell in mHighlightedCells)
cell.mOutlineImage.enabled = true;
}
protected void ClearCells()
{
foreach (Cell cell in mHighlightedCells)
cell.mOutlineImage.enabled = false;
mHighlightedCells.Clear();
}
protected virtual void Move()
{
// First move switch
mIsFirstMove = false;
// If there is an enemy piece, remove it
mTargetCell.RemovePiece();
// Clear current
mCurrentCell.mCurrentPiece = null;
// Switch cells
mCurrentCell = mTargetCell;
mCurrentCell.mCurrentPiece = this;
// Move on board
transform.position = mCurrentCell.transform.position;
mTargetCell = null;
SoundManager.PlaySound();
}
#endregion
#region Events
public override void OnBeginDrag(PointerEventData eventData)
{
base.OnBeginDrag(eventData);
// Test for cells
CheckPathing();
// Show valid cells
ShowCells();
}
public override void OnDrag(PointerEventData eventData)
{
base.OnDrag(eventData);
// Follow pointer
transform.position += (Vector3)eventData.delta;
// Check for overlapping available squares
foreach (Cell cell in mHighlightedCells)
{
if (RectTransformUtility.RectangleContainsScreenPoint(cell.mRectTransform, Input.mousePosition))
{
// If the mouse is within a valid cell, get it, and break.
mTargetCell = cell;
break;
}
// If the mouse is not within any highlighted cell, we don't have a valid move.
mTargetCell = null;
}
}
public override void OnEndDrag(PointerEventData eventData)
{
base.OnEndDrag(eventData);
// Hide
ClearCells();
// Return to original position
if (!mTargetCell)
{
transform.position = mCurrentCell.gameObject.transform.position;
return;
}
// Move to new cell
Move();
// End turn
mPieceManager.SwitchSides(mColor);
}
public override void OnPointerClick(PointerEventData eventData)
{
base.OnPointerClick(eventData);
// Test for cells
CheckPathing();
// Show valid cells
ShowCells();
Move();
// Hide
ClearCells();
// End turn
mPieceManager.SwitchSides(mColor);
}
#endregion
}
}
This is the second script that is also responsible for moving the pieces If there is something you didn't understand from me please tell me.
public class PieceManager : MonoBehaviour
{
[HideInInspector]
public bool mIsKingAlive = true;
public GameObject mPiecePrefab;
private List<BasePiece> mWhitePieces = null;
private List<BasePiece> mBlackPieces = null;
private List<BasePiece> mPromotedPieces = new List<BasePiece>();
private string[] mPieceOrder = new string[16]
{
"P", "P", "P", "P", "P", "P", "P", "P",
"R", "KN", "B", "Q", "K", "B", "KN", "R"
};
private Dictionary<string, Type> mPieceLibrary = new Dictionary<string, Type>()
{
{"P", typeof(Pawn)},
{"R", typeof(Rook)},
{"KN", typeof(Knight)},
{"B", typeof(Bishop)},
{"K", typeof(King)},
{"Q", typeof(Queen)}
};
public void Setup(Board board)
{
// Create white pieces
mWhitePieces = CreatePieces(Color.white, new Color32(80, 124, 159, 255));
// Create place pieces
mBlackPieces = CreatePieces(Color.black, new Color32(210, 95, 64, 255));
// Place pieces
PlacePieces(1, 0, mWhitePieces, board);
PlacePieces(6, 7, mBlackPieces, board);
// White goes first
SwitchSides(Color.black);
}
private List<BasePiece> CreatePieces(Color teamColor, Color32 spriteColor)
{
List<BasePiece> newPieces = new List<BasePiece>();
for (int i = 0; i < mPieceOrder.Length; i++)
{
// Get the type
string key = mPieceOrder[i];
Type pieceType = mPieceLibrary[key];
// Create
BasePiece newPiece = CreatePiece(pieceType);
newPieces.Add(newPiece);
// Setup
newPiece.Setup(teamColor, spriteColor, this);
}
return newPieces;
}
private BasePiece CreatePiece(Type pieceType)
{
// Create new object
GameObject newPieceObject = Instantiate(mPiecePrefab);
newPieceObject.transform.SetParent(transform);
// Set scale and position
newPieceObject.transform.localScale = new Vector3(1, 1, 1);
newPieceObject.transform.localRotation = Quaternion.identity;
// Store new piece
BasePiece newPiece = (BasePiece)newPieceObject.AddComponent(pieceType);
return newPiece;
}
private void PlacePieces(int pawnRow, int royaltyRow, List<BasePiece> pieces, Board board)
{
for (int i = 0; i < 8; i++)
{
// Place pawns
pieces[i].Place(board.mAllCells[i, pawnRow]);
// Place royalty
pieces[i + 8].Place(board.mAllCells[i, royaltyRow]);
}
}
private void SetInteractive(List<BasePiece> allPieces, bool value)
{
foreach (BasePiece piece in allPieces)
piece.enabled = value;
}
public void SwitchSides(Color color)
{
if (!mIsKingAlive)
{
// Reset pieces
ResetPieces();
// King has risen from the dead
mIsKingAlive = true;
// Change color to black, so white can go first again
color = Color.black;
}
bool isBlackTurn = color == Color.white ? true : false;
// Set team interactivity
SetInteractive(mWhitePieces, !isBlackTurn);
// Disable this so player can't move pieces
SetInteractive(mBlackPieces, isBlackTurn);
// Set promoted interactivity
foreach (BasePiece piece in mPromotedPieces)
{
bool isBlackPiece = piece.mColor != Color.white ? true : false;
bool isPartOfTeam = isBlackPiece == true ? isBlackTurn : !isBlackTurn;
piece.enabled = isPartOfTeam;
}
}
public void ResetPieces()
{
foreach (BasePiece piece in mPromotedPieces)
{
piece.Kill();
Destroy(piece.gameObject);
}
mPromotedPieces.Clear();
// Reset white
foreach (BasePiece piece in mWhitePieces)
piece.Reset();
//Reset black
foreach (BasePiece piece in mBlackPieces)
piece.Reset();
}
public void PromotePiece(Pawn pawn, Cell cell, Color teamColor, Color spriteColor)
{
// Kill Pawn
pawn.Kill();
// Create
BasePiece promotedPiece = CreatePiece(typeof(Queen));
promotedPiece.Setup(teamColor, spriteColor, this);
// Place piece
promotedPiece.Place(cell);
// Add
mPromotedPieces.Add(promotedPiece);
}
}
Thanks in Advance. Any help would be appreciated.
Answer by Llama_w_2Ls · Dec 21, 2020 at 10:40 AM
The first function really takes some time to implement. One easy way to do this, is to create classes for every type of piece on the chess board, and give it rules, on where it can move every turn. This will allow you to simply draw on the board, which squares they can move onto. (This also requires you to have identifiers for each square on the board).
For example, if we create a GameManager class to handle the movement of pawns and queens, it would look something like:
public class GameManager : MonoBehaviour
{
void MovePiece(Pawn pawn)
{
}
void MovePiece(Queen queen)
{
}
}
public class Pawn
{
// Info about what it looks like etc...
}
public class Queen
{
// Info about what it looks like etc...
}
The function, MovePiece()
can be replicated multiple times, containing different parameters for each piece. In these functions, you might want to decide what squares they can move onto, depending on what square they are on now.
For example, the pawn class would look more like:
public class GameManager : MonoBehaviour
{
public Square[] Grid = new Square[64];
void MovePiece(Pawn pawn)
{
if (pawn.HasMoved)
{
// Pawn can only move one square forward
// which is the pawn's current index in the
// Grid array plus 8 (one down in the array)
}
else
{
// Pawn can move one OR two squares forward
// which is the pawn's current index in the
// Grid array plus 8 OR plus 16 (one OR two
// down in the array)
}
// Make sure to update the pawn's CurrentSquare value
// to the new square that it is on
}
}
public class Pawn
{
// Pawns can move two squares forward on their first move
// but only one from then on
public bool HasMoved;
// Current position on the board
public Square CurrentSquare;
}
public class Square
{
// Info about where it is on the grid
}
This time, I've added a square class and an array of 64 squares called Grid which should help keep track of where everything is on the grid.
This hopefully should help you get started and give you some ideas about what to do next. Programming how to move and how the grid is understood by the GameManager is up to your skills now. I'm not so happy about doing this for you or programming anything any further because frankly, this seems like a large project that I'm doing for free, and I only want to assist. Not take the lead. I hope this helps @Malekob
One more thing, I do know that you are a beginner, and a word of advice would be, not to jump straight into using classes as objects, without knowing what they are capable of and how to use them correctly. I would advise you to work on smaller projects, and work your way up to something like chess. In the meantime, try tic-tac-toe as an exercise. But that's just my advice and it's up to you what you want to do in your career.
Your answer
Follow this Question
Related Questions
Android Stockfish chess engine error on call 1 Answer
Question about variabl lists 1 Answer
Help optimizing my code for chess game 1 Answer
How to validate chess moves with a server? Winboard and Unity 2020.3 0 Answers
Board games in Unity 1 Answer