4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SpriteKitで2D横スクロールゲームをつくろう(その4)

Last updated at Posted at 2022-12-07

Xcode-14.1 iOS-16.0

はじめに

前回の続きです。

今回はさみしかった画面に敵キャラを登場させます:smiling_imp:

素材準備

敵キャラはマヨネーズにしました(とくに意味はありません)。

m1 m2 m3
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)
            ])
        )
    }
}

こんな感じです。

enemy

衝突判定

衝突判定に使う categoryBitMask などの詳細は下記をご参考ください。

SpriteKitで衝突判定(Swift)

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        
}

下記のように衝突判定のデリゲート設定。これで playerenemy が接触するとコンソールに「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))
        }
    }
}

こんな感じです。

game_over

カスタムフォントには下記を使用しました。

PixelMplus

カスタムフォントの導入方法は下記の記事を参考にしました。

【Swift】UIKitとSwiftUIでカスタムフォントを使用する

あとは衝突判定で print("Hit!!!!!!!!!") と書いていたところに下記の遷移処理を追加すれば完成です!

view?.presentScene(GameOverScene(size: size), transition: .fade(withDuration: 2.0))

おわりに

前回のと合わせるとこんな感じになります。

game

次回はゴール判定を実装して完成です:tada:

SpriteKit あまりさわったことないのでもっといい方法あればぜひ教えて下さい:bow:

まとめ

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?