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

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

android OS & iPadOS の記録。

【Swift P4.6.2】SKTexture 2 (SwiftUI)

2025-05-09 01:37:36 | Swift iPadOS用

SpriteViewの中にスプライト画像を表示し、それをドラッグで移動させる。
テクスチャーの初期化部分をMyTextureクラスに分離しました。

 

【ContentView.swift】

import SwiftUI
import SpriteKit

struct ContentView: View {
    
    var currentScene: SKScene {
        let scene = MySKScene()
        scene.scaleMode = .resizeFill
        scene.backgroundColor = .yellow
        return scene
    }
    var body: some View {
        ZStack {
            SpriteView(scene: self.currentScene)
                .frame(width: 300, height: 250)
        }
    }
}

class MySKScene: SKScene {
    var image: SKSpriteNode!
    var beforeDragPosition: CGPoint?

    // シーンがViewに表示されたときに実行する処理をdidMoveメソッド内に書きます
    override func didMove(to view: SKView) {
        
        image = SKSpriteNode()
        image.size = CGSize(width: 32, height: 32)
        image.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
        self.addChild(image)
        
        let action = SKAction.animate(with: MyTextures().imageTextures(), timePerFrame: 0.3)
        image.run(.repeatForever(action))
    }
    
    // ドラッグした際に呼ばれる
    override func touchesMoved(_ touches: Set, with event: UIEvent?) {
        for t in touches {
            self.touchMoved(toPoint: t.location(in: self))
        }
    }
    
    //ドラッグが終了したとき(画面から指が離れたとき)に呼ばれる
    override func touchesEnded(_ touches: Set, with event: UIEvent?) {
        for t in touches { self.touchUp(atPoint: t.location(in: self)) }
    }
    
    // 指が画面から離れた際に呼ばれる
    func touchUp(atPoint pos : CGPoint){
        self.beforeDragPosition = nil
    }
    
     // 画像の位置を更新
     func touchMoved(toPoint pos : CGPoint) {
    
         if let p1 = self.beforeDragPosition {
             self.image.position.x += pos.x - p1.x
             self.image.position.y += pos.y - p1.y
             // SpriteView の左右に飛び出ないようにする
             let imagePosXMin = self.image.size.width/2
             let imagePosXMax = self.size.width - imagePosXMin
             if ( self.image.position.x < imagePosXMin ) {
                 self.image.position.x = imagePosXMin
             }
             else if ( self.image.position.x > imagePosXMax ) {
                 self.image.position.x = imagePosXMax
             }
             // SpriteView の上下に飛び出ないようにする
             let imagePosYMin = self.image.size.height/2
             let imagePosYMax = self.size.height - imagePosYMin
             if ( self.image.position.y < imagePosYMin ) {
                 self.image.position.y = imagePosYMin
             }
             else if ( self.image.position.y > imagePosYMax ) {
                 self.image.position.y = imagePosYMax
             }
         }
         self.beforeDragPosition = pos
     }
}

 

テクスチャーの初期化。
【MyTextures.swift】

import SwiftUI
import SpriteKit

public 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))
        }
    }
}

init() {} 内のコードを書き換えました。
UIImageが使えないと思い込み CGImage で設定していました。

 

参考にしたサイトのURLを見失ってしまいました。
見つけ次第掲載します。


【Swift P4.6.2】SKTexture (SwiftUI)

2025-05-07 20:05:24 | Swift iPadOS用

2Dキャラをアニメーションさせる為に画像(png 透明有)を複数用意してアセットフォルダに保存する。

Playgroundアプリ画面の左上の

サイドバー アイコン>追加ファイル アイコン>写真

でアセットフォルダにコピーする画像を選ぶ。
コピー後にファイル名を分かりやすい名前に変更しておく。
透明部分有りのPNGファイルはパソコンで作った方が簡単かな?

