goo blog サービス終了のお知らせ 

タブレット用プログラムの書き止め

android OS & iPadOS の記録。

【Swift P4.6.2】SpriteKit 3 (SwiftUI)

2025-05-23 17:57:41 | Swift iPadOS用

落ちものパズルっぽいゲームの基礎部分。
マス目、横10x縦15を想定してオブジェクトを一定時間で落としていく。
底に着くまで左右に動かせる。

マス目の10x15を二次元配列[10、15]に対応させる。
オブジェクトの種類を数値にして配列に積んでいく。
配列の積まれた状態をSpriteViewへ表示する。座標系が異なるので変換させる。
配列の並びを調べてパターンに合致したら消す。
上まで積み上がってしまったらゲームオーバー。

今回は落ちていくオブジェクトの左右移動と一定時間で下へマス目落下させる部分。

【ContentView.swift】

import SwiftUI
import SpriteKit

struct ContentView: View {
 
    var currentScene = MySKScene()
    init(){
        currentScene.scaleMode = .resizeFill
        currentScene.backgroundColor = .yellow
    }
    
    var body: some View {
        VStack {
            SpriteView(scene: currentScene)
                .frame(width: currentScene.sceneWidth(), height: currentScene.sceneHeight())
            HStack {
                Button("⬅️"){
                    currentScene.moveLeft()
                }
                Button("🔄"){
                    // 
                }
                Button("➡️"){
                    currentScene.moveRight()
                }
            }
        }
    }
}

【MySKScene.swift】

import SwiftUI
import SpriteKit

class MySKScene: SKScene {
    
    var image: SKSpriteNode!
    var imageGridPosition = (x:4,y:0) // 落下するオブジェクトのマス目位置
    var imageSize:CGFloat = 32.0
    // 10x15の2次元配列を0で初期化。グループNOを格納する2次元配列
    let gridMaxX = 10
    let gridMaxY = 15
    var grid = Array(repeating: Array(repeating: 0, count: 10), count: 15)
    
    var lastUpdateTime : TimeInterval = 0
    
    // シーンがViewに表示されたときに実行する処理をdidMoveメソッド内に書きます
    override func didMove(to view: SKView) {
        image = SKSpriteNode()
        image.size = CGSize(width: imageSize, height: imageSize)
        image.position = 
            getPosition(x: Double(imageGridPosition.x), y: Double(imageGridPosition.y))
        
        self.addChild(image)
        image.run(.repeatForever(
            .animate(with: MyTextures().imageTextures(), timePerFrame: 0.3)
        ))
    }
    
    //一定時間毎の処理
    override func update(_ currentTime: TimeInterval) {
        if (lastUpdateTime == 0) {
            lastUpdateTime = currentTime
        }
        if (lastUpdateTime + 1.0 <= currentTime) {
            downPosition()
            lastUpdateTime = currentTime
        }
    }
}

extension MySKScene {
    func sceneWidth()-> CGFloat {
        return imageSize * CGFloat(gridMaxX)
    }

    func sceneHeight()-> CGFloat {
        return imageSize * CGFloat(gridMaxY)
    }

    func moveLeft() { // 落下オブジェクトの左移動
        imageGridPosition.x -= 1
        if imageGridPosition.x < 0 {
            imageGridPosition.x = 0
        }

        image.position = getPosition(x: Double(imageGridPosition.x), y: Double(imageGridPosition.y))
    }

    func moveRight() { // 落下オブジェクトの右移動
        imageGridPosition.x += 1
        if imageGridPosition.x >= gridMaxX {
            imageGridPosition.x = gridMaxX - 1
        }

        image.position = getPosition(x: Double(imageGridPosition.x), y: Double(imageGridPosition.y))
    }

    func downPosition() { // 落下オブジェクトの下移動。色々省略中
        imageGridPosition.y += 1
        if imageGridPosition.y >= gridMaxY {
            imageGridPosition.y = 0 // 仮、上に戻している
            // 底に着いたor下に降ろせない時の処理。
        }

        image.position = getPosition(x: Double(imageGridPosition.x), y: Double(imageGridPosition.y))
    }

    func getPosition(x:Double, y:Double) -> CGPoint
    {
        // 2次元配列の位置(x,y)からSpriteViewの位置に変換する
        return CGPoint(x:32.0 * x + 16.0, y:480.0 - 32.0 * y - 16.0)
    }
}

【MyTextures.swift】

import SwiftUI
import SpriteKit

class MyTextures {
    public func imageTextures() -> [SKTexture] {
        return _imageTextures
    }
    private var _imageTextures:[SKTexture] = []

    init() {
        if let uii = UIImage(systemName: "arrowshape.up.circle" ) {
            _imageTextures.append(SKTexture(image: uii))
        }
        if let uii = UIImage(systemName: "arrowshape.forward.circle" ) {
            _imageTextures.append(SKTexture(image: uii))
        } 
        if let uii = UIImage(systemName: "arrowshape.down.circle" ) {
            _imageTextures.append(SKTexture(image: uii))
        } 
        if let uii = UIImage(systemName: "arrowshape.backward.circle" ) {
            _imageTextures.append(SKTexture(image: uii))
        }
    }
}