質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

249閲覧

チェスのようなボードゲームで(プレイヤーが打った手をちゃんと描画した後に)CPが打つまでに待機時間をつくりたい,iOS

mashiroyuya

総合スコア24

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/08/15 10:08

Swift で iOS向けの チェスのようなゲームを作っているなかでできないことがあったので質問させてください。
プレイヤーとCP(コンピュータ)の間の対戦に関しての質問です。

  1. プレイヤーが画面をタップしてコマを動かして、コマを動かした後を描画。
  2. そのあとにCPが次に打つところを決めてそれを描画。

という実装をしているのですが、プレイヤーが打った後にCPが打つまでの待ち時間がないのでプレイヤーが打った瞬間にCPが打ち返してきます。そこをなんとかしてプレイヤーとCPの打つときに間が欲しいです(CPが考えているように見せたい)。

つまり上記の1.と2.の間に待ち時間が欲しいです。

単純にsleep関数などで処理を止めるとプレイヤーの動かしたコマの描画が行われず、プレイヤーが動かしてCPが動かした後が描画されます。

現状は

  1. プレイヤーが駒を動かす
  2. すかさずCPが駒を動かす
  3. プレイヤーとCPの両方が打ち終わった盤面を描画

理想は

  1. プレイヤーがコマを動かす
  2. プレイヤーが打った盤面を描画
  3. CPのターンになるが2秒ほど待つ
  4. CPがコマを動かす
  5. CPが打った盤面を描画
  6. プレイヤーのターン

という流れです。

現在
盤面を描画するクラス(盤面に基づいた描画) StoneView(UIView)

view と GameStatusの間に入るクラス (タップされた位置の受け渡しなど) ViewController

ゲームを管理するクラス(ゲームのターン,盤面の変化,勝敗など) GameStatus
があります。

下のstoneTouchedはViewControllerに記述されているメソッドで、
stoneviewクラスで駒にタップされるとdelegateでViewControllerに実装されているstoneTouchedが呼ばれます。

引数のstoneは盤面のどの位置がタップされたかという座標(座標ですが1次元)です。

Swift

1//盤面がタップされたら呼ばれる 2func stoneTouched(stone: Int) { 3 // self.gameStatus : ViewControllerのインスタンス変数(GameStatusクラス) 4 // self.stoneView : ViewControllerのインスタンス変数(StoneViewクラス) 5 6 //gameStatusのchangestatesは どこがタップされた位置を引数に 7 //タップされたことによる(変化した盤面,ターンが変わったか?)をタプルで返します。 8 let states_turn = self.gameStatus.changestates(pos: stone) 9 10 //stoneViewの盤面に変更された盤面を代入します 11 self.stoneView.stonestates = states_turn.0 12 13 //タップによりターンが変わっていれば(states_turn.1 == true)CPのターンを始めます 14 if states_turn.1{ 15 //cpmoveにはcpが(動かす駒,どこに動かすか)がタプルで入っています. 16 let cpmove = self.gameStatus.cpnext() 17 //動かす駒をタップした時と同様の動作をさせる 18 var cp = self.gameStatus.changestates(stone: cpmove.0) 19 //次に動かす場所をタップしたときと同様の動作をさせる 20 cp = self.gameStatus.changestates(stone: cpmove.1) 21 22 //stoneViewの盤面にcpにより変更された盤面を代入します 23 self.stoneView.stonestates = cp.0 24 } 25 self.stoneView.setNeedsDisplay() 26 27 }

setNeedsDisplayをプレイヤーが打ったあとに挟んでもあくまでこのメソッドは再描画するフラグを立てるだけで、再描画はしてくれません。
現状を理想の流れにするにはどうしたらよいでしょうか。
そもそもゲームを進めるロジックの組み方に問題があるのでしょうか。

説明不足があるところもあるかとは思いますがご教授お願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

StoneViewの方に盤面の再描画のためのメソッドを作ってやれば良いかと思います。
盤面のビューの方のコードが分からないのでなんとも言えませんが、単に現状の石の描画をクリアして現在のGameStatusで再描画すれば良いのではないでしょうか。

間を作る方法は、Timerを使えば十分かと思います。

まとめるとこんな感じでしょうか。

func stoneTouched(stone: Int) { let states_turn = self.gameStatus.changestates(pos: stone) self.stoneView.stonestates = states_turn.0 if states_turn.1{ // タイマーで遅延 Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in let cpmove = self.gameStatus.cpnext() var cp = self.gameStatus.changestates(stone: cpmove.0) cp = self.gameStatus.changestates(stone: cpmove.1) self.stoneView.stonestates = cp.0 self.stoneView.refreshStonePosition(self.gameStatus) //新規作成した再描画メソッド } } }

現在の実装にもよりますが、タイマーでユーザを待たせている間にstoneViewを操作できなくする処理も必要かもしれませんね。

投稿2017/08/17 10:37

YokemuraTakeshi

総合スコア297

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

NSObjectperform(_:with:afterDelay:)によるメソッドの遅延呼び出しを利用してください。
これで、RunLoopにタイマーイベントがスケジュールされます。

投稿2017/08/16 14:37

編集2017/08/16 14:37
Stripe

総合スコア2183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問