動作テストなら写真フォルダ内の適当な画像を設定する。かなり縮小されますが(笑)

【ContentView.swift】

import SwiftUI
import SpriteKit

struct ContentView: View {
    
    var currentScene: SKScene {
        let scene = MySKScene()
        scene.scaleMode = .resizeFill
        return scene
    }
    
    var body: some View {
        ZStack {
            SpriteView(scene: self.currentScene)
                .frame(width: 300, height: 250)
        }
    }
}

class MySKScene: SKScene {
    
    // シーンがViewに表示されたときに実行する処理をdidMoveメソッド内に書きます
    override func didMove(to view: SKView) {
    
        let node = SKSpriteNode()
        node.size = CGSize(width: 50, height: 50)
        node.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
        self.addChild(node)

        //  複数の画像を用意して順次0.3秒で切り替えてアニメーション表示させる
        let textures: [SKTexture] = [
            .init(imageNamed: "Test-a"), // アセット内のファイル名を指定する
            .init(imageNamed: "Test-b"),
            .init(imageNamed: "Test-c")
        ]
        let action = SKAction.animate(with: textures, timePerFrame: 0.3)
        node.run(.repeatForever(action))
    }
}

 

【追記】

システムのアイコンを画像変換して利用をし、アニメーションの確認をするコード。


import SwiftUI
import SpriteKit

struct ContentView: View {
    
    var currentScene: SKScene {
        let scene = MySKScene()
        scene.scaleMode = .resizeFill
        scene.backgroundColor = .yellow // 追加
        return scene
    }
    var body: some View {
        ZStack {
            SpriteView(scene: self.currentScene)
                .frame(width: 300, height: 250)
        }
    }
    
}
class MySKScene: SKScene {
    
    // シーンがViewに表示されたときに実行する処理をdidMoveメソッド内に書きます
    override func didMove(to view: SKView) {

        let node = SKSpriteNode()
        node.size = CGSize(width: 50, height: 50)
        node.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
        self.addChild(node)

        let dummy = SKTexture(imageNamed: "dummy") // cgiが失敗した時の画像。アセットに用意しておく
        var texture1 = dummy
        if let cgi1 = UIImage(systemName: "arrowshape.up.circle" )?.cgImage { // システムのアイコンを利用する
            texture1 = SKTexture(cgImage: cgi1)
        }
        
        var texture2 = dummy
        if let cgi2 = UIImage(systemName: "arrowshape.forward.circle" )?.cgImage {
            texture2 = SKTexture(cgImage: cgi2)
        } 
        
        var texture3 = dummy
        if let cgi3 = UIImage(systemName: "arrowshape.down.circle" )?.cgImage {
            texture3 = SKTexture(cgImage: cgi3)
        } 
        
        var texture4 = dummy
        if let cgi4 = UIImage(systemName: "arrowshape.backward.circle" )?.cgImage {
            texture4 = SKTexture(cgImage: cgi4)
        } 

         let textures: [SKTexture] = [
            texture1,
            texture2,
            texture3,
            texture4
         ]
         let action = SKAction.animate(with: textures, timePerFrame: 0.3)
         node.run(.repeatForever(action))
    }
}

 


【Swift P4.6.2】SpriteKit (SwiftUIで利用)

2025-05-05 00:53:04 | Swift iPadOS用

画像ビュアーを作るにはファイルを開くのにやや面倒だったし、じゃぁ画像編集と思ったけど、PCの方が都合良さそうなのでSwift playground は休止でした。

Playground はゲームも簡単に出来るらしいと言うのでチュートリアルの「ブロック崩し」を見ました。

MyApp.swift が無い。
Main(bookアイコン)から始まってそうだけど、チュートリアル用の型式みたい。
新規アプリ作成でゲームコード選択は無し。
ゲーム作れないジャン。

ブロック崩しのコード仕様は、iPad Swift Playground の書式とは相違があり、新規アプリのファイルにコピペで新規swiftファイルを作るとエラー乱立。
 “Cannot find 〜”
