Swift5.1.3 Xcode11.3.1 SwiftUI
- サイコロアプリの基本的な作り方
- アプリを改造して手品用のイカサマのダイスを作る
- GameplayKitをimportしてif文でサイコロの確率を調整します
「以下は動画のハイライトです。」
少しオジさん年齢がバレてしまいそうですが、あのゲームの最強武器「イカサマのダイス」をiOSアプリで作ってみたいと思います。
まずその手品用のサイコロを作る前に普通のサイコロアプリの作り方をお伝えします。
サイコロのそれぞれの出目を写した適当な写真を6つ用意してくださいね。
その写真をそれぞれ以下のように画像ファイルとして扱います。
1.png
2.png
3.png
4.png
5.png
6.png
これを第24回で学習しましたパラパラ漫画作成の技術を使ってサイコロが転がっているようなアニメーションを作ります。
6枚の画像をAssets.xcassetsに入れましたら以下のstructを作成します。
var images : [UIImage]! = [UIImage(named: "1")!, UIImage(named:
"4")!, UIImage(named: "2")!, UIImage(named: "3")!,
UIImage(named: "5")!, UIImage(named: "6")!]
let animationImage = UIImage.animatedImage(with: images, duration: 2.0)
struct startAnimation: UIViewRepresentable {
func makeUIView(context: Self.Context) -> UIView {
let myView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
let myImage = UIImageView(frame: CGRect(x: 30, y: 200, width: 360, height:
300))
myImage.contentMode = UIView.ContentMode.scaleAspectFill
myImage.image = animationImage
myView.addSubview(myImage)
return myView
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<startAnimation>)
{
print("updated!")
}
}
この画像が動く仕組みの細かいところは第24回をご査収ください。ここでポイントは以下の画像指定のところです。
var images : [UIImage]! = [UIImage(named: "1")!, UIImage(named:
"4")!, UIImage(named: "2")!, UIImage(named: "3")!,
UIImage(named: "5")!, UIImage(named: "6")!]
画像を格納するArrayの中身はこんな感じにデタラメに数字を並べた方がよりサイコロが転がっている感じになります。各画像も微妙に写真のサイコロの位置をずらした方が全て中心にピタッとあるサイコロの写真より動いている感が表現でると思います。
これをContentView内でstartAnimation()を配置してサイコロの動きを確認しましょう。
アニメーションが出来上がったところでサイコロをプログラミングします。
実はSwiftUIでは便利なゲーム機能があり、以下のライブラリをimportします。
import GameplayKit
let d6 = GKRandomDistribution.d6()
var dicedInt = d6.nextInt()
このライブラリの使用方法は簡単です。上記の二行でdicedIntとある変数に最終的にIntの値で数字の1~6がランダムに格納されます。
サイコロの出目となるdicedIntを変数dicedを新たに作ってString値に変換します。
self.diced = "\(dicedInt)"
これをButton動作と連動させてif文でアニメーションと静止画に切り替える論理式を組みます。
@State var dicing = false
@State var diced = "1"
if self.dicing == true {
startAnimation()
} else {
Image(self.diced)
.resizable()
.aspectRatio(contentMode: .fit)
}
と、ここまでがイカサマでない正常なサイコロの作り方です。
@State var dicing = false
@State var diced = "1"
@State var btnName = "Roll it"
var body: some View {
VStack(spacing: 50) {
Button(action: {
let d6 = GKRandomDistribution.d6()
var dicedInt = d6.nextInt()
// if dicedInt > 4 {
// dicedInt = 4
// }
self.diced = "\(dicedInt)"
self.dicing.toggle()
if self.dicing == true {
self.btnName = "Done"
} else {
self.btnName = "Rool it"
}
}) {
Text(self.btnName).font(.largeTitle)
}
Spacer()
if self.dicing == true {
startAnimation()
} else {
Image(self.diced)
.resizable()
.aspectRatio(contentMode: .fit)
}
}
}
上記のコードの中にコメントアウトの部分があるかと思われますが、その箇所をアンコメントすると「イカサマのダイス」の出来上がりです。実はロジックは簡単です。dicedIntを一定の基準に従って上書きしてしまおうということです。
例として4以上の出目は全て4にするという上書き操作です。
これにより以下のことが成立します。
- このサイコロでは5と6は出ない
- 50%の確率で4が出る
- 1~3の出る確率はそれぞれ等しい
これだけ先に知っているとゲーム必勝間違いなしですね^^
こんな感じで開発者の特権を駆使して手品などにご活用ください。
ソースコードはYouTubeのコメント欄に記載します。
目次へ戻る