Five Steps to Create a Chess App 4/5

Step 4: drawing pieces on board

拇指 muzhi.com
Analytics Vidhya
Published in
6 min readOct 11, 2019

--

Summary of previous 3 steps:

Step 1: created chess app from scratch

Step 2: added a view for our chess board

Step 3: drew 8x8 chess board

We need 12 piece images, 6 white and 6 black, to represent 32 pieces on board. Try to search whatever images you like and download them into, e.g. “Downloads” folder. The image files used in this tutorial can be found here.

12 piece images ready for use

Go back to Xcode and click “Assets.xcassets” on the left navigation panel. We’ll drag and drop all 12 piece images onto the big white area under “AppIcon”.

click “Assets.xcassets” on the left navigation panel

You can drag pieces one by one, or select all and drag them all together.

select all 12 piece images i Finder

When finished the pieces look like the following in Xcode. We’ll use the name of each image to create UIImage object shortly. E.g, the name of black bishop image is “Bishop-black”, case sensitive.

each image has a name, e.g “Biship-black”

Time for writing some code. We’ll create a struct representing a piece. Right click the yellow “Chess” folder on the left navigation panel and select “New File…”. Select “Swift File” under “iOS”. Then click “Next” button to continue.

we’ll create a Swift file

Input the very creative name “ChessPiece” and click “Create” button.

click “Create” button to create file ChessPiece.swift

Here is what it looks like when created.

when created, ChessPiece.swift is almost empty

We need two integers “col” and “row” for the location of a piece on logical chess board. Each piece also keep a field “imageName” for its own image name, e.g. “Bishop-black”. “Hashable” is needed when we use “Set” to contain objects of type ChessPiece.

import Foundationstruct ChessPiece: Hashable {
let col: Int
let row: Int
let imageName: String
}
struct ChessPiece has 3 properties, or fields

Move on to create another struct for our game engine, which will hold all the pieces on board. If you ever heard of MVC design pattern, this is the M, meaning Model.

create anoter swift file under folder “Chess”

Key in “ChessEngine” and click “Create” button to continue.

click “Create” button to create file ChessEngine.swift

ChessEngine.swift is created but still empty.

we created ChessEngine.swift after ChessPiece.swift

ChessEngine keeps a set of pieces. We create a convenient function to insert all 32 initial pieces into property “pieces”.

create property “pieces” and function “initializeGame”

Here is the complete code of ChessEngine.swift:

import Foundationstruct ChessEngine {
var pieces = Set<ChessPiece>()

mutating func initializeGame() {
pieces.removeAll()

// ...
}
}

Put the following code in the place of “// …” above.

pieces.insert(ChessPiece(col: 0, row: 0, imageName: "Rook-black"))
pieces.insert(ChessPiece(col: 7, row: 0, imageName: "Rook-black"))
pieces.insert(ChessPiece(col: 0, row: 7, imageName: "Rook-white"))
pieces.insert(ChessPiece(col: 7, row: 7, imageName: "Rook-white"))
pieces.insert(ChessPiece(col: 1, row: 0, imageName: "Knight-black"))
pieces.insert(ChessPiece(col: 6, row: 0, imageName: "Knight-black"))
pieces.insert(ChessPiece(col: 1, row: 7, imageName: "Knight-white"))
pieces.insert(ChessPiece(col: 6, row: 7, imageName: "Knight-white"))
pieces.insert(ChessPiece(col: 2, row: 0, imageName: "Bishop-black"))
pieces.insert(ChessPiece(col: 5, row: 0, imageName: "Bishop-black"))
pieces.insert(ChessPiece(col: 2, row: 7, imageName: "Bishop-white"))
pieces.insert(ChessPiece(col: 5, row: 7, imageName: "Bishop-white"))
pieces.insert(ChessPiece(col: 3, row: 0, imageName: "Queen-black"))
pieces.insert(ChessPiece(col: 3, row: 7, imageName: "Queen-white"))
pieces.insert(ChessPiece(col: 4, row: 0, imageName: "King-black"))
pieces.insert(ChessPiece(col: 4, row: 7, imageName: "King-white"))
pieces.insert(ChessPiece(col: 0, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 1, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 2, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 3, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 4, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 5, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 6, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 7, row: 1, imageName: "Pawn-black"))
pieces.insert(ChessPiece(col: 0, row: 6, imageName: "Pawn-white"))
pieces.insert(ChessPiece(col: 1, row: 6, imageName: "Pawn-white"))
pieces.insert(ChessPiece(col: 2, row: 6, imageName: "Pawn-white"))
pieces.insert(ChessPiece(col: 3, row: 6, imageName: "Pawn-white"))
pieces.insert(ChessPiece(col: 4, row: 6, imageName: "Pawn-white"))
pieces.insert(ChessPiece(col: 5, row: 6, imageName: "Pawn-white"))
pieces.insert(ChessPiece(col: 6, row: 6, imageName: "Pawn-white"))
pieces.insert(ChessPiece(col: 7, row: 6, imageName: "Pawn-white"))

