Ground rules

Our game is really starting to come together and I’ve been demanding anyone who sits still for too long plays a game with me. The primary problem there is of all of the people I meet day to day, I’m the only person who has heard of this game so my reluctant opponents have to keep brand new rules in their head while trying to pull together a strategy on the fly. It’s not too easy.

The other problem is the screen display is so small a fingertip covers the piece entirely so it’s possible to accidentally pick the wrong piece and not realise until the move is complete. This is why the undo post came up early.

My solution is to highlight the valid moves when a piece is selected. This leaves people spending less time thinking about what they are allowed to do and more time playing the game, and because the valid move area is going to be substantially larger than the finger of even the most sausage handed among us it’s easier to be sure the right piece has been selected.

There is a slight wrinkle in the deal though. If you want to make up a real chess game then right now all you have to do is paint up some new pieces and ask the activity to lay them out correctly. The board doesn’t know anything about the game being played and I’d like to keep it that way. What we need is a rules engine interface that will let us swap in different rules without changing the board class.

//Board.java
public interface onMoveHandler {
	public void setBoard(int[][] board); 
	public int[][] getValidMoves(int type, int x, int y); 
} 

public void setOnMoveHandler(onMoveHandler moveHandler){ 
	mMoveHandler = moveHandler;
	mMoveHandler.setBoard(mPieces);
}
private onMoveHandler mMoveHandler = null;

We also need a setter function that will accept the new onMoveHandler and store it for later use by the board. It also seems likely that the onMoveHandler will need to access the game state to make decisions, so we pass it back here. Of course, we are passing a reference to the game state, not a copy, so it will always be up to date.

Valid moves are laid out in the same was as the board array, with zeros indicating invalid moves and ones indicating valid normal moves. We are going to hack up a quick and dirty move handler that will declare most squares as valid moves not matter what.

//RPSChess.java
@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);

	getBoard();
	layoutBoard();
	setupMoveHandler();
}

private void setupMoveHandler() {
	b.setOnMoveHandler(new Board.onMoveHandler() {

	int[][] mValidMoves = {{0,1,1,1,1,1,1,1,}
	                          ,{1,0,1,1,1,1,1,1,}
	                          ,{1,1,0,1,1,1,1,1,}
	                          ,{1,1,1,0,1,1,1,1,}
	                          ,{1,1,1,1,0,1,1,1,}
	                          ,{1,1,1,1,1,0,1,1,}
	                          ,{1,1,1,1,1,1,0,1,}
	                          ,{1,1,1,1,1,1,1,0,}

	};
	
	@Override
	public void setBoard(int[][] board) {
	}

	@Override
	public int[][] getValidMoves(int type, int x, int y) {
		return mValidMoves;
	}
});
}

We are going to add a new onDraw subroutine to grab the valid moves and draw them if the mMovingPiece variable is set and the mMoveHandler is set.

//Board.java
@Override public void onDraw(Canvas canvas) { 
	
	drawBoard(canvas);
	
	drawPieces(canvas);
	
	drawValidMoves(canvas);
	
	drawMovingPiece(canvas);
}

Paint mMovePaint = new Paint();
private void drawValidMoves(Canvas canvas) {
	if ((mMovingPiece != 0)&&(mMoveHandler!=null)) {
		int[][] moves = mMoveHandler.getValidMoves(mMovingPiece, mCurrentMove.mFromX, mCurrentMove.mFromY);
		for (int i = 0 ; i < moves.length ; i++){ 
			for (int j = 0 ; j < moves[i].length ; j++) { 
				if (moves[i][j]==1) { 
					canvas.drawRect(i * mTileWidth , j * mTileHeight , (i+1) * mTileWidth , (j+1) * mTileHeight , mMovePaint); 
				} 
			} 
		} 
	} 
}

This sets up the painting order as: First the board, then the unmoving pieces, then the move/capture highlights, then the moving piece. This tints the capture pieces as well, but leaves the moving piece in it’s original colour scheme.

All that remains is to set up the mMovePaint object so the finished result looks the part.

//Board.java
public Board(Context context, AttributeSet attrs) {
	super(context, attrs);

	mDark.setColor(Color.parseColor("#AAAA88")); 
	mMovePaint.setColor(Color.parseColor("#00FF00")); 
	mMovePaint.setAlpha(100);
}

We are setting the mMovePaint to be a bright green colour. We are also using the setAlpha() function on the paint objects to make the highlights slightly transparent.

The last step is to validate the move the player makes. If they complete a move onto a square where the mMoves flag is zero, then we automatically undo the move and let them try again.

