0
1

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.

Swiftでゲームを作る Spritekit

Last updated at Posted at 2023-07-28

Swiftでゲームを作る
Swiftでゲーム作る場合、2Dゲームであれば、
Spritekitを使うのが一般的だと思います。
プロジェクト作成から作っていきます。
Xcode Version 14.3
スクリーンショット 2023-07-28 9.51.41.png
上のメニューバーからFile→New→Projectを選び
スクリーンショット 2023-07-28 9.55.01.png
iosタブのAppを選択しNextボタンを押す。
スクリーンショット 2023-07-28 9.59.36.png
Project Nameでプロジェクト名を入力し(今回はblock breakerと入力しました。)
Nextボタンを押して保存先を決めます。

下準備、
いらない物を消す。
左のファイル一覧にある
SceneDelegate.swift
を削除。
右クリック→delete→Move To trash(ゴミ箱に移動)
同じファイル一覧にある
info(Info.plist)
Application Scene Manifest
を選択しバックスペースで削除。

ファイルを編集していきます。
ViewController.swiftのファイル名をGameViewController.swiftに変更します。

GameViewController.swift
import UIKit
import SpriteKit

class GameViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let scene = GameScene(size: view.bounds.size)
        let skView = view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true
        skView.showsPhysics = true
        skView.ignoresSiblingOrder = true
        scene.scaleMode = .resizeFill
        skView.presentScene(scene)
    }
 
}

AppDelegate.swift
AppDelegateも編集します。

AppDelegate.swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window:UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
           self.window = UIWindow(frame: UIScreen.main.bounds)
           window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
           window?.makeKeyAndVisible()
           return true
       }
}

ストーリーボードの編集
左のファイル一覧にあるMain(Main.storyboard)を選択し
スクリーンショット 2023-07-28 10.39.25.png
画像で丸した所をクリックしてclass欄のViewControllerからGameViewControllerへ変更する。

続いてViewの所画像の順番にクリックしSKViewに変更する。
スクリーンショット 2023-07-28 10.44.47.png

ここまで下準備。
ゲームシーンを作成。
わかりやすくするためにシーンファイルを置くフォルダを作る。
スクリーンショット 2023-07-28 10.55.02.png
半角でgameと入力し右クリックしてNew Fileを選択
スクリーンショット 2023-07-28 11.00.50.png
Swift Fileを選択しNext
Save As:にGameScene.swiftと入力しCreateボタンを押す。

動作テストしてみる。ブロック崩しサンプル

GameScene.swift
import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {
    
    private var ball: SKShapeNode!
    private var paddle: SKSpriteNode!
    private var blocks = [SKSpriteNode]()
    
    private let ballCategory: UInt32 = 0x1 << 0
    private let paddleCategory: UInt32 = 0x1 << 1
    private let blockCategory: UInt32 = 0x1 << 2
    private let edgeCategory: UInt32 = 0x1 << 3
    
    override func didMove(to view: SKView) {
        physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        physicsWorld.contactDelegate = self
        createBall()
        createPaddle()
        createBlocks()
        createPhysicsBoundaries()
        // ボールに初速を与える
    let dx: CGFloat = 200.0 // x方向の初速度
    let dy: CGFloat = 400.0 // y方向の初速度
        ball.physicsBody?.velocity = CGVector(dx: dx, dy: dy)
    }
    
    func createBall() {
        ball = SKShapeNode(circleOfRadius: 10)
        ball.fillColor = UIColor.red
        ball.position = CGPoint(x: frame.midX, y: frame.midY)
        ball.physicsBody = SKPhysicsBody(circleOfRadius: 10)
        ball.physicsBody?.categoryBitMask = ballCategory
        ball.physicsBody?.contactTestBitMask = blockCategory
        ball.physicsBody?.collisionBitMask = blockCategory | paddleCategory | edgeCategory
        ball.physicsBody?.isDynamic = true
        addChild(ball)
    }
    
    func createPaddle() {
        paddle = SKSpriteNode(color: UIColor.blue, size: CGSize(width: 100, height: 20))
        paddle.position = CGPoint(x: frame.midX, y: frame.minY + 100)
        paddle.physicsBody = SKPhysicsBody(rectangleOf: paddle.size)
        paddle.physicsBody?.categoryBitMask = paddleCategory
        paddle.physicsBody?.restitution = 1.0
        paddle.physicsBody?.collisionBitMask = ballCategory
        paddle.physicsBody?.isDynamic = false
        addChild(paddle)
    }
    
    func createBlocks() {
        let numRows = 3
        let numCols = 5
        let blockWidth = frame.width / CGFloat(numCols)
        let blockHeight: CGFloat = 20
        
        for row in 0..<numRows {
            for col in 0..<numCols {
            let block = SKSpriteNode(color: UIColor.green, size: CGSize(width: blockWidth, height: blockHeight))
                block.position = CGPoint(x: blockWidth * CGFloat(col) + blockWidth / 2, y: frame.height - CGFloat(row) * blockHeight - blockHeight / 2)
                block.physicsBody = SKPhysicsBody(rectangleOf: block.size)
                block.physicsBody?.categoryBitMask = blockCategory
                block.physicsBody?.collisionBitMask = ballCategory
                block.physicsBody?.isDynamic = false
                blocks.append(block)
                addChild(block)
            }
        }
    }
    
   override func update(_ currentTime: TimeInterval) {
           // ボールの速度を一定に保つことで停止させない
           let minSpeed: CGFloat = 300.0
           let speed = sqrt(ball.physicsBody!.velocity.dx * ball.physicsBody!.velocity.dx + ball.physicsBody!.velocity.dy * ball.physicsBody!.velocity.dy)
           if speed < minSpeed {
               let scale = minSpeed / speed
               ball.physicsBody?.velocity.dx *= scale
               ball.physicsBody?.velocity.dy *= scale
           }
       }
   
   func createPhysicsBoundaries() {
    let edge = SKNode()
        edge.physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
        edge.physicsBody?.friction = 0.0
        edge.physicsBody?.restitution = 1.0
        edge.physicsBody?.categoryBitMask = edgeCategory
        addChild(edge)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)
            paddle.position.x = location.x
        }
    }
    
    func didBegin(_ contact: SKPhysicsContact) {
        if contact.bodyA.categoryBitMask == blockCategory || contact.bodyB.categoryBitMask == blockCategory {
            let blockNode = contact.bodyA.categoryBitMask == blockCategory ? contact.bodyA.node : contact.bodyB.node
            blockNode?.removeFromParent()
            if let index = blocks.firstIndex(of: blockNode as! SKSpriteNode) {
                blocks.remove(at: index)
            }
        }
    }
}
0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?