Swiftで遊ぼう! - 888 - やっとTower(turret)をグリッドに並べるよ
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
次は、やぐら(turret)を画面上に並べていくところです。
コーディングの舞台は、「GameScene.swift」です。ゲームはこの上で展開されます。画面上のタップされた場所にやぐらを出現させるためにイメージを用意します。私は次のイメージを作りました。勝手にコピーして使って構いませんよ。
ファイル形式は当然、PNGで、名前を「turrt.png」にして、プロジェクト・ナビゲータにある「Assets.xcassets」にドラッグ&ドロップします。
GameSceneクラス、そのスーパークラスにあたるUIViewクラスが持っている「touchesBegan()」メソッドをオーバライドして実装します。
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let touch = touches.first! let location = touch.location(in: self) let coordinate = coordinateFor(point: location) // この時点でエラーです createTower(atCoordinate: coordinate) // この時点でエラーです }
まず最初の2行で、タッチした位置をCGPoint型の「location」として取り出します。そして次にGameplayKitの座標システム「int2」型に変換するメソッドを用意します。このコードを入力したところで、赤いエラーマークが出ています。
update()メソッドの下に次のヘルパーメソッドを作ります。
// MARK: Unit Changing func coordinateFor(point: CGPoint) -> int2 { return int2(Int32((point.x - gridStart.x) / boxSize), Int32((point.y - gridStart.y) / boxSize)) }
この説明はいらないですね。これでどのグリッドが選択されたのか分かります。この情報を使って、createTower()メソッドを発動して、やぐらオブジェクト(Entity)を作って、VisualComponentも使用して画面に表示させるんです。まだ赤いエラーコードが表示されているんで、「// MARK: Unit Changing」のcoordinatFor()メソッドの下に次のコードを加えます。
// MARK: Tower func createTower(atCoordinate: int2) { if let node = graph.node(atGridPosition: atCoordinate) { let tower = GKEntity() let towerSprite = SKSpriteNode(imageNamed: "turret") towerSprite.position = pointFor(coordinate: atCoordinate) // この時点でエラーです towerSprite.size = CGSize(width: boxSize * 0.9, height: boxSize * 0.9) let visualComponent = VisualComponent(scene: self, sprite: towerSprite, coordinate: atCoordinate) tower.addComponent(visualComponent) addChild(towerSprite) graph.remove([node]) // updateコードが加わります } }
まず、タップされたgraph領域の座標の位置にnodeがあれば、それを返して、nodeを作ります。SpriteNodeクラスのtowerSpriteをAssets.xcassetsから作って、int2座標システムからCGPoint画面座標システムに変換するpointFor()メソッド(今はエラーになっています)を使って、グリッドの真ん中の情報を持たせて、イメージのサイズも90%にします。VisualComponentクラスのvisualComponentインスタンスを作って、sceneとtowerSpriteと位置情報を結びつけます。これをGKEntityクラスのtowerに組み込んで準備完了です。
しかし、微妙に疑問が残ります。実は、VisualComponentクラスをEntityクラスに持たせても、実際の画面に表示はされません。SpriteKitが絡むと、少し話が複雑になるのかもしれません。結局描画するためにtowerSpriteをSceneに加える作業の「addChild(towerSprite)」が必要になるんです。
2つの座標システムを交互に扱わせているこのチュートリアルはコーディングが悪いのだろうか?私が最初に考えたイメージは、VisualComponentクラスをEntityクラスに組み込んだところで画面表示がされると思いました。プログラマーの皆さん、意見をお願いします。
取りあえず、int2型座標システムからCGPoint型座標システムに変換するメソッドを「// MARK: Unit Changing」に加えます。
func pointFor(coordinate: int2) -> CGPoint { return CGPoint(x: CGFloat(coordinate.x) * boxSize + gridStart.x + boxSize / 2, y: CGFloat(coordinate.y) * boxSize + gridStart.y + boxSize / 2) }
曲がりなりにもこれでタップしたところに「やぐら」が現れます。
今日はここまで。