昨日の続き。
今日はボードの描画を実装していく。
ボードの描画
ボードの描画は、SKSpriteNodeを継承したBoardNodeを作って実装する。
//============================== // YWF //------------------------------ // BoardNode.swift //============================== import SpriteKit public class BoardNode: SKSpriteNode { // 続く
トークンの位置
まず、トークンの位置をクラス定数として用意しておく。
// 続き private static let tokenPosition = [ Board.Status.Bad: CGPoint(x: SquareNode.size.width * CGFloat(-5), y: SquareNode.size.height * CGFloat(-4)), Board.Status.Common: CGPoint(x: SquareNode.size.width * CGFloat(-5), y: 0.0), Board.Status.Good: CGPoint(x: SquareNode.size.width * CGFloat(-5), y: SquareNode.size.height * CGFloat(4)), ] // 続く
なお、以前作ったBoardクラスでは、マスの情報を表すのにBoard.Colorという列挙型を使っていたけど、もはや黒/灰色/白というのではなく、悪い子/普通の子/良い子という表現の方がいいので、Board.Statusという列挙型に変えて、列挙子も.Bad/.Common/.Goodに変えている。
画像のロード
駒と同様に、ボードの画像をロードするクラスメソッドを用意する。
// 続き private static var textures = [String: SKTexture]() public class func loadAssets() { let atlas = SKTextureAtlas(named: "Board") let names = ["BoardBase", "BoardOver", "Token"] for name in names { BoardNode.textures[name] = atlas.textureNamed(name) } }
特筆すべきことは、特にないかな?
Board.atlasというTextureAtlasを用意して、それを読み込み、texturesというクラス変数に格納しているだけ。
プロパティとイニシャライザ
次はプロパティとイニシャライザ。
// 続き private var board: Board private var squares: [[SquareNode!]] private var token: SKSpriteNode! public init(board: Board) { self.board = board self.squares = [ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], ] self.token = nil let baseTexture = BoardNode.textures["BoardBase"]! super.init(texture: baseTexture, color: SKColor.whiteColor(), size: baseTexture.size()) for row in Board.RowMin...Board.RowMax { for col in Board.ColMin...Board.ColMax { self.squares[row][col] = SquareNode(row: row, col: col) self.squares[row][col].position.x = SquareNode.size.width * CGFloat(col - 5) self.squares[row][col].position.y = SquareNode.size.height * CGFloat(5 - row) self.addChild(self.squares[row][col]) } } let overTexture = BoardNode.textures["BoardOver"]! let over = SKSpriteNode(texture: overTexture) self.addChild(over) self.token = SKSpriteNode(texture: BoardNode.textures["Token"]) self.token.position = BoardNode.tokenPosition[.Common]! self.addChild(token) for row in Board.RowMin...Board.RowMax { for col in Board.ColMin...Board.ColMax { switch board.status(row, col) { case .Bad: self.squares[row][col].addPiece(.Bad) case .Common: self.squares[row][col].addPiece(.Common) case .Good: self.squares[row][col].addPiece(.Good) default: break } } } let tokenPosition = BoardNode.tokenPosition[board.token]! self.token.position = tokenPosition self.userInteractionEnabled = true } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 続く
プロパティとしては、モデルとなるボードと、マスのインスタンスを入れる二次元配列、それとトークンを持っている。
そして、イニシャライザでは、モデルとなるボードを受け取って、それにしたがって対応するマスに駒を配置したり、トークンの位置を変えたりしている。
タッチされたマスの検出
最後に、タッチされたマスの検出の実装。
// 続き public override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) { let touch = touches.first as! UITouch let location = touch.locationInNode(self) loop: for node in self.nodesAtPoint(location) { switch node { case let squareNode as SquareNode: println("row: \(squareNode.row), col: \(squareNode.col)") break loop default: break } } } }
とりあえずはタッチされたマスの場所をコンソールに出力するだけ。
ポイントは、タッチされた場所にあるノードの集まりからSquareNodeを探しているところ。
SquareNodeが見つかれば、その情報を見ることで、タッチされたマスの場所を簡単に知ることが出来る。
ボードの描画の動作確認
ボードの描画の動作確認をするために、コントローラのコードをちょろっと書き換える。
//============================== // YWF //------------------------------ // GameViewController.swift //============================== import UIKit import SpriteKit class GameViewController: UIViewController { @IBOutlet weak var skView: SKView! override func viewDidLoad() { BoardNode.loadAssets() PieceNode.loadAssetsAndCreateTemplates() } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) var size = self.view.bounds.size if UIDevice.currentDevice().userInterfaceIdiom == .Phone { size.height *= 2 size.width *= 2 } let scene = GameScene(size: size) scene.scaleMode = .AspectFill let backgroundTexture = SKTexture(imageNamed: "Background") let background = SKSpriteNode(texture: backgroundTexture) background.position = CGPoint(x: scene.frame.width/2, y: scene.frame.height/2) scene.addChild(background) var board = Board() board = board.play(6, 7) board = board.play(7, 6) board = board.change(6, 6) board = board.play(5, 7) let boardNode = BoardNode(board: board) background.addChild(boardNode) self.skView.presentScene(scene) } // hide status bar. override func prefersStatusBarHidden() -> Bool { return true } }
やっているのは、モデルとなるボードのインスタンスを用意して、そこからBoardNodeを作り、表示させているだけ。
これを実行すると、以下のような表示がされる。
マスをタッチすると、タッチされたマスの情報もコンソールに表示される。
今日はここまで!