Class 、struct の名前が違うか内容の構成が違うのかスペシャルコード仕様なのか(笑)
iPad Swift Playground ではゼロからブロック崩しのようなゲームアプリを作る手立てが無いのは分かった。

ブロック崩しチュートリアルの意味ないジャン。

仕方ないのでWeb検索しました。
情報少な!(検索ワード設定がムズイ)

少ない情報からSpriteKit クラスを使って、 
ContentView.swift に SwiftUI 上でゲーム用のSpriteViewが作れるのが分かりました。
ゲーム作りは参考書を買って勉強しないと素人はダメのようです。


2Dゲーム用のSpriteViewをSwiftUIに設置する最小コードです。
テキスト表示&回転のみ。

【ContentView.swift 】

import SwiftUI
import SpriteKit

struct ContentView: View {
    
    var currentScene: SKScene {
        let scene = MySKScene()
        scene.scaleMode = .resizeFill
        return scene
    }
    
    var body: some View {
        ZStack {
            SpriteView(scene: self.currentScene)
                .frame(width: 300, height: 250)
        }
    }
}

class MySKScene: SKScene {
    
    // シーンがViewに表示されたときに実行する処理をdidMoveメソッド内に書きます
    override func didMove(to view: SKView) {
        
        let myLabel = SKLabelNode(fontNamed:"Chalkduster")
        myLabel.text = "Hello, World!";
        myLabel.fontSize = 20;
        myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
        myLabel.fontColor = .red
        self.addChild(myLabel)
        
        // 回転アクションを生成(360度を3秒かけて回転)。それを連続する
        let rotation = SKAction.repeatForever(
            SKAction.rotate(byAngle: .pi*2, duration: 3)
        )
        // アクションをNodeに適用
        myLabel.run(rotation)
    }
}


箸休め的なBDレコーダーの話

2025-03-11 01:59:10 | 気まぐれ言の葉

TVがアナログからデジタルに移行する時期のこと。

アナログ放送の録画やVHSテープをDVD–R(VR形式)にダビングしました。
DVD–video形式よりDVD–VR形式の方が解像度がちょっと良かったから。

時代はBDレコーダーに移り、DVD–Rをそのまま見ていました。
ある日、DVDディスクを取り替えるのが面倒くさくない?

BDレコーダーのHDDにダビングできれば取り替えいらなくない?
DVD–VR形式はダビングしても表示できないはず...。

※アナログ放送、VHSのダビングは、DVD-RからBDレコーダーのHDDへダビングしても映像表示はできました。内蔵HDDから外付けUSBHDDへの移動はできません。USBHDDに纏めるには別の方法が必要です。私のBDレコーダーの場合です。DVD-R録画は昔のVHS付DVDレコーダーで作成したもの。
(情報修正)

 

VR形式はプロテクトがかかってしまう。内蔵HDDから外付けHDDへの移動ができない。
なので調査をしました。

DVDから動画を抽出するソフトがあるらしい。
ただ、地デジ録画についてはプロテクトを外す事が違法になったみたい。市販DVDもかな。

VHSダビングやアナログ放送録画のDVDは、まぁ大丈夫か…?
個人責任で実行するのには変わりない。言い訳は考えておく。

 

※著作権がある作品は著作権保有者に許可を得ていなければ、無料有料に関わらず個人間譲渡、配布、配信は違法となり罰則を受けます。また個人で楽しむ場合にも制限はあるので十分に注意が必要です。

 

流れは、
1、ダビングしても良いDVDの映像から動画ファイルを取り出す。
2、取り出した動画を都合の良い形式に変換する。
3、BD–R、BD–REに書き込む。
4、BDレコーダーのHDDにダビングし、外付けUSBHDDへ移動する。