//Board.java
private boolean handleUpAction(MotionEvent event) {
	mCurrentMove.mToX = (int)(event.getX() / mTileWidth); 
	mCurrentMove.mToY = (int)(event.getY() / mTileHeight);
	
	if ((mCurrentMove.mFromX != mCurrentMove.mToX)||(mCurrentMove.mFromY != mCurrentMove.mToY)) {
		mCurrentMove.mTakenPiece = mPieces[mCurrentMove.mToX][mCurrentMove.mToY];
		mPieces[mCurrentMove.mToX][mCurrentMove.mToY] = mMovingPiece; 
		
		mHistory.push(mCurrentMove);
		if ((mMoveHandler!=null)&&(mMoveHandler.getValidMoves(mMovingPiece, mCurrentMove.mFromX, mCurrentMove.mFromY)[mCurrentMove.mToX][mCurrentMove.mToY])==0) {undo();}
		mCurrentMove = new Move();
	}else
		mPieces[mCurrentMove.mToX][mCurrentMove.mToY] = mMovingPiece; 

	mMovingPiece = 0;
	
	invalidate(); 
	return true;
}

Once again the dread invalidate() is left short for clarity. You can see this is more effort than is required to achieve the effect, but it means we can create a private class in the activity that implements the same interface but that actually defines the rules of the game. With that in hand we get a much more robust experience; the players can see the valid moves as they play and can work out which piece is selected even if they can’t see it directly.

But wait a minute, if we try this out the highlights are only visible just around the moving piece. That’s because the highlights are only drawn in the invalid areas. We need to invalidate the whole screen during the down action.

//Board.java
private boolean handleDownAction(MotionEvent event) {
	int x = (int)(event.getX() / mTileWidth); 
	int y = (int)(event.getY() / mTileHeight);

	if (mPieces[x][y] != 0) {
		mMovingX = event.getX(); 
		mMovingY = event.getY();
		invalidate();

		mCurrentMove.mFromX = x;
		mCurrentMove.mFromY = y;
		mMovingPiece = mPieces[x][y];
		mPieces[x][y] = 0; 
		return true;
	}else
		return false;
}

An extension that could be worked in here would be to highlight moves and captures in different colours, or perhaps valid and invalid moves. It’s all about what is returned from getValidMoves, how that is painted during the draw and how the handleUpAction() function reacts. In this case my focus group (Hi honey!) advised that a single colour highlighting the valid moves was the way to go.

There is one critical problem with all of this though. I don’t like it. There’s a maximum of eight possible moves that can be made at any given time and in many games you wouldn’t even get that, yet we’re scanning a relatively large structure that we painstakingly construct just in case. There is a very neat solution to this though, which we will take a look at next week.

The valid moves are highlighted on the board

Valid Moves

This entry was posted in android and tagged . Bookmark the permalink.