Let’s move on to add 2 lines of code in ViewController.swift. To create an instance of ChessEngine, add the following code above “override func viewDidLoad() {”.

var chessEngine = ChessEngine()

And add the following code under “super.viewDidLoad()” to initalize our chess game, i.e. deploying all 32 pieces in place.

chessEngine.initializeGame()

Now we arrive at the trickiest and most interesting part of this assignment. We need to build the connection between the screen element and the code. In our case it means ctrl dragging from the white board view to somewhere inside file ViewController.swift. To make that happen, both files have to show up side by side. On left navigation panel, click ViewController.swift first, then hold on “option” key and click Main.storyboard.

Click the white board view on the right to select it. With control key being held, start dragging from board view to the empty area above “override func viewDidLoad() {”. When you release mouse, A dialog box pops up.

a dialog pops up when dragging finishes

Give the connection its name “boardView”. Then click “Connect” button to hide the dialog.

input “boardView” and click “Connect” button

Xcode inserts the following line of code. This variable “boardView” represents the white view on screen.

@IBOutlet weak var boardView: BoardView!
Xcode inserts variable boardView of type BoardView!

Now let’s go back to file BoardView.swift to add code for pieces drawing. We create an instance variable pieces of type Set<ChessPiece>. Think it as the shadow pieces box of the one in ChessEngine, which is the variable pieces defined in ChessEngine. We also create a function to draw all pieces.

write code in BoardView.swift

The complete code in BoardView.swift follows.

import UIKitclass BoardView: UIView {
var pieces = Set<ChessPiece>()
override func draw(_ rect: CGRect) {
drawBoard()
drawPieces()
}

func drawPieces() {
for piece in pieces {
let pieceImage = UIImage(named: piece.imageName)
pieceImage?.draw(in: CGRect(x: piece.col * 80, y: piece.row * 80, width: 80, height: 80))
}
}
func drawBoard() {
drawTwoRowsAt(y: 0 * 80)
drawTwoRowsAt(y: 2 * 80)
drawTwoRowsAt(y: 4 * 80)
drawTwoRowsAt(y: 6 * 80)
}

func drawTwoRowsAt(y: CGFloat) {
drawSquareAt(x: 1 * 80, y: y)
drawSquareAt(x: 3 * 80, y: y)
drawSquareAt(x: 5 * 80, y: y)
drawSquareAt(x: 7 * 80, y: y)

drawSquareAt(x: 0 * 80, y: y + 80)
drawSquareAt(x: 2 * 80, y: y + 80)
drawSquareAt(x: 4 * 80, y: y + 80)
drawSquareAt(x: 6 * 80, y: y + 80)
}

func drawSquareAt(x: CGFloat, y: CGFloat) {
let path = UIBezierPath(rect: CGRect(x: x, y: y, width: 80, height: 80))
UIColor.lightGray.setFill()
path.fill()
}
}

Go back to file ViewController.swift to add 2 lines of code. Line 21 updates the shadow pieces (box) in boardView from the main pieces (box) in chessEngine. Line 22 tells the system to redraw everything on screen.

add 2 lines to re-render UI after 32 pieces are initialized in chessEngine

Here is the complete code of ViewController.swift.

import UIKitclass ViewController: UIViewController {

var chessEngine = ChessEngine()
@IBOutlet weak var boardView: BoardView!

override func viewDidLoad() {
super.viewDidLoad()

chessEngine.initializeGame()
boardView.pieces = chessEngine.pieces
boardView.setNeedsDisplay()
}
}

Run the app to enjoy these lovely pieces.

32 pieces in the initial chess board

--

--