ユーザ情報の表示も出来た。
あとはゲームの結果を表示したりも必要だけど、かなり長くなったので、とりあえずまとめていく。
ターンコントローラの修正
とりあえず、終了判定の実装だけは入れておく。
//============================== // YWF //------------------------------ // TurnController.swift //============================== import Foundation public class TurnController: BoardNodeObserver, ButtonNodeObserver { // 省略 public func boardNodeActionIsFinished(node: BoardNode) { if self.undoOperation != nil { if self.undoOperation.finished { let board = self.boardNode.board let turnPlayer = (board.turn == .Bad) ? self.badPlayer : self.goodPlayer if board.move > 0 && turnPlayer.isCom { // turn player is not human, // so undo again. self.undoOperation = NSBlockOperation { self.boardNode.undo() } self.queue.addOperation(self.undoOperation) return } else { // undo has been finished. self.undoOperation = nil if let lastAction = self.boardNode.lastAction { switch lastAction { case let .Play(row, col): self.boardNode.lightUpSquare(row, col, withOpponent: true) case let .Change(row, col): self.boardNode.lightUpSquare(row, col, withOpponent: true) default: break } } } } else { // do nothing, // because undo has been requested and not been finished. return } } if self.boardNode.board.isGameEnd { let winner: Player! if self.boardNode.board.win(.Bad) { winner = self.badPlayer } else if self.boardNode.board.win(.Good) { winner = self.goodPlayer } else { winner = nil } if winner != nil { println("game end: \(winner) won.") } else { println("draw.") } } else { self.selectOperation = NSBlockOperation { self.requestAction() } self.queue.addOperation(self.selectOperation) } } // 省略 }
ボードでアクションが終わったところで、ゲームが終了しているか判断している。
そして、ゲームが終了していたら、とりあえずどちらが勝ったかをログに出力して、それ以上アクションの選択がされないようにしている。
ゲームシーンの実装
さて、いままでビューコントローラでベタにやっていたシーンの構築を、ゲームシーンのイニシャライザへ移動する。
//============================== // YWF //------------------------------ // GameScene.swift //============================== import SpriteKit public class GameScene: SKScene { private var turnController: TurnController! public init(size: CGSize, userName: String, userStatus: PieceNode.Status, opponentName: String, opponentPlayer: Player) { self.turnController = nil super.init(size: size) self.scaleMode = .AspectFill let layoutManager = LayoutManager.getInstanceFor(size) let backgroundTexture = SKTexture(imageNamed: "Background") let background = SKSpriteNode(texture: backgroundTexture) background.position = layoutManager.getPosition(.Background, relativeTo: .Scene) self.addChild(background) let headerPosition = layoutManager.getPosition(.Header, relativeTo: .Background) if headerPosition != nil { let headerTexture = SKTexture(imageNamed: "Header") let header = SKSpriteNode(texture: headerTexture) header.position = headerPosition background.addChild(header) let logoTexture = SKTexture(imageNamed: "Logo") let logo = SKSpriteNode(texture: logoTexture) logo.position = layoutManager.getPosition(.Logo, relativeTo: .Header) header.addChild(logo) } var board = Board() let boardNode = BoardNode(board: board) boardNode.position = layoutManager.getPosition(.Board, relativeTo: .Background) background.addChild(boardNode) let undoButton = ButtonNode(type: .Undo) let passButton = ButtonNode(type: .Pass, enabled: false) let exitButton = ButtonNode(type: .Exit) undoButton.position = layoutManager.getPosition(.UndoButton, relativeTo: .Background) passButton.position = layoutManager.getPosition(.PassButton, relativeTo: .Background) exitButton.position = layoutManager.getPosition(.ExitButton, relativeTo: .Background) background.addChild(undoButton) background.addChild(passButton) background.addChild(exitButton) let userInfoSize = layoutManager.getSize(.UserInfo) let opponentInfoSize = layoutManager.getSize(.OpponentInfo) let opponentStatus: PieceNode.Status = (userStatus == .Bad) ? .Good: .Bad let userInfoNode = UserInfoNode(playerName: userName, status: userStatus, size: userInfoSize, boardNode: boardNode) let opponentInfoNode = UserInfoNode(playerName: opponentName, status: opponentStatus, size: opponentInfoSize, boardNode: boardNode) userInfoNode.position = layoutManager.getPosition(.UserInfo, relativeTo: .Background) opponentInfoNode.position = layoutManager.getPosition(.OpponentInfo, relativeTo: .Background) background.addChild(userInfoNode) background.addChild(opponentInfoNode) let user = Human(boardNode: boardNode, passButton: passButton) let badPlayer: Player let goodPlayer: Player if userStatus == .Bad { badPlayer = user goodPlayer = opponentPlayer } else { badPlayer = opponentPlayer goodPlayer = user } self.turnController = TurnController(boardNode: boardNode, undoButton: undoButton, badPlayer: badPlayer, goodPlayer: goodPlayer) } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override func didMoveToView(view: SKView) { self.turnController.start() } }
ただ、ちょっと融通が利かない実装というか、今のところは大丈夫だけど、あとから外部向けのインタフェースが必要になったときに、いろいろ苦しい感じがあるので、あとで修正は必要そう。
(例えば、イニシャライザでやるのは必要なUIの配置だけで、(ファサードクラスのように)外部からシーン内の各要素の設定が出来るようになっていた方が、融通が利く)
なお、Appleのサンプルコードではシーンのロードをバックグラウンドで行うようにしていたけれど( SpriteKitのサンプルコードを読んでみた。(その2) - いものやま。などを参照)、今まで実行していた感じだと、ロードに時間はかかっていなかったので、バックグラウンドで行うようにはしていない。
コントローラの修正
コードをゲームシーンへ移したので、それに合わせてコントローラも修正。
//============================== // YWF //------------------------------ // GameViewController.swift //============================== import UIKit import SpriteKit class GameViewController: UIViewController { @IBOutlet weak var skView: SKView! override func viewDidLoad() { BoardNode.loadAssets() PieceNode.loadAssetsAndCreateTemplates() UserInfoNode.loadAssets() ButtonNode.loadAssets() } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) var size = self.view.bounds.size if UIDevice.currentDevice().userInterfaceIdiom == .Phone { size.width *= 2.0 size.height *= 2.0 } let computer = AlphaBetaCom(status: .Good, depth: 3) let scene = GameScene(size: size, userName: "You", userStatus: .Bad, opponentName: "Computer", opponentPlayer: computer) self.skView.presentScene(scene) } // hide status bar. override func prefersStatusBarHidden() -> Bool { return true } }
これでUI作りも一段落。
今日はここまで!