はじめに
前回の続きです。
今回はさみしかった画面に敵キャラを登場させます
素材準備
敵キャラはマヨネーズにしました(とくに意味はありません)。
m1 | m2 | m3 |
---|---|---|
実装
細かい当たり判定が難しいので今回は接触すればゲームオーバーになる撃破不可の敵にします。
とりあえず表示
位置とかは気にせずとりあえず表示します。
final class GameScene: SKScene {
override func didMove(to view: SKView) {
let enemy = makeEnemy()
enemy.position = .init(x: frame.midX + 30, y: frame.midY)
addChild(enemy)
enemy.run(makeEnemyAction())
}
private func makeEnemy() -> SKSpriteNode {
let enemy = SKSpriteNode(texture: .init(imageNamed: "m1"), size: .init(width: 32, height: 32))
enemy.physicsBody = .init(texture: enemy.texture!, size: enemy.size)
enemy.physicsBody?.allowsRotation = false
return enemy
}
private func makeEnemyAction() -> SKAction {
let textures: [SKTexture] = [
.init(imageNamed: "m2"),
.init(imageNamed: "m3"),
.init(imageNamed: "m1"),
]
return .repeatForever(
.sequence([
.group([
.animate(with: textures, timePerFrame: 0.2),
.sequence([
.wait(forDuration: 0.2),
.applyImpulse(.init(dx: -1, dy: 4), duration: 0.2)
])
]),
.wait(forDuration: 0.5)
])
)
}
}
こんな感じです。
衝突判定
衝突判定に使う categoryBitMask
などの詳細は下記をご参考ください。
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
:
:
// 床表示のtilePositions.forEachの処理に追加
node.physicsBody?.categoryBitMask = 0b0100
node.name = "floor"
// playerにbitMask設定
player.name = "player"
player.physicsBody?.contactTestBitMask = 0b0011
player.physicsBody?.categoryBitMask = 0b0011
// enemyにbitMask設定
enemy.name = "enemy"
enemy.physicsBody?.categoryBitMask = 0b0011
}
下記のように衝突判定のデリゲート設定。これで player
と enemy
が接触するとコンソールに「Hit!!!!!!!!!」と表示されます。
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node,
let nodeB = contact.bodyB.node else {
return
}
if nodeA.name == "enemy" || nodeB.name == "enemy" {
print("Hit!!!!!!!!!")
}
}
}
ゲームオーバー処理
まずはゲームオーバーの画面を作成します。
final class GameOverScene: SKScene {
override func didMove(to view: SKView) {
backgroundColor = .black
let label = SKLabelNode(text: "Game Over")
label.fontName = "PixelMplus10-Bold"
label.fontColor = .systemRed
label.position = .init(x: frame.midX, y: frame.midY)
addChild(label)
let button = SKLabelNode(text: "もう一回やる")
button.name = "continue"
button.fontName = "PixelMplus10-Regular"
button.fontColor = .white
button.position = .init(x: frame.midX, y: frame.midY - 100)
addChild(button)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
if atPoint(touch.location(in: self)).name == "continue" {
view?.presentScene(GameScene(size: size), transition: .doorway(withDuration: 2.0))
}
}
}
こんな感じです。
カスタムフォントには下記を使用しました。
カスタムフォントの導入方法は下記の記事を参考にしました。
【Swift】UIKitとSwiftUIでカスタムフォントを使用する
あとは衝突判定で print("Hit!!!!!!!!!")
と書いていたところに下記の遷移処理を追加すれば完成です!
view?.presentScene(GameOverScene(size: size), transition: .fade(withDuration: 2.0))
おわりに
前回のと合わせるとこんな感じになります。
次回はゴール判定を実装して完成です
SpriteKit あまりさわったことないのでもっといい方法あればぜひ教えて下さい