17 Responses to Ground rules

  1. NSD says:

    Hi Chris,

    I have one doubt can we create a checker/chess board using XML ? If we can use XML , how to place the coins over it randomly but each player should have similar coins.? If we can use XML how can we highlight over the XML Board.? If we can use use XML , how can we move the coins horizontal , vertical and diagonal?

    I have on issue, I have “five different squares”, the property of each squares are different. Like “Plain Square”, where the coins placed over the plain square can move in horizontal and vertical; “Pattern Square”, where the coins placed over the pattern square can move in diagonal direction; “Image1 Square”, where we can have only one move in all directions; “Image2 Square”, where we can have only two move in all directions;”Image3 Square”, where we can have only three move in all directions. These are the five different squares, if you can solve this problem, that would be great help to me.

    Thanks & Regards,
    NSD.

    • Chris says:

      I don’t think we can create a chess board with just XML. I could be wrong, there’s plenty about Android programming I’m still learning, but I don’t know how to do it.

      Your “five different squares” sounds very interesting, if you get it running please post a link so we can take a look. You could copy the MoveHandler I’ve posted in this article, but instead of making the moves depend on the piece type, they would depend on the tile. You could set up another array similar to the mPieces array, but for the tile types and pass that to the move handler too. I imagine the board would need one anyway so it knows which tile image to draw where.

      I hope that helps.

  2. kumar says:

    Hi,

    Where you mentioned the blue and red color images.can you send that code.i did not understand where you mentioned.
    cheers,
    kumar

  3. kumar says:

    HI,

    I created board with alternative colors and i placed coins on the board.i need to move the coins in horizontally and vertically .Please send me the code how to move the coins and how to highlight the path. I am waiting for you early and prompt reply. Can you please send your personal email address because , i need to send the code. so that you can understand the problem in my application.

  4. santhosh says:

    Hi,
    I was little confused in highlighting the path and where exactly i’ve to place the setOnMoveHandler(onMoveHandler moveHandler) in the Board class or else could you please provide me the link for this entire GAME code

    Thanks & Regards
    Santhosh

    • Chris says:

      The setOnMoveHandler() function can just be added anywhere in the Board class and it should be called from the Activity. I’ve put the MoveHandler interface into the Board class too although that is not needed. It has minor effects elsewhere in the code but nothing signigicant.

      You can see from the posts that the app is still under active development, including ripping out and re-implementing bits of the MoveHandler in the next post, so I’m not willing to post the whole code yet. Once it’s finally all in order I will be posting the finished code, but until then I’ll have to disappoint you.

  5. NSD says:

    Hi Chris,
    Thanks Chris for the reply. Once I solve the issue, i will sure post the link to you. Using your tutorial I have solved some issues in my project. But, I have one issue on the moving the checkers. We are using onTouch events, but instead of that i want to use motion for the checker, where on first click on the checker it should highlight the path and choose any one of the selected path and on second double click it should show the motion of the checker in a slow & visible motion diagonal and horizontal & vertical path. If you can help me out, it would be great help.

    Thanks & Regards,
    NSD.

    • Chris says:

      The first part of your question should be easy enough. Instead of handling the DOWN, MOVE and UP touch events, you are going to have to do everything in the DOWN event. You will need a flag to indicate you are either at the start of a move or in the middle of a move, and then move the right parts of the UP event code into the new section. I checked if mMoves was null to say I was waiting for the user to pick their piece and if mMoves was set then we were waiting for the user to select a move. I started setting my game up with this kind of control scheme, but it’s littered with too many assumptions to make it work easily so I can’t give you code snippets just now.

      Animation should be simple enough too, but it’s not something I have done. You sound like you are looking for Tween animation, which should be well documented but it’s not something I can help you with I’m afraid.

      It sounds like an excellent avenue of investigation so I will add it to the queue of posts. It will be a few weeks until I get around to it though.

  6. NSD says:

    Hi Chris,
    Thanks for the reply. I have one doubt in your tutorial that, to generate the board you are using canvas and filling the board with two colors cream and gray.
    Instead of filling the squares pieces with colors, can I use Image to fill the each square piece. Why am I asking this because I have a square piece which is filled with pattern lines, over the pattern lines I have a circle and the a number is placed at four corners. On that type of square piece in need to place a coin.
    So, Can I use images on canvas? If I can use them will it give problems in future?
    Hope you can help me out….

    With Warm Regards,
    NSD.

    • Chris says:

      You can use canvas.drawbipmap to lay out your images just like you would lay out your pieces. As long as you draw them first in onDraw() they will appear underneath your pieces just like the board currently does. I can’t imagine you will run into problems laying out your board like this as long as you are careful with your invalidate() calls.

  7. NSD says:

    Hi Chris,
    Thanks for the information and guidelines. I will try out with what you have said.

    Thanks & Regards,
    NSD

  8. Mayuri says:

    Hi Everyone..

    I am stuck in a problem while developing a app….please help me with this problem
    Q)I have two activities A and B.., A activity contains a list of icons and B activity contains three tabs with a search box( like google) and i have list of names..now

    when i click on a icon in A activity it should show the list of names along with the first tab selection present in the B activity directly, with out giving any search

    option…

    NOTE:-In B activity i used three XML files for tabs, search box and list view…

    ….Please any one help me on this issue am stuck
    Thanks in advance

    • Chris says:

      Hi,

      I’m not sure where you are having problems. Are you having problems getting the first activity to call the second or some kind of display issue? The more detail you can give us, the better.

  9. NSD says:

    Hi Chris,
    Good Morning ! How are you? I would like to inform you that I am able to design a board and place the checkers over it and able to highlight the path.
    I would like to know, how to write a game design document ? Why we use/need this game design document? Could you send a sample game design document / link to design document of any checker game? That will be a great help. Waiting for your reply.

    Thanks & Regards,
    NSD.

    • Chris says:

      Good stuff, I’m glad you are making progress.

      Game design documents are essentially program specifications. They are needed to let different teams work together. To take the example of my own poor art skills: I could hire an artist to design my board and pieces, moving highlights, capture highlights and any animations, but before I set them to work I would need to know, in reasonable detail, what I wanted. Beyond the list of drawables I’d need to specify themes. Do I want a modern feel or something ancient and dusty looking?

      It would also be of use if I was involving a third party company, say a publisher or similar. I could make deals with them based of the design document before a single line of code is written. Another example would be getting my games rewritten for the iPhone. I can produce everything for Android, then pass the artwork and design document to an iPhone development house and let them get on with it.

      I’m not working from one though. I’ve started with a basic idea (from a webcomic) and I’m applying basic Android features to it wherever they make sense. Drawing graphics, playing with menus and soon I’ll be looking at data storage. The only thing I have as a guiding principle is making sure I don’t put something in that doesn’t belong. There will be other projects with accelerometers, music and so forth.

      I hope that helps.

Comments are closed.