調査の途中にBlu-rayディスクにBDMVとBDAV形式があると分かった。
市販タイトルBDは、BDMV形式で、BDレコーダーでダビングするのがBDAV形式。
なので、BDAV形式で書き込めるソフトでないとBlu-ray DiscからBDレコーダーにダビングできない。やばかった散財するところだった。

1、の動画取り出しソフトは気を付ける部分が多い。まず体験版がある物で試してみて決める。有料版は払ったあとにコンタクトが取りづらく返金とかできると書いてあっても難しい事があるらしい。
私の場合は、見つけた全体の半分くらいに体験版があった。速度や取り出し形態などで残ったのは一つだけでした。

2、の変換については、最終的に720x480の解像度でBDレコーダーにダビング出来る事が分かったので圧縮形式だけ調整すればOKでした。
720x480と、1920x1080変換の動画を作って試したら私のレコーダーではどちらもディスクからHDDにダビングできました。

3、のBlu-ray Discの書き込み。BDAV形式の書き込みができる事が重要です。

BDAV規格に必要な動画形式は、

映像ストリーム形式は、MPEG-2ビデオ、H.264/AVC。
解像度が、NTSCの720x480、1280x720、1440x1080、1920x1080。一部分抜粋。
フレームレートは、NTSCの29.97fps。通常。
ビットレートは、MAXで15Mbps。通常。

入力ファイルが合致しないとBDAV規格のオーサリング(書き込み)ができないみたい。

4、Blu-ray Disc(使用中)にBDAV規格で追加書き込みできれば、ディスクからBDレコーダーのHDDにダビング、そしてUSBHDDへの移動ができます。タイトル設定がまだ分からず動画のタイトルが無タイトル状態でダビング、BDレコーダーのタイトル編集で名前を書き込んでいます。
解像度はDVD-VRの720x480のままでも問題ないので時短の意味でそのままにする。BDレコーダーHDDでの動画表示はDVD画質のままで高画質化はしていない。AI編集ソフトで高画質化はできるらしいけど、どの程度か分からないし予算が無いので保留にしている。

内蔵HDDから外付けのUSBHDDにダビングできるのでDVD–Rからのダビング専用HDDを1つ作ろう(^∇^)


ビジネスモデルの安いノートPCは向いていません。
GPU付きかGPU機能の高いAPUを使ったPCを使う必要があります。
長時間待てる人は左にあらず。ですが。

メーカーがDVD-VRの読み込みダビングを実現してくれたら買い替えるんだけど、無いものは仕方ないので方法を見つけてしまいました。お金かかった。でも昔のビデオを24時間ノンストップで観られるわ~。

 

 


【Swift P4.6.2】ボタンタップアクション

2025-02-18 19:20:23 | Swift iPadOS用

Button()はタップすると明暗変化?している。
ボタン画像をタップした時に拡大縮小してアピールを大きくしたい。
新しい iOS に制限されるけど、androidOSより簡単にアニメーションです。

【MyApp.swift】
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}


【ContentView.swift】
struct ContentView: View {
    var body: some View {
        ButtonView()
    }
}


・ボタンパーツ
 ボタンに使う画像をPNGファイルで用意して背景を透明設定しておくと良い。

【ButtonView.swift】
struct ButtonView: View {
    @State var scale: CGFloat = 2.0 // 大きさ調整
    var body: some View {
        Image(systemName:"arrowshape.forward.circle.fill")
            .gesture(
                TapGesture()
                    .onEnded{_ in
                        ZoomAnimation()
                        /* 処理本体を書く */
                    }
            )
            .scaleEffect(scale)
    }
    
    func ZoomAnimation() { // ボタン代わりの画像を拡大縮小させる
        withAnimation(Animation.linear(duration: 0.1)){ // 変化する時間も設定
            scale = 3.0
        } completion: { // ios17以降?
            withAnimation(Animation.linear(duration: 0.1)){ 
                scale = 2.0
            }
        }
    }
}